diff --git a/api/server.go b/api/server.go index 1019521e03..fc4a5c2f04 100644 --- a/api/server.go +++ b/api/server.go @@ -13,6 +13,7 @@ import ( "github.com/dotcloud/docker/pkg/listenbuffer" "github.com/dotcloud/docker/pkg/systemd" "github.com/dotcloud/docker/pkg/user" + "github.com/dotcloud/docker/pkg/version" "github.com/dotcloud/docker/utils" "github.com/gorilla/mux" "io" @@ -32,7 +33,7 @@ var ( activationLock chan struct{} ) -type HttpApiFunc func(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error +type HttpApiFunc func(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) { conn, _, err := w.(http.Hijacker).Hijack() @@ -113,7 +114,7 @@ func getBoolParam(value string) (bool, error) { return ret, nil } -func postAuth(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postAuth(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { var ( authConfig, err = ioutil.ReadAll(r.Body) job = eng.Job("auth") @@ -136,13 +137,13 @@ func postAuth(eng *engine.Engine, version string, w http.ResponseWriter, r *http return nil } -func getVersion(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getVersion(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { w.Header().Set("Content-Type", "application/json") eng.ServeHTTP(w, r) return nil } -func postContainersKill(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postContainersKill(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } @@ -160,7 +161,7 @@ func postContainersKill(eng *engine.Engine, version string, w http.ResponseWrite return nil } -func getContainersExport(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getContainersExport(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } @@ -172,7 +173,7 @@ func getContainersExport(eng *engine.Engine, version string, w http.ResponseWrit return nil } -func getImagesJSON(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getImagesJSON(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -186,7 +187,7 @@ func getImagesJSON(eng *engine.Engine, version string, w http.ResponseWriter, r job.Setenv("filter", r.Form.Get("filter")) job.Setenv("all", r.Form.Get("all")) - if utils.CompareVersion(version, "1.7") >= 0 { + if version.GreaterThanOrEqualTo("1.7") { streamJSON(job, w, false) } else if outs, err = job.Stdout.AddListTable(); err != nil { return err @@ -196,7 +197,7 @@ func getImagesJSON(eng *engine.Engine, version string, w http.ResponseWriter, r return err } - if utils.CompareVersion(version, "1.7") < 0 && outs != nil { // Convert to legacy format + if version.LessThan("1.7") && outs != nil { // Convert to legacy format outsLegacy := engine.NewTable("Created", 0) for _, out := range outs.Data { for _, repoTag := range out.GetList("RepoTags") { @@ -219,8 +220,8 @@ func getImagesJSON(eng *engine.Engine, version string, w http.ResponseWriter, r return nil } -func getImagesViz(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if utils.CompareVersion(version, "1.6") > 0 { +func getImagesViz(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { + if version.GreaterThan("1.6") { w.WriteHeader(http.StatusNotFound) return fmt.Errorf("This is now implemented in the client.") } @@ -228,13 +229,13 @@ func getImagesViz(eng *engine.Engine, version string, w http.ResponseWriter, r * return nil } -func getInfo(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getInfo(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { w.Header().Set("Content-Type", "application/json") eng.ServeHTTP(w, r) return nil } -func getEvents(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getEvents(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -245,7 +246,7 @@ func getEvents(eng *engine.Engine, version string, w http.ResponseWriter, r *htt return job.Run() } -func getImagesHistory(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getImagesHistory(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } @@ -259,7 +260,7 @@ func getImagesHistory(eng *engine.Engine, version string, w http.ResponseWriter, return nil } -func getContainersChanges(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getContainersChanges(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } @@ -269,8 +270,8 @@ func getContainersChanges(eng *engine.Engine, version string, w http.ResponseWri return job.Run() } -func getContainersTop(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if utils.CompareVersion(version, "1.4") < 0 { +func getContainersTop(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { + if version.LessThan("1.4") { return fmt.Errorf("top was improved a lot since 1.3, Please upgrade your docker client.") } if vars == nil { @@ -285,7 +286,7 @@ func getContainersTop(eng *engine.Engine, version string, w http.ResponseWriter, return job.Run() } -func getContainersJSON(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getContainersJSON(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -301,7 +302,7 @@ func getContainersJSON(eng *engine.Engine, version string, w http.ResponseWriter job.Setenv("before", r.Form.Get("before")) job.Setenv("limit", r.Form.Get("limit")) - if utils.CompareVersion(version, "1.5") >= 0 { + if version.GreaterThanOrEqualTo("1.5") { streamJSON(job, w, false) } else if outs, err = job.Stdout.AddTable(); err != nil { return err @@ -309,7 +310,7 @@ func getContainersJSON(eng *engine.Engine, version string, w http.ResponseWriter if err = job.Run(); err != nil { return err } - if utils.CompareVersion(version, "1.5") < 0 { // Convert to legacy format + if version.LessThan("1.5") { // Convert to legacy format for _, out := range outs.Data { ports := engine.NewTable("", 0) ports.ReadListFrom([]byte(out.Get("Ports"))) @@ -323,7 +324,7 @@ func getContainersJSON(eng *engine.Engine, version string, w http.ResponseWriter return nil } -func postImagesTag(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postImagesTag(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -340,7 +341,7 @@ func postImagesTag(eng *engine.Engine, version string, w http.ResponseWriter, r return nil } -func postCommit(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postCommit(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -369,7 +370,7 @@ func postCommit(eng *engine.Engine, version string, w http.ResponseWriter, r *ht } // Creates an image from Pull or from Import -func postImagesCreate(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postImagesCreate(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -397,7 +398,7 @@ func postImagesCreate(eng *engine.Engine, version string, w http.ResponseWriter, } } job = eng.Job("pull", r.Form.Get("fromImage"), tag) - job.SetenvBool("parallel", utils.CompareVersion(version, "1.3") > 0) + job.SetenvBool("parallel", version.GreaterThan("1.3")) job.SetenvJson("metaHeaders", metaHeaders) job.SetenvJson("authConfig", authConfig) } else { //import @@ -405,7 +406,7 @@ func postImagesCreate(eng *engine.Engine, version string, w http.ResponseWriter, job.Stdin.Add(r.Body) } - if utils.CompareVersion(version, "1.0") > 0 { + if version.GreaterThan("1.0") { job.SetenvBool("json", true) streamJSON(job, w, true) } else { @@ -415,14 +416,14 @@ func postImagesCreate(eng *engine.Engine, version string, w http.ResponseWriter, if !job.Stdout.Used() { return err } - sf := utils.NewStreamFormatter(utils.CompareVersion(version, "1.0") > 0) + sf := utils.NewStreamFormatter(version.GreaterThan("1.0")) w.Write(sf.FormatError(err)) } return nil } -func getImagesSearch(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getImagesSearch(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -454,7 +455,7 @@ func getImagesSearch(eng *engine.Engine, version string, w http.ResponseWriter, return job.Run() } -func postImagesInsert(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postImagesInsert(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -462,7 +463,7 @@ func postImagesInsert(eng *engine.Engine, version string, w http.ResponseWriter, return fmt.Errorf("Missing parameter") } job := eng.Job("insert", vars["name"], r.Form.Get("url"), r.Form.Get("path")) - if utils.CompareVersion(version, "1.0") > 0 { + if version.GreaterThan("1.0") { job.SetenvBool("json", true) streamJSON(job, w, false) } else { @@ -472,14 +473,14 @@ func postImagesInsert(eng *engine.Engine, version string, w http.ResponseWriter, if !job.Stdout.Used() { return err } - sf := utils.NewStreamFormatter(utils.CompareVersion(version, "1.0") > 0) + sf := utils.NewStreamFormatter(version.GreaterThan("1.0")) w.Write(sf.FormatError(err)) } return nil } -func postImagesPush(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postImagesPush(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } @@ -513,7 +514,7 @@ func postImagesPush(eng *engine.Engine, version string, w http.ResponseWriter, r job := eng.Job("push", vars["name"]) job.SetenvJson("metaHeaders", metaHeaders) job.SetenvJson("authConfig", authConfig) - if utils.CompareVersion(version, "1.0") > 0 { + if version.GreaterThan("1.0") { job.SetenvBool("json", true) streamJSON(job, w, true) } else { @@ -524,17 +525,17 @@ func postImagesPush(eng *engine.Engine, version string, w http.ResponseWriter, r if !job.Stdout.Used() { return err } - sf := utils.NewStreamFormatter(utils.CompareVersion(version, "1.0") > 0) + sf := utils.NewStreamFormatter(version.GreaterThan("1.0")) w.Write(sf.FormatError(err)) } return nil } -func getImagesGet(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getImagesGet(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } - if utils.CompareVersion(version, "1.0") > 0 { + if version.GreaterThan("1.0") { w.Header().Set("Content-Type", "application/x-tar") } job := eng.Job("image_export", vars["name"]) @@ -542,13 +543,13 @@ func getImagesGet(eng *engine.Engine, version string, w http.ResponseWriter, r * return job.Run() } -func postImagesLoad(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postImagesLoad(eng *engine.Engine, version version.Version, 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(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postContainersCreate(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return nil } @@ -579,7 +580,7 @@ func postContainersCreate(eng *engine.Engine, version string, w http.ResponseWri return writeJSON(w, http.StatusCreated, out) } -func postContainersRestart(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postContainersRestart(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -595,7 +596,7 @@ func postContainersRestart(eng *engine.Engine, version string, w http.ResponseWr return nil } -func deleteContainers(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func deleteContainers(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -612,7 +613,7 @@ func deleteContainers(eng *engine.Engine, version string, w http.ResponseWriter, return nil } -func deleteImages(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func deleteImages(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -626,7 +627,7 @@ func deleteImages(eng *engine.Engine, version string, w http.ResponseWriter, r * return job.Run() } -func postContainersStart(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postContainersStart(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } @@ -647,7 +648,7 @@ func postContainersStart(eng *engine.Engine, version string, w http.ResponseWrit return nil } -func postContainersStop(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postContainersStop(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -663,7 +664,7 @@ func postContainersStop(eng *engine.Engine, version string, w http.ResponseWrite return nil } -func postContainersWait(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postContainersWait(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } @@ -685,7 +686,7 @@ func postContainersWait(eng *engine.Engine, version string, w http.ResponseWrite return writeJSON(w, http.StatusOK, env) } -func postContainersResize(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postContainersResize(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -698,7 +699,7 @@ func postContainersResize(eng *engine.Engine, version string, w http.ResponseWri return nil } -func postContainersAttach(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postContainersAttach(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -740,7 +741,7 @@ func postContainersAttach(eng *engine.Engine, version string, w http.ResponseWri fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n") - if c.GetSubEnv("Config") != nil && !c.GetSubEnv("Config").GetBool("Tty") && utils.CompareVersion(version, "1.6") >= 0 { + if c.GetSubEnv("Config") != nil && !c.GetSubEnv("Config").GetBool("Tty") && version.GreaterThanOrEqualTo("1.6") { errStream = utils.NewStdWriter(outStream, utils.Stderr) outStream = utils.NewStdWriter(outStream, utils.Stdout) } else { @@ -763,7 +764,7 @@ func postContainersAttach(eng *engine.Engine, version string, w http.ResponseWri return nil } -func wsContainersAttach(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func wsContainersAttach(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -795,7 +796,7 @@ func wsContainersAttach(eng *engine.Engine, version string, w http.ResponseWrite return nil } -func getContainersByName(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getContainersByName(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } @@ -805,7 +806,7 @@ func getContainersByName(eng *engine.Engine, version string, w http.ResponseWrit return job.Run() } -func getImagesByName(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getImagesByName(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } @@ -815,8 +816,8 @@ func getImagesByName(eng *engine.Engine, version string, w http.ResponseWriter, return job.Run() } -func postBuild(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if utils.CompareVersion(version, "1.3") < 0 { +func postBuild(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { + if version.LessThan("1.3") { return fmt.Errorf("Multipart upload for build is no longer supported. Please upgrade your docker client.") } var ( @@ -831,7 +832,7 @@ func postBuild(eng *engine.Engine, version string, w http.ResponseWriter, r *htt // 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 // be overridden. See BuildFile::CmdFrom for details. - if utils.CompareVersion(version, "1.9") < 0 && authEncoded != "" { + if version.LessThan("1.9") && authEncoded != "" { authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded)) if err := json.NewDecoder(authJson).Decode(authConfig); err != nil { // for a pull it is not an error if no auth was given @@ -849,7 +850,7 @@ func postBuild(eng *engine.Engine, version string, w http.ResponseWriter, r *htt } } - if utils.CompareVersion(version, "1.8") >= 0 { + if version.GreaterThanOrEqualTo("1.8") { job.SetenvBool("json", true) streamJSON(job, w, true) } else { @@ -868,13 +869,13 @@ func postBuild(eng *engine.Engine, version string, w http.ResponseWriter, r *htt if !job.Stdout.Used() { return err } - sf := utils.NewStreamFormatter(utils.CompareVersion(version, "1.8") >= 0) + sf := utils.NewStreamFormatter(version.GreaterThanOrEqualTo("1.8")) w.Write(sf.FormatError(err)) } return nil } -func postContainersCopy(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func postContainersCopy(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if vars == nil { return fmt.Errorf("Missing parameter") } @@ -907,7 +908,7 @@ func postContainersCopy(eng *engine.Engine, version string, w http.ResponseWrite return nil } -func optionsHandler(eng *engine.Engine, version string, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func optionsHandler(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { w.WriteHeader(http.StatusOK) return nil } @@ -917,7 +918,7 @@ func writeCorsHeaders(w http.ResponseWriter, r *http.Request) { w.Header().Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS") } -func makeHttpHandler(eng *engine.Engine, logging bool, localMethod string, localRoute string, handlerFunc HttpApiFunc, enableCors bool, dockerVersion string) http.HandlerFunc { +func makeHttpHandler(eng *engine.Engine, logging bool, localMethod string, localRoute string, handlerFunc HttpApiFunc, enableCors bool, dockerVersion version.Version) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // log the request utils.Debugf("Calling %s %s", localMethod, localRoute) @@ -928,11 +929,11 @@ func makeHttpHandler(eng *engine.Engine, logging bool, localMethod string, local if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") { userAgent := strings.Split(r.Header.Get("User-Agent"), "/") - if len(userAgent) == 2 && userAgent[1] != dockerVersion { + if len(userAgent) == 2 && !dockerVersion.Equal(userAgent[1]) { utils.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], dockerVersion) } } - version := mux.Vars(r)["version"] + version := version.Version(mux.Vars(r)["version"]) if version == "" { version = APIVERSION } @@ -940,7 +941,7 @@ func makeHttpHandler(eng *engine.Engine, logging bool, localMethod string, local writeCorsHeaders(w, r) } - if utils.CompareVersion(version, APIVERSION) == 1 { + if version.GreaterThan(APIVERSION) { http.Error(w, fmt.Errorf("client and server don't have same version (client : %s, server: %s)", version, APIVERSION).Error(), http.StatusNotFound) return } @@ -1039,7 +1040,7 @@ func createRouter(eng *engine.Engine, logging, enableCors bool, dockerVersion st localMethod := method // build the handler function - f := makeHttpHandler(eng, logging, localMethod, localRoute, localFct, enableCors, dockerVersion) + f := makeHttpHandler(eng, logging, localMethod, localRoute, localFct, enableCors, version.Version(dockerVersion)) // add the new route if localRoute == "" { @@ -1057,7 +1058,7 @@ func createRouter(eng *engine.Engine, logging, enableCors bool, dockerVersion st // 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(eng *engine.Engine, apiversion string, w http.ResponseWriter, req *http.Request) error { +func ServeRequest(eng *engine.Engine, apiversion version.Version, w http.ResponseWriter, req *http.Request) error { router, err := createRouter(eng, false, true, "") if err != nil { return err diff --git a/integration/server_test.go b/integration/server_test.go index 2fe16551dc..1247e8d2d8 100644 --- a/integration/server_test.go +++ b/integration/server_test.go @@ -2,6 +2,7 @@ package docker import ( "github.com/dotcloud/docker" + "github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/runconfig" "strings" "testing" diff --git a/pkg/version/version.go b/pkg/version/version.go new file mode 100644 index 0000000000..3721d64aa8 --- /dev/null +++ b/pkg/version/version.go @@ -0,0 +1,52 @@ +package version + +import ( + "strconv" + "strings" +) + +type Version string + +func (me Version) compareTo(other string) int { + var ( + meTab = strings.Split(string(me), ".") + otherTab = strings.Split(other, ".") + ) + for i, s := range meTab { + var meInt, otherInt int + meInt, _ = strconv.Atoi(s) + if len(otherTab) > i { + otherInt, _ = strconv.Atoi(otherTab[i]) + } + if meInt > otherInt { + return 1 + } + if otherInt > meInt { + return -1 + } + } + if len(otherTab) > len(meTab) { + return -1 + } + return 0 +} + +func (me Version) LessThan(other string) bool { + return me.compareTo(other) == -1 +} + +func (me Version) LessThanOrEqualTo(other string) bool { + return me.compareTo(other) <= 0 +} + +func (me Version) GreaterThan(other string) bool { + return me.compareTo(other) == 1 +} + +func (me Version) GreaterThanOrEqualTo(other string) bool { + return me.compareTo(other) >= 0 +} + +func (me Version) Equal(other string) bool { + return me.compareTo(other) == 0 +} diff --git a/pkg/version/version_test.go b/pkg/version/version_test.go new file mode 100644 index 0000000000..4bebd0c434 --- /dev/null +++ b/pkg/version/version_test.go @@ -0,0 +1,25 @@ +package version + +import ( + "testing" +) + +func assertVersion(t *testing.T, a, b string, result int) { + if r := Version(a).compareTo(b); r != result { + t.Fatalf("Unexpected version comparison result. Found %d, expected %d", r, result) + } +} + +func TestCompareVersion(t *testing.T) { + assertVersion(t, "1.12", "1.12", 0) + assertVersion(t, "1.05.00.0156", "1.0.221.9289", 1) + assertVersion(t, "1", "1.0.1", -1) + assertVersion(t, "1.0.1", "1", 1) + assertVersion(t, "1.0.1", "1.0.2", -1) + assertVersion(t, "1.0.2", "1.0.3", -1) + assertVersion(t, "1.0.3", "1.1", -1) + assertVersion(t, "1.1", "1.1.1", -1) + assertVersion(t, "1.1.1", "1.1.2", -1) + assertVersion(t, "1.1.2", "1.2", -1) + +} diff --git a/utils/utils.go b/utils/utils.go index 88f43c8bd5..1aba80ff41 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -972,27 +972,3 @@ func NewReadCloserWrapper(r io.Reader, closer func() error) io.ReadCloser { closer: closer, } } - -func CompareVersion(a, b string) int { - var ( - aa = strings.Split(a, ".") - bb = strings.Split(b, ".") - ) - for i, s := range aa { - var ai, bi int - ai, _ = strconv.Atoi(s) - if len(bb) > i { - bi, _ = strconv.Atoi(bb[i]) - } - if ai > bi { - return 1 - } - if bi > ai { - return -1 - } - } - if len(bb) > len(aa) { - return -1 - } - return 0 -} diff --git a/utils/utils_test.go b/utils/utils_test.go index 41dba72aa7..7e63a45cf7 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -479,23 +479,3 @@ func StrSlicesEqual(a, b []string) bool { return true } - -func asserVersion(t *testing.T, a, b string, result int) { - if r := CompareVersion(a, b); r != result { - t.Fatalf("Unexpected version comparison result. Found %d, expected %d", r, result) - } -} - -func TestCompareVersion(t *testing.T) { - asserVersion(t, "1.12", "1.12", 0) - asserVersion(t, "1.05.00.0156", "1.0.221.9289", 1) - asserVersion(t, "1", "1.0.1", -1) - asserVersion(t, "1.0.1", "1", 1) - asserVersion(t, "1.0.1", "1.0.2", -1) - asserVersion(t, "1.0.2", "1.0.3", -1) - asserVersion(t, "1.0.3", "1.1", -1) - asserVersion(t, "1.1", "1.1.1", -1) - asserVersion(t, "1.1.1", "1.1.2", -1) - asserVersion(t, "1.1.2", "1.2", -1) - -}