Merge pull request #3827 from vieux/mova_api_package

Move api into sub package
This commit is contained in:
Michael Crosby 2014-01-31 15:39:33 -08:00
commit 6a1ee89d2d
12 changed files with 209 additions and 217 deletions

View file

@ -1,4 +1,4 @@
package docker
package api
import (
"bufio"
@ -34,7 +34,11 @@ const (
DEFAULTUNIXSOCKET = "/var/run/docker.sock"
)
type HttpApiFunc func(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error
type HttpApiFunc func(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error
func init() {
engine.Register("serveapi", ServeApi)
}
func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
conn, _, err := w.(http.Hijacker).Hijack()
@ -106,7 +110,20 @@ func getBoolParam(value string) (bool, error) {
return ret, nil
}
func matchesContentType(contentType, expectedType string) bool {
//TODO remove, used on < 1.5 in getContainersJSON
func displayablePorts(ports *engine.Table) string {
result := []string{}
for _, port := range ports.Data {
if port.Get("IP") == "" {
result = append(result, fmt.Sprintf("%d/%s", port.GetInt("PublicPort"), port.Get("Type")))
} else {
result = append(result, fmt.Sprintf("%s:%d->%d/%s", port.Get("IP"), port.GetInt("PublicPort"), port.GetInt("PrivatePort"), port.Get("Type")))
}
}
return strings.Join(result, ", ")
}
func MatchesContentType(contentType, expectedType string) bool {
mimetype, _, err := mime.ParseMediaType(contentType)
if err != nil {
utils.Errorf("Error parsing media type: %s error: %s", contentType, err.Error())
@ -114,10 +131,10 @@ func matchesContentType(contentType, expectedType string) bool {
return err == nil && mimetype == expectedType
}
func postAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postAuth(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
var (
authConfig, err = ioutil.ReadAll(r.Body)
job = srv.Eng.Job("auth")
job = eng.Job("auth")
status string
)
if err != nil {
@ -137,20 +154,20 @@ func postAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Reque
return nil
}
func getVersion(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getVersion(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
w.Header().Set("Content-Type", "application/json")
srv.Eng.ServeHTTP(w, r)
eng.ServeHTTP(w, r)
return nil
}
func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postContainersKill(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
if err := parseForm(r); err != nil {
return err
}
job := srv.Eng.Job("kill", vars["name"])
job := eng.Job("kill", vars["name"])
if sig := r.Form.Get("signal"); sig != "" {
job.Args = append(job.Args, sig)
}
@ -161,11 +178,11 @@ func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r *
return nil
}
func getContainersExport(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getContainersExport(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
job := srv.Eng.Job("export", vars["name"])
job := eng.Job("export", vars["name"])
job.Stdout.Add(w)
if err := job.Run(); err != nil {
return err
@ -173,7 +190,7 @@ func getContainersExport(srv *Server, version float64, w http.ResponseWriter, r
return nil
}
func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getImagesJSON(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
@ -181,7 +198,7 @@ func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http.
var (
err error
outs *engine.Table
job = srv.Eng.Job("images")
job = eng.Job("images")
)
job.Setenv("filter", r.Form.Get("filter"))
@ -219,39 +236,39 @@ func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http.
return nil
}
func getImagesViz(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getImagesViz(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if version > 1.6 {
w.WriteHeader(http.StatusNotFound)
return fmt.Errorf("This is now implemented in the client.")
}
srv.Eng.ServeHTTP(w, r)
eng.ServeHTTP(w, r)
return nil
}
func getInfo(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getInfo(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
w.Header().Set("Content-Type", "application/json")
srv.Eng.ServeHTTP(w, r)
eng.ServeHTTP(w, r)
return nil
}
func getEvents(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getEvents(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
w.Header().Set("Content-Type", "application/json")
var job = srv.Eng.Job("events", r.RemoteAddr)
var job = eng.Job("events", r.RemoteAddr)
job.Stdout.Add(utils.NewWriteFlusher(w))
job.Setenv("since", r.Form.Get("since"))
return job.Run()
}
func getImagesHistory(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getImagesHistory(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
var job = srv.Eng.Job("history", vars["name"])
var job = eng.Job("history", vars["name"])
job.Stdout.Add(w)
if err := job.Run(); err != nil {
@ -260,17 +277,17 @@ func getImagesHistory(srv *Server, version float64, w http.ResponseWriter, r *ht
return nil
}
func getContainersChanges(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getContainersChanges(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
var job = srv.Eng.Job("changes", vars["name"])
var job = eng.Job("changes", vars["name"])
job.Stdout.Add(w)
return job.Run()
}
func getContainersTop(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getContainersTop(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if version < 1.4 {
return fmt.Errorf("top was improved a lot since 1.3, Please upgrade your docker client.")
}
@ -281,19 +298,19 @@ func getContainersTop(srv *Server, version float64, w http.ResponseWriter, r *ht
return err
}
job := srv.Eng.Job("top", vars["name"], r.Form.Get("ps_args"))
job := eng.Job("top", vars["name"], r.Form.Get("ps_args"))
job.Stdout.Add(w)
return job.Run()
}
func getContainersJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getContainersJSON(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
var (
err error
outs *engine.Table
job = srv.Eng.Job("containers")
job = eng.Job("containers")
)
job.Setenv("all", r.Form.Get("all"))
@ -323,7 +340,7 @@ func getContainersJSON(srv *Server, version float64, w http.ResponseWriter, r *h
return nil
}
func postImagesTag(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postImagesTag(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
@ -331,7 +348,7 @@ func postImagesTag(srv *Server, version float64, w http.ResponseWriter, r *http.
return fmt.Errorf("Missing parameter")
}
job := srv.Eng.Job("tag", vars["name"], r.Form.Get("repo"), r.Form.Get("tag"))
job := eng.Job("tag", vars["name"], r.Form.Get("repo"), r.Form.Get("tag"))
job.Setenv("force", r.Form.Get("force"))
if err := job.Run(); err != nil {
return err
@ -340,14 +357,14 @@ func postImagesTag(srv *Server, version float64, w http.ResponseWriter, r *http.
return nil
}
func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postCommit(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
var (
config engine.Env
env engine.Env
job = srv.Eng.Job("commit", r.Form.Get("container"))
job = eng.Job("commit", r.Form.Get("container"))
)
if err := config.Import(r.Body); err != nil {
utils.Errorf("%s", err)
@ -369,7 +386,7 @@ func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Req
}
// Creates an image from Pull or from Import
func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postImagesCreate(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
@ -399,12 +416,12 @@ func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *ht
metaHeaders[k] = v
}
}
job = srv.Eng.Job("pull", r.Form.Get("fromImage"), tag)
job = eng.Job("pull", r.Form.Get("fromImage"), tag)
job.SetenvBool("parallel", version > 1.3)
job.SetenvJson("metaHeaders", metaHeaders)
job.SetenvJson("authConfig", authConfig)
} else { //import
job = srv.Eng.Job("import", r.Form.Get("fromSrc"), r.Form.Get("repo"), tag)
job = eng.Job("import", r.Form.Get("fromSrc"), r.Form.Get("repo"), tag)
job.Stdin.Add(r.Body)
}
@ -421,7 +438,7 @@ func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *ht
return nil
}
func getImagesSearch(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getImagesSearch(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
@ -445,7 +462,7 @@ func getImagesSearch(srv *Server, version float64, w http.ResponseWriter, r *htt
}
}
var job = srv.Eng.Job("search", r.Form.Get("term"))
var job = eng.Job("search", r.Form.Get("term"))
job.SetenvJson("metaHeaders", metaHeaders)
job.SetenvJson("authConfig", authConfig)
job.Stdout.Add(w)
@ -453,7 +470,7 @@ func getImagesSearch(srv *Server, version float64, w http.ResponseWriter, r *htt
return job.Run()
}
func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postImagesInsert(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
@ -464,7 +481,7 @@ func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *ht
w.Header().Set("Content-Type", "application/json")
}
job := srv.Eng.Job("insert", vars["name"], r.Form.Get("url"), r.Form.Get("path"))
job := 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 {
@ -478,7 +495,7 @@ func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *ht
return nil
}
func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postImagesPush(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
@ -512,7 +529,7 @@ func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http
if version > 1.0 {
w.Header().Set("Content-Type", "application/json")
}
job := srv.Eng.Job("push", vars["name"])
job := eng.Job("push", vars["name"])
job.SetenvJson("metaHeaders", metaHeaders)
job.SetenvJson("authConfig", authConfig)
job.SetenvBool("json", version > 1.0)
@ -528,31 +545,31 @@ func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http
return nil
}
func getImagesGet(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getImagesGet(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
if version > 1.0 {
w.Header().Set("Content-Type", "application/x-tar")
}
job := srv.Eng.Job("image_export", vars["name"])
job := eng.Job("image_export", vars["name"])
job.Stdout.Add(w)
return job.Run()
}
func postImagesLoad(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
job := srv.Eng.Job("load")
func postImagesLoad(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
job := eng.Job("load")
job.Stdin.Add(r.Body)
return job.Run()
}
func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postContainersCreate(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return nil
}
var (
out engine.Env
job = srv.Eng.Job("create", r.Form.Get("name"))
job = eng.Job("create", r.Form.Get("name"))
outWarnings []string
outId string
warnings = bytes.NewBuffer(nil)
@ -577,14 +594,14 @@ func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r
return writeJSON(w, http.StatusCreated, out)
}
func postContainersRestart(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postContainersRestart(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
job := srv.Eng.Job("restart", vars["name"])
job := eng.Job("restart", vars["name"])
job.Setenv("t", r.Form.Get("t"))
if err := job.Run(); err != nil {
return err
@ -593,14 +610,14 @@ func postContainersRestart(srv *Server, version float64, w http.ResponseWriter,
return nil
}
func deleteContainers(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func deleteContainers(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
job := srv.Eng.Job("container_delete", vars["name"])
job := eng.Job("container_delete", vars["name"])
job.Setenv("removeVolume", r.Form.Get("v"))
job.Setenv("removeLink", r.Form.Get("link"))
if err := job.Run(); err != nil {
@ -610,29 +627,29 @@ func deleteContainers(srv *Server, version float64, w http.ResponseWriter, r *ht
return nil
}
func deleteImages(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func deleteImages(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
var job = srv.Eng.Job("image_delete", vars["name"])
var job = eng.Job("image_delete", vars["name"])
job.Stdout.Add(w)
job.SetenvBool("autoPrune", version > 1.1)
return job.Run()
}
func postContainersStart(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postContainersStart(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
job := srv.Eng.Job("start", name)
job := eng.Job("start", name)
// allow a nil body for backwards compatibility
if r.Body != nil {
if matchesContentType(r.Header.Get("Content-Type"), "application/json") {
if MatchesContentType(r.Header.Get("Content-Type"), "application/json") {
if err := job.DecodeEnv(r.Body); err != nil {
return err
}
@ -645,14 +662,14 @@ func postContainersStart(srv *Server, version float64, w http.ResponseWriter, r
return nil
}
func postContainersStop(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postContainersStop(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
job := srv.Eng.Job("stop", vars["name"])
job := eng.Job("stop", vars["name"])
job.Setenv("t", r.Form.Get("t"))
if err := job.Run(); err != nil {
return err
@ -661,14 +678,14 @@ func postContainersStop(srv *Server, version float64, w http.ResponseWriter, r *
return nil
}
func postContainersWait(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postContainersWait(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
var (
env engine.Env
status string
job = srv.Eng.Job("wait", vars["name"])
job = eng.Job("wait", vars["name"])
)
job.Stdout.AddString(&status)
if err := job.Run(); err != nil {
@ -683,20 +700,20 @@ func postContainersWait(srv *Server, version float64, w http.ResponseWriter, r *
return writeJSON(w, http.StatusOK, env)
}
func postContainersResize(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postContainersResize(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
if err := srv.Eng.Job("resize", vars["name"], r.Form.Get("h"), r.Form.Get("w")).Run(); err != nil {
if err := eng.Job("resize", vars["name"], r.Form.Get("h"), r.Form.Get("w")).Run(); err != nil {
return err
}
return nil
}
func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postContainersAttach(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
@ -705,7 +722,7 @@ func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r
}
var (
job = srv.Eng.Job("inspect", vars["name"], "container")
job = eng.Job("inspect", vars["name"], "container")
c, err = job.Stdout.AddEnv()
)
if err != nil {
@ -745,7 +762,7 @@ func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r
errStream = outStream
}
job = srv.Eng.Job("attach", vars["name"])
job = eng.Job("attach", vars["name"])
job.Setenv("logs", r.Form.Get("logs"))
job.Setenv("stream", r.Form.Get("stream"))
job.Setenv("stdin", r.Form.Get("stdin"))
@ -761,7 +778,7 @@ func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r
return nil
}
func wsContainersAttach(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func wsContainersAttach(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
@ -769,13 +786,13 @@ func wsContainersAttach(srv *Server, version float64, w http.ResponseWriter, r *
return fmt.Errorf("Missing parameter")
}
if err := srv.Eng.Job("inspect", vars["name"], "container").Run(); err != nil {
if err := eng.Job("inspect", vars["name"], "container").Run(); err != nil {
return err
}
h := websocket.Handler(func(ws *websocket.Conn) {
defer ws.Close()
job := srv.Eng.Job("attach", vars["name"])
job := eng.Job("attach", vars["name"])
job.Setenv("logs", r.Form.Get("logs"))
job.Setenv("stream", r.Form.Get("stream"))
job.Setenv("stdin", r.Form.Get("stdin"))
@ -793,27 +810,27 @@ func wsContainersAttach(srv *Server, version float64, w http.ResponseWriter, r *
return nil
}
func getContainersByName(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getContainersByName(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
var job = srv.Eng.Job("inspect", vars["name"], "container")
var job = eng.Job("inspect", vars["name"], "container")
job.Stdout.Add(w)
job.SetenvBool("conflict", true) //conflict=true to detect conflict between containers and images in the job
return job.Run()
}
func getImagesByName(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func getImagesByName(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
var job = srv.Eng.Job("inspect", vars["name"], "image")
var job = eng.Job("inspect", vars["name"], "image")
job.Stdout.Add(w)
job.SetenvBool("conflict", true) //conflict=true to detect conflict between containers and images in the job
return job.Run()
}
func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postBuild(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if version < 1.3 {
return fmt.Errorf("Multipart upload for build is no longer supported. Please upgrade your docker client.")
}
@ -822,7 +839,7 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
authConfig = &auth.AuthConfig{}
configFileEncoded = r.Header.Get("X-Registry-Config")
configFile = &auth.ConfigFile{}
job = srv.Eng.Job("build")
job = eng.Job("build")
)
// This block can be removed when API versions prior to 1.9 are deprecated.
@ -870,7 +887,7 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
return nil
}
func postContainersCopy(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func postContainersCopy(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
@ -892,7 +909,7 @@ func postContainersCopy(srv *Server, version float64, w http.ResponseWriter, r *
copyData.Set("Resource", copyData.Get("Resource")[1:])
}
job := srv.Eng.Job("container_copy", vars["name"], copyData.Get("Resource"))
job := eng.Job("container_copy", vars["name"], copyData.Get("Resource"))
job.Stdout.Add(w)
if err := job.Run(); err != nil {
utils.Errorf("%s", err.Error())
@ -900,7 +917,7 @@ func postContainersCopy(srv *Server, version float64, w http.ResponseWriter, r *
return nil
}
func optionsHandler(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func optionsHandler(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
w.WriteHeader(http.StatusOK)
return nil
}
@ -910,7 +927,7 @@ func writeCorsHeaders(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
}
func makeHttpHandler(srv *Server, logging bool, localMethod string, localRoute string, handlerFunc HttpApiFunc, enableCors bool) http.HandlerFunc {
func makeHttpHandler(eng *engine.Engine, logging bool, localMethod string, localRoute string, handlerFunc HttpApiFunc, enableCors bool, dockerVersion string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// log the request
utils.Debugf("Calling %s %s", localMethod, localRoute)
@ -921,8 +938,8 @@ func makeHttpHandler(srv *Server, logging bool, localMethod string, localRoute s
if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") {
userAgent := strings.Split(r.Header.Get("User-Agent"), "/")
if len(userAgent) == 2 && userAgent[1] != VERSION {
utils.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], VERSION)
if len(userAgent) == 2 && userAgent[1] != dockerVersion {
utils.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], dockerVersion)
}
}
version, err := strconv.ParseFloat(mux.Vars(r)["version"], 64)
@ -938,7 +955,7 @@ func makeHttpHandler(srv *Server, logging bool, localMethod string, localRoute s
return
}
if err := handlerFunc(srv, version, w, r, mux.Vars(r)); err != nil {
if err := handlerFunc(eng, version, w, r, mux.Vars(r)); err != nil {
utils.Errorf("Error: %s", err)
httpError(w, err)
}
@ -971,7 +988,7 @@ func AttachProfiler(router *mux.Router) {
router.HandleFunc("/debug/pprof/threadcreate", pprof.Handler("threadcreate").ServeHTTP)
}
func createRouter(srv *Server, logging, enableCors bool) (*mux.Router, error) {
func createRouter(eng *engine.Engine, logging, enableCors bool, dockerVersion string) (*mux.Router, error) {
r := mux.NewRouter()
if os.Getenv("DEBUG") != "" {
AttachProfiler(r)
@ -1032,7 +1049,7 @@ func createRouter(srv *Server, logging, enableCors bool) (*mux.Router, error) {
localMethod := method
// build the handler function
f := makeHttpHandler(srv, logging, localMethod, localRoute, localFct, enableCors)
f := makeHttpHandler(eng, logging, localMethod, localRoute, localFct, enableCors, dockerVersion)
// add the new route
if localRoute == "" {
@ -1050,8 +1067,8 @@ func createRouter(srv *Server, logging, enableCors bool) (*mux.Router, error) {
// ServeRequest processes a single http request to the docker remote api.
// FIXME: refactor this to be part of Server and not require re-creating a new
// router each time. This requires first moving ListenAndServe into Server.
func ServeRequest(srv *Server, apiversion float64, w http.ResponseWriter, req *http.Request) error {
router, err := createRouter(srv, false, true)
func ServeRequest(eng *engine.Engine, apiversion float64, w http.ResponseWriter, req *http.Request) error {
router, err := createRouter(eng, false, true, "")
if err != nil {
return err
}
@ -1093,8 +1110,8 @@ func ServeFd(addr string, handle http.Handler) error {
// ListenAndServe sets up the required http.Server and gets it listening for
// each addr passed in and does protocol specific checking.
func ListenAndServe(proto, addr string, srv *Server, logging, enableCors bool) error {
r, err := createRouter(srv, logging, enableCors)
func ListenAndServe(proto, addr string, eng *engine.Engine, logging, enableCors bool, dockerVersion string) error {
r, err := createRouter(eng, logging, enableCors, dockerVersion)
if err != nil {
return err
}
@ -1147,3 +1164,30 @@ func ListenAndServe(proto, addr string, srv *Server, logging, enableCors bool) e
httpSrv := http.Server{Addr: addr, Handler: r}
return httpSrv.Serve(l)
}
// ServeApi loops through all of the protocols sent in to docker and spawns
// off a go routine to setup a serving http.Server for each.
func ServeApi(job *engine.Job) engine.Status {
protoAddrs := job.Args
chErrors := make(chan error, len(protoAddrs))
for _, protoAddr := range protoAddrs {
protoAddrParts := strings.SplitN(protoAddr, "://", 2)
go func() {
log.Printf("Listening for HTTP on %s (%s)\n", protoAddrParts[0], protoAddrParts[1])
chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("Version"))
}()
}
for i := 0; i < len(protoAddrs); i += 1 {
err := <-chErrors
if err != nil {
return job.Error(err)
}
}
// Tell the init daemon we are accepting requests
go systemd.SdNotify("READY=1")
return engine.StatusOK
}

View file

@ -1,4 +1,4 @@
package docker
package api
import (
"fmt"
@ -7,6 +7,20 @@ import (
"testing"
)
func TestJsonContentType(t *testing.T) {
if !MatchesContentType("application/json", "application/json") {
t.Fail()
}
if !MatchesContentType("application/json; charset=utf-8", "application/json") {
t.Fail()
}
if MatchesContentType("dockerapplication/json", "application/json") {
t.Fail()
}
}
func TestGetBoolParam(t *testing.T) {
if ret, err := getBoolParam("true"); err != nil || !ret {
t.Fatalf("true -> true, nil | got %t %s", ret, err)

View file

@ -1,19 +0,0 @@
package docker
import (
"testing"
)
func TestJsonContentType(t *testing.T) {
if !matchesContentType("application/json", "application/json") {
t.Fail()
}
if !matchesContentType("application/json; charset=utf-8", "application/json") {
t.Fail()
}
if matchesContentType("dockerapplication/json", "application/json") {
t.Fail()
}
}

View file

@ -8,6 +8,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/auth"
"github.com/dotcloud/docker/engine"
@ -79,7 +80,7 @@ func (cli *DockerCli) CmdHelp(args ...string) error {
return nil
}
}
help := fmt.Sprintf("Usage: docker [OPTIONS] COMMAND [arg...]\n -H=[unix://%s]: tcp://host:port to bind/connect to or unix://path/to/socket to use\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n", DEFAULTUNIXSOCKET)
help := fmt.Sprintf("Usage: docker [OPTIONS] COMMAND [arg...]\n -H=[unix://%s]: tcp://host:port to bind/connect to or unix://path/to/socket to use\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n", api.DEFAULTUNIXSOCKET)
for _, command := range [][]string{
{"attach", "Attach to a running container"},
{"build", "Build a container from a Dockerfile"},
@ -2283,7 +2284,7 @@ func (cli *DockerCli) call(method, path string, data interface{}, passAuthInfo b
re := regexp.MustCompile("/+")
path = re.ReplaceAllString(path, "/")
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), params)
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", api.APIVERSION, path), params)
if err != nil {
return nil, -1, err
}
@ -2360,7 +2361,7 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer, h
re := regexp.MustCompile("/+")
path = re.ReplaceAllString(path, "/")
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), in)
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", api.APIVERSION, path), in)
if err != nil {
return err
}
@ -2405,7 +2406,7 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer, h
return fmt.Errorf("Error: %s", bytes.TrimSpace(body))
}
if matchesContentType(resp.Header.Get("Content-Type"), "application/json") {
if api.MatchesContentType(resp.Header.Get("Content-Type"), "application/json") {
return utils.DisplayJSONMessagesStream(resp.Body, out, cli.terminalFd, cli.isTerminal)
}
if _, err := io.Copy(out, resp.Body); err != nil {
@ -2424,7 +2425,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
re := regexp.MustCompile("/+")
path = re.ReplaceAllString(path, "/")
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), nil)
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", api.APIVERSION, path), nil)
if err != nil {
return err
}

View file

@ -3,6 +3,7 @@ package main
import (
"fmt"
"github.com/dotcloud/docker"
"github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/engine"
flag "github.com/dotcloud/docker/pkg/mflag"
"github.com/dotcloud/docker/sysinit"
@ -57,7 +58,7 @@ func main() {
if defaultHost == "" || *flDaemon {
// If we do not have a host, default to unix socket
defaultHost = fmt.Sprintf("unix://%s", docker.DEFAULTUNIXSOCKET)
defaultHost = fmt.Sprintf("unix://%s", api.DEFAULTUNIXSOCKET)
}
flHosts.Set(defaultHost)
}
@ -82,7 +83,7 @@ func main() {
log.Fatal(err)
}
// Load plugin: httpapi
job := eng.Job("initapi")
job := eng.Job("initserver")
job.Setenv("Pidfile", *pidfile)
job.Setenv("Root", *flRoot)
job.SetenvBool("AutoRestart", *flAutoRestart)
@ -102,6 +103,7 @@ func main() {
job = eng.Job("serveapi", flHosts.GetAll()...)
job.SetenvBool("Logging", true)
job.SetenvBool("EnableCors", *flEnableCors)
job.Setenv("Version", VERSION)
if err := job.Run(); err != nil {
log.Fatal(err)
}

View file

@ -7,6 +7,7 @@ import (
"encoding/json"
"fmt"
"github.com/dotcloud/docker"
"github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/utils"
"io"
@ -21,7 +22,6 @@ import (
func TestGetVersion(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
var err error
r := httptest.NewRecorder()
@ -31,7 +31,7 @@ func TestGetVersion(t *testing.T) {
t.Fatal(err)
}
// FIXME getting the version should require an actual running Server
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -58,7 +58,6 @@ func TestGetVersion(t *testing.T) {
func TestGetInfo(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
job := eng.Job("images")
initialImages, err := job.Stdout.AddListTable()
@ -74,7 +73,7 @@ func TestGetInfo(t *testing.T) {
}
r := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -122,7 +121,7 @@ func TestGetEvents(t *testing.T) {
r := httptest.NewRecorder()
setTimeout(t, "", 500*time.Millisecond, func() {
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -146,7 +145,6 @@ func TestGetEvents(t *testing.T) {
func TestGetImagesJSON(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
job := eng.Job("images")
initialImages, err := job.Stdout.AddListTable()
@ -164,7 +162,7 @@ func TestGetImagesJSON(t *testing.T) {
r := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -199,7 +197,7 @@ func TestGetImagesJSON(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r2, req2); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r2, req2); err != nil {
t.Fatal(err)
}
assertHttpNotError(r2, t)
@ -232,7 +230,7 @@ func TestGetImagesJSON(t *testing.T) {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r3, req3); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r3, req3); err != nil {
t.Fatal(err)
}
assertHttpNotError(r3, t)
@ -250,7 +248,6 @@ func TestGetImagesJSON(t *testing.T) {
func TestGetImagesHistory(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
r := httptest.NewRecorder()
@ -258,7 +255,7 @@ func TestGetImagesHistory(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -275,7 +272,6 @@ func TestGetImagesHistory(t *testing.T) {
func TestGetImagesByName(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
req, err := http.NewRequest("GET", "/images/"+unitTestImageName+"/json", nil)
if err != nil {
@ -283,7 +279,7 @@ func TestGetImagesByName(t *testing.T) {
}
r := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -300,7 +296,6 @@ func TestGetImagesByName(t *testing.T) {
func TestGetContainersJSON(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
job := eng.Job("containers")
job.SetenvBool("all", true)
@ -328,7 +323,7 @@ func TestGetContainersJSON(t *testing.T) {
}
r := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -347,7 +342,6 @@ func TestGetContainersJSON(t *testing.T) {
func TestGetContainersExport(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
// Create a container and remove a file
containerID := createTestContainer(eng,
@ -365,7 +359,7 @@ func TestGetContainersExport(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -396,7 +390,6 @@ func TestGetContainersExport(t *testing.T) {
func TestGetContainersChanges(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
// Create a container and remove a file
containerID := createTestContainer(eng,
@ -413,7 +406,7 @@ func TestGetContainersChanges(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -437,7 +430,6 @@ func TestGetContainersChanges(t *testing.T) {
func TestGetContainersTop(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
containerID := createTestContainer(eng,
&docker.Config{
@ -481,7 +473,7 @@ func TestGetContainersTop(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -514,7 +506,6 @@ func TestGetContainersTop(t *testing.T) {
func TestGetContainersByName(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
// Create a container and remove a file
containerID := createTestContainer(eng,
@ -530,7 +521,7 @@ func TestGetContainersByName(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -565,7 +556,7 @@ func TestPostCommit(t *testing.T) {
}
r := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -585,7 +576,6 @@ func TestPostCommit(t *testing.T) {
func TestPostContainersCreate(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
configJSON, err := json.Marshal(&docker.Config{
Image: unitTestImageID,
@ -602,7 +592,7 @@ func TestPostContainersCreate(t *testing.T) {
}
r := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -627,7 +617,6 @@ func TestPostContainersCreate(t *testing.T) {
func TestPostContainersKill(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
containerID := createTestContainer(eng,
&docker.Config{
@ -652,7 +641,7 @@ func TestPostContainersKill(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -667,7 +656,6 @@ func TestPostContainersKill(t *testing.T) {
func TestPostContainersRestart(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
containerID := createTestContainer(eng,
&docker.Config{
@ -692,7 +680,7 @@ func TestPostContainersRestart(t *testing.T) {
t.Fatal(err)
}
r := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -713,7 +701,6 @@ func TestPostContainersRestart(t *testing.T) {
func TestPostContainersStart(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
containerID := createTestContainer(
eng,
@ -735,7 +722,7 @@ func TestPostContainersStart(t *testing.T) {
req.Header.Set("Content-Type", "application/json")
r := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -752,7 +739,7 @@ func TestPostContainersStart(t *testing.T) {
}
r = httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
// Starting an already started container should return an error
@ -767,7 +754,6 @@ func TestPostContainersStart(t *testing.T) {
func TestRunErrorBindMountRootSource(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
containerID := createTestContainer(
eng,
@ -791,7 +777,7 @@ func TestRunErrorBindMountRootSource(t *testing.T) {
req.Header.Set("Content-Type", "application/json")
r := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
if r.Code != http.StatusInternalServerError {
@ -803,7 +789,6 @@ func TestRunErrorBindMountRootSource(t *testing.T) {
func TestPostContainersStop(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
containerID := createTestContainer(eng,
&docker.Config{
@ -829,7 +814,7 @@ func TestPostContainersStop(t *testing.T) {
t.Fatal(err)
}
r := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -844,7 +829,6 @@ func TestPostContainersStop(t *testing.T) {
func TestPostContainersWait(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
containerID := createTestContainer(eng,
&docker.Config{
@ -862,7 +846,7 @@ func TestPostContainersWait(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -883,7 +867,6 @@ func TestPostContainersWait(t *testing.T) {
func TestPostContainersAttach(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
containerID := createTestContainer(eng,
&docker.Config{
@ -921,7 +904,7 @@ func TestPostContainersAttach(t *testing.T) {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r.ResponseRecorder, t)
@ -962,7 +945,6 @@ func TestPostContainersAttach(t *testing.T) {
func TestPostContainersAttachStderr(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
containerID := createTestContainer(eng,
&docker.Config{
@ -1000,7 +982,7 @@ func TestPostContainersAttachStderr(t *testing.T) {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r.ResponseRecorder, t)
@ -1044,7 +1026,6 @@ func TestPostContainersAttachStderr(t *testing.T) {
func TestDeleteContainers(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
containerID := createTestContainer(eng,
&docker.Config{
@ -1058,7 +1039,7 @@ func TestDeleteContainers(t *testing.T) {
t.Fatal(err)
}
r := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -1071,13 +1052,13 @@ func TestDeleteContainers(t *testing.T) {
func TestOptionsRoute(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
r := httptest.NewRecorder()
req, err := http.NewRequest("OPTIONS", "/", nil)
if err != nil {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -1089,14 +1070,14 @@ func TestOptionsRoute(t *testing.T) {
func TestGetEnabledCors(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
r := httptest.NewRecorder()
req, err := http.NewRequest("GET", "/version", nil)
if err != nil {
t.Fatal(err)
}
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -1122,7 +1103,6 @@ func TestGetEnabledCors(t *testing.T) {
func TestDeleteImages(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
initialImages := getImages(eng, t, true, "")
@ -1142,7 +1122,7 @@ func TestDeleteImages(t *testing.T) {
}
r := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
if r.Code != http.StatusConflict {
@ -1155,7 +1135,7 @@ func TestDeleteImages(t *testing.T) {
}
r2 := httptest.NewRecorder()
if err := docker.ServeRequest(srv, docker.APIVERSION, r2, req2); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r2, req2); err != nil {
t.Fatal(err)
}
assertHttpNotError(r2, t)
@ -1180,7 +1160,6 @@ func TestDeleteImages(t *testing.T) {
func TestPostContainersCopy(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
// Create a container and remove a file
containerID := createTestContainer(eng,
@ -1208,7 +1187,7 @@ func TestPostContainersCopy(t *testing.T) {
t.Fatal(err)
}
req.Header.Add("Content-Type", "application/json")
if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)

View file

@ -61,7 +61,7 @@ func cleanup(eng *engine.Engine, t *testing.T) error {
}
for _, image := range images.Data {
if image.Get("Id") != unitTestImageID {
mkServerFromEngine(eng, t).DeleteImage(image.Get("Id"), false)
eng.Job("image_delete", image.Get("Id")).Run()
}
}
return nil
@ -125,17 +125,18 @@ func setupBaseImage() {
if err != nil {
log.Fatalf("Can't initialize engine at %s: %s", unitTestStoreBase, err)
}
job := eng.Job("initapi")
job := eng.Job("initserver")
job.Setenv("Root", unitTestStoreBase)
job.SetenvBool("Autorestart", false)
job.Setenv("BridgeIface", unitTestNetworkBridge)
if err := job.Run(); err != nil {
log.Fatalf("Unable to create a runtime for tests: %s", err)
}
srv := mkServerFromEngine(eng, log.New(os.Stderr, "", 0))
job = eng.Job("inspect", unitTestImageName, "image")
img, _ := job.Stdout.AddEnv()
// If the unit test is not found, try to download it.
if img, err := srv.ImageInspect(unitTestImageName); err != nil || img.ID != unitTestImageID {
if err := job.Run(); err != nil || img.Get("id") != unitTestImageID {
// Retrieve the Image
job = eng.Job("pull", unitTestImageName)
job.Stdout.Add(utils.NopWriteCloser(os.Stdout))
@ -572,7 +573,7 @@ func TestRestore(t *testing.T) {
if err != nil {
t.Fatal(err)
}
job := eng.Job("initapi")
job := eng.Job("initserver")
job.Setenv("Root", eng.Root())
job.SetenvBool("Autorestart", false)
if err := job.Run(); err != nil {
@ -604,7 +605,7 @@ func TestRestore(t *testing.T) {
}
func TestReloadContainerLinks(t *testing.T) {
// FIXME: here we don't use NewTestEngine because it calls initapi with Autorestart=false,
// FIXME: here we don't use NewTestEngine because it calls initserver with Autorestart=false,
// and we want to set it to true.
root, err := newTestDirectory(unitTestStoreBase)
if err != nil {
@ -614,7 +615,7 @@ func TestReloadContainerLinks(t *testing.T) {
if err != nil {
t.Fatal(err)
}
job := eng.Job("initapi")
job := eng.Job("initserver")
job.Setenv("Root", eng.Root())
job.SetenvBool("Autorestart", true)
if err := job.Run(); err != nil {
@ -664,7 +665,7 @@ func TestReloadContainerLinks(t *testing.T) {
if err != nil {
t.Fatal(err)
}
job = eng.Job("initapi")
job = eng.Job("initserver")
job.Setenv("Root", eng.Root())
job.SetenvBool("Autorestart", false)
if err := job.Run(); err != nil {

View file

@ -262,7 +262,7 @@ func TestRestartKillWait(t *testing.T) {
t.Fatal(err)
}
job = eng.Job("initapi")
job = eng.Job("initserver")
job.Setenv("Root", eng.Root())
job.SetenvBool("AutoRestart", false)
// TestGetEnabledCors and TestOptionsRoute require EnableCors=true

View file

@ -1,7 +1,7 @@
package docker
import (
"github.com/dotcloud/docker"
"github.com/dotcloud/docker/engine"
"testing"
"time"
)
@ -9,9 +9,8 @@ import (
func TestServerListOrderedImagesByCreationDate(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
if err := generateImage("", srv); err != nil {
if err := generateImage("", eng); err != nil {
t.Fatal(err)
}
@ -25,16 +24,15 @@ func TestServerListOrderedImagesByCreationDate(t *testing.T) {
func TestServerListOrderedImagesByCreationDateAndTag(t *testing.T) {
eng := NewTestEngine(t)
defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
err := generateImage("bar", srv)
err := generateImage("bar", eng)
if err != nil {
t.Fatal(err)
}
time.Sleep(time.Second)
err = generateImage("zed", srv)
err = generateImage("zed", eng)
if err != nil {
t.Fatal(err)
}
@ -46,12 +44,12 @@ func TestServerListOrderedImagesByCreationDateAndTag(t *testing.T) {
}
}
func generateImage(name string, srv *docker.Server) error {
func generateImage(name string, eng *engine.Engine) error {
archive, err := fakeTar()
if err != nil {
return err
}
job := srv.Eng.Job("import", "-", "repo", name)
job := eng.Job("import", "-", "repo", name)
job.Stdin.Add(archive)
job.SetenvBool("json", true)
return job.Run()

View file

@ -188,7 +188,7 @@ func NewTestEngine(t utils.Fataler) *engine.Engine {
}
// Load default plugins
// (This is manually copied and modified from main() until we have a more generic plugin system)
job := eng.Job("initapi")
job := eng.Job("initserver")
job.Setenv("Root", root)
job.SetenvBool("AutoRestart", false)
// TestGetEnabledCors and TestOptionsRoute require EnableCors=true

View file

@ -2,6 +2,7 @@ package docker
import (
"fmt"
"github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/utils"
"os"
"path/filepath"
@ -129,7 +130,7 @@ func ValidateEnv(val string) (string, error) {
}
func ValidateHost(val string) (string, error) {
host, err := utils.ParseHost(DEFAULTHTTPHOST, DEFAULTHTTPPORT, DEFAULTUNIXSOCKET, val)
host, err := utils.ParseHost(api.DEFAULTHTTPHOST, api.DEFAULTHTTPPORT, api.DEFAULTUNIXSOCKET, val)
if err != nil {
return val, err
}

View file

@ -8,7 +8,6 @@ import (
"github.com/dotcloud/docker/auth"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/pkg/graphdb"
"github.com/dotcloud/docker/pkg/systemd"
"github.com/dotcloud/docker/registry"
"github.com/dotcloud/docker/utils"
"io"
@ -34,13 +33,13 @@ func (srv *Server) Close() error {
}
func init() {
engine.Register("initapi", jobInitApi)
engine.Register("initserver", jobInitServer)
}
// jobInitApi runs the remote api server `srv` as a daemon,
// Only one api server can run at the same time - this is enforced by a pidfile.
// The signals SIGINT, SIGQUIT and SIGTERM are intercepted for cleanup.
func jobInitApi(job *engine.Job) engine.Status {
func jobInitServer(job *engine.Job) engine.Status {
job.Logf("Creating server")
srv, err := NewServer(job.Eng, DaemonConfigFromJob(job))
if err != nil {
@ -76,7 +75,6 @@ func jobInitApi(job *engine.Job) engine.Status {
"restart": srv.ContainerRestart,
"start": srv.ContainerStart,
"kill": srv.ContainerKill,
"serveapi": srv.ListenAndServe,
"wait": srv.ContainerWait,
"tag": srv.ImageTag,
"resize": srv.ContainerResize,
@ -111,33 +109,6 @@ func jobInitApi(job *engine.Job) engine.Status {
return engine.StatusOK
}
// ListenAndServe loops through all of the protocols sent in to docker and spawns
// off a go routine to setup a serving http.Server for each.
func (srv *Server) ListenAndServe(job *engine.Job) engine.Status {
protoAddrs := job.Args
chErrors := make(chan error, len(protoAddrs))
for _, protoAddr := range protoAddrs {
protoAddrParts := strings.SplitN(protoAddr, "://", 2)
go func() {
log.Printf("Listening for HTTP on %s (%s)\n", protoAddrParts[0], protoAddrParts[1])
chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], srv, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"))
}()
}
for i := 0; i < len(protoAddrs); i += 1 {
err := <-chErrors
if err != nil {
return job.Error(err)
}
}
// Tell the init daemon we are accepting requests
go systemd.SdNotify("READY=1")
return engine.StatusOK
}
// simpleVersionInfo is a simple implementation of
// the interface VersionInfo, which is used
// to provide version information for some product,