Browse Source

Merge pull request #15953 from duglin/DaemonContext

Add a "context" to the api/server/* code
David Calavera 9 years ago
parent
commit
6efe45990d

+ 2 - 2
api/server/auth.go

@@ -6,10 +6,10 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/cliconfig"
-	"github.com/docker/docker/pkg/version"
+	"github.com/docker/docker/context"
 )
 
-func (s *Server) postAuth(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postAuth(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	var config *cliconfig.AuthConfig
 	err := json.NewDecoder(r.Body).Decode(&config)
 	r.Body.Close()

+ 22 - 20
api/server/container.go

@@ -12,14 +12,14 @@ import (
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/context"
 	"github.com/docker/docker/daemon"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/signal"
-	"github.com/docker/docker/pkg/version"
 	"github.com/docker/docker/runconfig"
 )
 
-func (s *Server) getContainersJSON(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getContainersJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -48,7 +48,7 @@ func (s *Server) getContainersJSON(version version.Version, w http.ResponseWrite
 	return writeJSON(w, http.StatusOK, containers)
 }
 
-func (s *Server) getContainersStats(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getContainersStats(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -89,7 +89,7 @@ func (s *Server) getContainersStats(version version.Version, w http.ResponseWrit
 	return s.daemon.ContainerStats(container, config)
 }
 
-func (s *Server) getContainersLogs(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getContainersLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -146,7 +146,7 @@ func (s *Server) getContainersLogs(version version.Version, w http.ResponseWrite
 	return nil
 }
 
-func (s *Server) getContainersExport(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getContainersExport(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -154,7 +154,7 @@ func (s *Server) getContainersExport(version version.Version, w http.ResponseWri
 	return s.daemon.ContainerExport(vars["name"], w)
 }
 
-func (s *Server) postContainersStart(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainersStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -190,7 +190,7 @@ func (s *Server) postContainersStart(version version.Version, w http.ResponseWri
 	return nil
 }
 
-func (s *Server) postContainersStop(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainersStop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -212,7 +212,7 @@ func (s *Server) postContainersStop(version version.Version, w http.ResponseWrit
 	return nil
 }
 
-func (s *Server) postContainersKill(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainersKill(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -250,6 +250,7 @@ func (s *Server) postContainersKill(version version.Version, w http.ResponseWrit
 		// Return error that's not caused because the container is stopped.
 		// Return error if the container is not running and the api is >= 1.20
 		// to keep backwards compatibility.
+		version := ctx.Version()
 		if version.GreaterThanOrEqualTo("1.20") || !isStopped {
 			return fmt.Errorf("Cannot kill container %s: %v", name, err)
 		}
@@ -259,7 +260,7 @@ func (s *Server) postContainersKill(version version.Version, w http.ResponseWrit
 	return nil
 }
 
-func (s *Server) postContainersRestart(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainersRestart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -278,7 +279,7 @@ func (s *Server) postContainersRestart(version version.Version, w http.ResponseW
 	return nil
 }
 
-func (s *Server) postContainersPause(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainersPause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -295,7 +296,7 @@ func (s *Server) postContainersPause(version version.Version, w http.ResponseWri
 	return nil
 }
 
-func (s *Server) postContainersUnpause(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainersUnpause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -312,7 +313,7 @@ func (s *Server) postContainersUnpause(version version.Version, w http.ResponseW
 	return nil
 }
 
-func (s *Server) postContainersWait(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainersWait(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -327,7 +328,7 @@ func (s *Server) postContainersWait(version version.Version, w http.ResponseWrit
 	})
 }
 
-func (s *Server) getContainersChanges(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getContainersChanges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -340,7 +341,7 @@ func (s *Server) getContainersChanges(version version.Version, w http.ResponseWr
 	return writeJSON(w, http.StatusOK, changes)
 }
 
-func (s *Server) getContainersTop(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getContainersTop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -357,7 +358,7 @@ func (s *Server) getContainersTop(version version.Version, w http.ResponseWriter
 	return writeJSON(w, http.StatusOK, procList)
 }
 
-func (s *Server) postContainerRename(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainerRename(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -374,7 +375,7 @@ func (s *Server) postContainerRename(version version.Version, w http.ResponseWri
 	return nil
 }
 
-func (s *Server) postContainersCreate(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainersCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -390,6 +391,7 @@ func (s *Server) postContainersCreate(version version.Version, w http.ResponseWr
 	if err != nil {
 		return err
 	}
+	version := ctx.Version()
 	adjustCPUShares := version.LessThan("1.19")
 
 	container, warnings, err := s.daemon.ContainerCreate(name, config, hostConfig, adjustCPUShares)
@@ -403,7 +405,7 @@ func (s *Server) postContainersCreate(version version.Version, w http.ResponseWr
 	})
 }
 
-func (s *Server) deleteContainers(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) deleteContainers(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -431,7 +433,7 @@ func (s *Server) deleteContainers(version version.Version, w http.ResponseWriter
 	return nil
 }
 
-func (s *Server) postContainersResize(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainersResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -451,7 +453,7 @@ func (s *Server) postContainersResize(version version.Version, w http.ResponseWr
 	return s.daemon.ContainerResize(vars["name"], height, width)
 }
 
-func (s *Server) postContainersAttach(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -493,7 +495,7 @@ func (s *Server) postContainersAttach(version version.Version, w http.ResponseWr
 	return nil
 }
 
-func (s *Server) wsContainersAttach(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) wsContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}

+ 5 - 5
api/server/copy.go

@@ -10,11 +10,11 @@ import (
 	"strings"
 
 	"github.com/docker/docker/api/types"
-	"github.com/docker/docker/pkg/version"
+	"github.com/docker/docker/context"
 )
 
 // postContainersCopy is deprecated in favor of getContainersArchive.
-func (s *Server) postContainersCopy(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainersCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -68,7 +68,7 @@ func setContainerPathStatHeader(stat *types.ContainerPathStat, header http.Heade
 	return nil
 }
 
-func (s *Server) headContainersArchive(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) headContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	v, err := archiveFormValues(r, vars)
 	if err != nil {
 		return err
@@ -82,7 +82,7 @@ func (s *Server) headContainersArchive(version version.Version, w http.ResponseW
 	return setContainerPathStatHeader(stat, w.Header())
 }
 
-func (s *Server) getContainersArchive(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	v, err := archiveFormValues(r, vars)
 	if err != nil {
 		return err
@@ -104,7 +104,7 @@ func (s *Server) getContainersArchive(version version.Version, w http.ResponseWr
 	return err
 }
 
-func (s *Server) putContainersArchive(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) putContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	v, err := archiveFormValues(r, vars)
 	if err != nil {
 		return err

+ 6 - 4
api/server/daemon.go

@@ -12,15 +12,15 @@ import (
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/autogen/dockerversion"
+	"github.com/docker/docker/context"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/jsonmessage"
 	"github.com/docker/docker/pkg/parsers/filters"
 	"github.com/docker/docker/pkg/parsers/kernel"
-	"github.com/docker/docker/pkg/version"
 	"github.com/docker/docker/utils"
 )
 
-func (s *Server) getVersion(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	v := &types.Version{
 		Version:    dockerversion.VERSION,
 		APIVersion: api.Version,
@@ -31,6 +31,8 @@ func (s *Server) getVersion(version version.Version, w http.ResponseWriter, r *h
 		BuildTime:  dockerversion.BUILDTIME,
 	}
 
+	version := ctx.Version()
+
 	if version.GreaterThanOrEqualTo("1.19") {
 		v.Experimental = utils.ExperimentalBuild()
 	}
@@ -42,7 +44,7 @@ func (s *Server) getVersion(version version.Version, w http.ResponseWriter, r *h
 	return writeJSON(w, http.StatusOK, v)
 }
 
-func (s *Server) getInfo(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	info, err := s.daemon.SystemInfo()
 	if err != nil {
 		return err
@@ -51,7 +53,7 @@ func (s *Server) getInfo(version version.Version, w http.ResponseWriter, r *http
 	return writeJSON(w, http.StatusOK, info)
 }
 
-func (s *Server) getEvents(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getEvents(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}

+ 5 - 5
api/server/exec.go

@@ -9,12 +9,12 @@ import (
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/context"
 	"github.com/docker/docker/pkg/stdcopy"
-	"github.com/docker/docker/pkg/version"
 	"github.com/docker/docker/runconfig"
 )
 
-func (s *Server) getExecByID(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter 'id'")
 	}
@@ -27,7 +27,7 @@ func (s *Server) getExecByID(version version.Version, w http.ResponseWriter, r *
 	return writeJSON(w, http.StatusOK, eConfig)
 }
 
-func (s *Server) postContainerExecCreate(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainerExecCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -59,7 +59,7 @@ func (s *Server) postContainerExecCreate(version version.Version, w http.Respons
 }
 
 // TODO(vishh): Refactor the code to avoid having to specify stream config as part of both create and start.
-func (s *Server) postContainerExecStart(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainerExecStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -106,7 +106,7 @@ func (s *Server) postContainerExecStart(version version.Version, w http.Response
 	return nil
 }
 
-func (s *Server) postContainerExecResize(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postContainerExecResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}

+ 15 - 13
api/server/image.go

@@ -12,17 +12,17 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/builder"
 	"github.com/docker/docker/cliconfig"
+	"github.com/docker/docker/context"
 	"github.com/docker/docker/graph"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/streamformatter"
 	"github.com/docker/docker/pkg/ulimit"
-	"github.com/docker/docker/pkg/version"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/utils"
 )
 
-func (s *Server) postCommit(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postCommit(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -34,6 +34,7 @@ func (s *Server) postCommit(version version.Version, w http.ResponseWriter, r *h
 	cname := r.Form.Get("container")
 
 	pause := boolValue(r, "pause")
+	version := ctx.Version()
 	if r.FormValue("pause") == "" && version.GreaterThanOrEqualTo("1.13") {
 		pause = true
 	}
@@ -64,7 +65,7 @@ func (s *Server) postCommit(version version.Version, w http.ResponseWriter, r *h
 }
 
 // Creates an image from Pull or from Import
-func (s *Server) postImagesCreate(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postImagesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -140,7 +141,7 @@ func (s *Server) postImagesCreate(version version.Version, w http.ResponseWriter
 	return nil
 }
 
-func (s *Server) postImagesPush(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -192,7 +193,7 @@ func (s *Server) postImagesPush(version version.Version, w http.ResponseWriter,
 	return nil
 }
 
-func (s *Server) getImagesGet(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getImagesGet(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -220,11 +221,11 @@ func (s *Server) getImagesGet(version version.Version, w http.ResponseWriter, r
 	return nil
 }
 
-func (s *Server) postImagesLoad(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postImagesLoad(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	return s.daemon.Repositories().Load(r.Body, w)
 }
 
-func (s *Server) deleteImages(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) deleteImages(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -249,7 +250,7 @@ func (s *Server) deleteImages(version version.Version, w http.ResponseWriter, r
 	return writeJSON(w, http.StatusOK, list)
 }
 
-func (s *Server) getImagesByName(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getImagesByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -262,7 +263,7 @@ func (s *Server) getImagesByName(version version.Version, w http.ResponseWriter,
 	return writeJSON(w, http.StatusOK, imageInspect)
 }
 
-func (s *Server) postBuild(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	var (
 		authConfigs        = map[string]cliconfig.AuthConfig{}
 		authConfigsEncoded = r.Header.Get("X-Registry-Config")
@@ -280,6 +281,7 @@ func (s *Server) postBuild(version version.Version, w http.ResponseWriter, r *ht
 
 	w.Header().Set("Content-Type", "application/json")
 
+	version := ctx.Version()
 	if boolValue(r, "forcerm") && version.GreaterThanOrEqualTo("1.12") {
 		buildConfig.Remove = true
 	} else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
@@ -346,7 +348,7 @@ func (s *Server) postBuild(version version.Version, w http.ResponseWriter, r *ht
 	return nil
 }
 
-func (s *Server) getImagesJSON(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -360,7 +362,7 @@ func (s *Server) getImagesJSON(version version.Version, w http.ResponseWriter, r
 	return writeJSON(w, http.StatusOK, images)
 }
 
-func (s *Server) getImagesHistory(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getImagesHistory(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -374,7 +376,7 @@ func (s *Server) getImagesHistory(version version.Version, w http.ResponseWriter
 	return writeJSON(w, http.StatusOK, history)
 }
 
-func (s *Server) postImagesTag(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postImagesTag(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -394,7 +396,7 @@ func (s *Server) postImagesTag(version version.Version, w http.ResponseWriter, r
 	return nil
 }
 
-func (s *Server) getImagesSearch(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getImagesSearch(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}

+ 4 - 2
api/server/inspect.go

@@ -4,11 +4,11 @@ import (
 	"fmt"
 	"net/http"
 
-	"github.com/docker/docker/pkg/version"
+	"github.com/docker/docker/context"
 )
 
 // getContainersByName inspects containers configuration and serializes it as json.
-func (s *Server) getContainersByName(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
@@ -16,6 +16,8 @@ func (s *Server) getContainersByName(version version.Version, w http.ResponseWri
 	var json interface{}
 	var err error
 
+	version := ctx.Version()
+
 	switch {
 	case version.LessThan("1.20"):
 		json, err = s.daemon.ContainerInspectPre120(vars["name"])

+ 27 - 11
api/server/server.go

@@ -16,8 +16,10 @@ import (
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/autogen/dockerversion"
+	"github.com/docker/docker/context"
 	"github.com/docker/docker/daemon"
 	"github.com/docker/docker/pkg/sockets"
+	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/docker/pkg/version"
 )
 
@@ -122,7 +124,7 @@ func (s *HTTPServer) Close() error {
 
 // HTTPAPIFunc is an adapter to allow the use of ordinary functions as Docker API endpoints.
 // Any function that has the appropriate signature can be register as a API endpoint (e.g. getVersion).
-type HTTPAPIFunc func(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error
+type HTTPAPIFunc func(ctx context.Context, 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()
@@ -219,7 +221,7 @@ func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
 	return json.NewEncoder(w).Encode(v)
 }
 
-func (s *Server) optionsHandler(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) optionsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	w.WriteHeader(http.StatusOK)
 	return nil
 }
@@ -230,7 +232,7 @@ func writeCorsHeaders(w http.ResponseWriter, r *http.Request, corsHeaders string
 	w.Header().Add("Access-Control-Allow-Methods", "HEAD, GET, POST, DELETE, PUT, OPTIONS")
 }
 
-func (s *Server) ping(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) ping(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	_, err := w.Write([]byte{'O', 'K'})
 	return err
 }
@@ -250,6 +252,24 @@ func (s *Server) initTCPSocket(addr string) (l net.Listener, err error) {
 
 func makeHTTPHandler(logging bool, localMethod string, localRoute string, handlerFunc HTTPAPIFunc, corsHeaders string, dockerVersion version.Version) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
+		// Define the context that we'll pass around to share info
+		// like the docker-request-id.
+		//
+		// The 'context' will be used for global data that should
+		// apply to all requests. Data that is specific to the
+		// immediate function being called should still be passed
+		// as 'args' on the function call.
+
+		reqID := stringid.TruncateID(stringid.GenerateNonCryptoID())
+		apiVersion := version.Version(mux.Vars(r)["version"])
+		if apiVersion == "" {
+			apiVersion = api.Version
+		}
+
+		ctx := context.Background()
+		ctx = context.WithValue(ctx, context.RequestID, reqID)
+		ctx = context.WithValue(ctx, context.APIVersion, apiVersion)
+
 		// log the request
 		logrus.Debugf("Calling %s %s", localMethod, localRoute)
 
@@ -270,26 +290,22 @@ func makeHTTPHandler(logging bool, localMethod string, localRoute string, handle
 				logrus.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], dockerVersion)
 			}
 		}
-		version := version.Version(mux.Vars(r)["version"])
-		if version == "" {
-			version = api.Version
-		}
 		if corsHeaders != "" {
 			writeCorsHeaders(w, r, corsHeaders)
 		}
 
-		if version.GreaterThan(api.Version) {
-			http.Error(w, fmt.Errorf("client is newer than server (client API version: %s, server API version: %s)", version, api.Version).Error(), http.StatusBadRequest)
+		if apiVersion.GreaterThan(api.Version) {
+			http.Error(w, fmt.Errorf("client is newer than server (client API version: %s, server API version: %s)", apiVersion, api.Version).Error(), http.StatusBadRequest)
 			return
 		}
-		if version.LessThan(api.MinVersion) {
+		if apiVersion.LessThan(api.MinVersion) {
 			http.Error(w, fmt.Errorf("client is too old, minimum supported API version is %s, please upgrade your client to a newer version", api.MinVersion).Error(), http.StatusBadRequest)
 			return
 		}
 
 		w.Header().Set("Server", "Docker/"+dockerversion.VERSION+" ("+runtime.GOOS+")")
 
-		if err := handlerFunc(version, w, r, mux.Vars(r)); err != nil {
+		if err := handlerFunc(ctx, w, r, mux.Vars(r)); err != nil {
 			logrus.Errorf("Handler for %s %s returned error: %s", localMethod, localRoute, err)
 			httpError(w, err)
 		}

+ 5 - 5
api/server/volume.go

@@ -5,10 +5,10 @@ import (
 	"net/http"
 
 	"github.com/docker/docker/api/types"
-	"github.com/docker/docker/pkg/version"
+	"github.com/docker/docker/context"
 )
 
-func (s *Server) getVolumesList(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getVolumesList(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -20,7 +20,7 @@ func (s *Server) getVolumesList(version version.Version, w http.ResponseWriter,
 	return writeJSON(w, http.StatusOK, &types.VolumesListResponse{Volumes: volumes})
 }
 
-func (s *Server) getVolumeByName(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) getVolumeByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -32,7 +32,7 @@ func (s *Server) getVolumeByName(version version.Version, w http.ResponseWriter,
 	return writeJSON(w, http.StatusOK, v)
 }
 
-func (s *Server) postVolumesCreate(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) postVolumesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}
@@ -53,7 +53,7 @@ func (s *Server) postVolumesCreate(version version.Version, w http.ResponseWrite
 	return writeJSON(w, http.StatusCreated, volume)
 }
 
-func (s *Server) deleteVolumes(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+func (s *Server) deleteVolumes(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
 	}

+ 64 - 0
context/context.go

@@ -0,0 +1,64 @@
+package context
+
+import (
+	"golang.org/x/net/context"
+
+	"github.com/docker/docker/pkg/version"
+)
+
+const (
+	// RequestID is the unique ID for each http request
+	RequestID = "request-id"
+
+	// APIVersion is the client's requested API version
+	APIVersion = "api-version"
+)
+
+// Context is just our own wrapper for the golang 'Context' - mainly
+// so we can add our over version of the funcs.
+type Context struct {
+	context.Context
+}
+
+// Background creates a new Context based on golang's default one.
+func Background() Context {
+	return Context{context.Background()}
+}
+
+// WithValue will return a Context that has this new key/value pair
+// associated with it. Just uses the golang version but then wraps it.
+func WithValue(ctx Context, key, value interface{}) Context {
+	return Context{context.WithValue(ctx, key, value)}
+}
+
+// RequestID is a utility func to make it easier to get the
+// request ID associated with this Context/request.
+func (ctx Context) RequestID() string {
+	val := ctx.Value(RequestID)
+	if val == nil {
+		return ""
+	}
+
+	id, ok := val.(string)
+	if !ok {
+		// Ideally we shouldn't panic but we also should never get here
+		panic("Context RequestID isn't a string")
+	}
+	return id
+}
+
+// Version is a utility func to make it easier to get the
+// API version string associated with this Context/request.
+func (ctx Context) Version() version.Version {
+	val := ctx.Value(APIVersion)
+	if val == nil {
+		return version.Version("")
+	}
+
+	ver, ok := val.(version.Version)
+	if !ok {
+		// Ideally we shouldn't panic but we also should never get here
+		panic("Context APIVersion isn't a version.Version")
+	}
+	return ver
+}

+ 35 - 0
context/context_test.go

@@ -0,0 +1,35 @@
+package context
+
+import (
+	"testing"
+
+	"github.com/docker/docker/pkg/version"
+)
+
+func TestContext(t *testing.T) {
+	ctx := Background()
+
+	// First make sure getting non-existent values doesn't break
+	if id := ctx.RequestID(); id != "" {
+		t.Fatalf("RequestID() should have been '', was: %q", id)
+	}
+
+	if ver := ctx.Version(); ver != "" {
+		t.Fatalf("Version() should have been '', was: %q", ver)
+	}
+
+	// Test basic set/get
+	ctx = WithValue(ctx, RequestID, "123")
+	if ctx.RequestID() != "123" {
+		t.Fatalf("RequestID() should have been '123'")
+	}
+
+	// Now make sure after a 2nd set we can still get both
+	ctx = WithValue(ctx, APIVersion, version.Version("x.y"))
+	if id := ctx.RequestID(); id != "123" {
+		t.Fatalf("RequestID() should have been '123', was %q", id)
+	}
+	if ver := ctx.Version(); ver != "x.y" {
+		t.Fatalf("Version() should have been 'x.y', was %q", ver)
+	}
+}