Browse code

Use golang.org/x/net/context in api/server/

This patch removes the internal context package and uses golang's
package instead.

Signed-off-by: Tibor Vass <tibor@docker.com>

Tibor Vass authored on 2015/09/30 06:32:07
Showing 14 changed files
... ...
@@ -6,7 +6,7 @@ import (
6 6
 
7 7
 	"github.com/docker/docker/api/types"
8 8
 	"github.com/docker/docker/cliconfig"
9
-	"github.com/docker/docker/context"
9
+	"golang.org/x/net/context"
10 10
 )
11 11
 
12 12
 func (s *Server) postAuth(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -9,19 +9,17 @@ import (
9 9
 	"syscall"
10 10
 	"time"
11 11
 
12
-	"golang.org/x/net/websocket"
13
-
14 12
 	"github.com/Sirupsen/logrus"
15 13
 	"github.com/docker/distribution/registry/api/errcode"
16 14
 	"github.com/docker/docker/api/types"
17
-	"github.com/docker/docker/context"
18 15
 	"github.com/docker/docker/daemon"
19 16
 	derr "github.com/docker/docker/errors"
20 17
 	"github.com/docker/docker/pkg/ioutils"
21 18
 	"github.com/docker/docker/pkg/signal"
22
-	"github.com/docker/docker/pkg/version"
23 19
 	"github.com/docker/docker/runconfig"
24 20
 	"github.com/docker/docker/utils"
21
+	"golang.org/x/net/context"
22
+	"golang.org/x/net/websocket"
25 23
 )
26 24
 
27 25
 func (s *Server) getContainersJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -75,12 +73,11 @@ func (s *Server) getContainersStats(ctx context.Context, w http.ResponseWriter,
75 75
 		closeNotifier = notifier.CloseNotify()
76 76
 	}
77 77
 
78
-	version, _ := ctx.Value("api-version").(version.Version)
79 78
 	config := &daemon.ContainerStatsConfig{
80 79
 		Stream:    stream,
81 80
 		OutStream: out,
82 81
 		Stop:      closeNotifier,
83
-		Version:   version,
82
+		Version:   versionFromContext(ctx),
84 83
 	}
85 84
 
86 85
 	return s.daemon.ContainerStats(vars["name"], config)
... ...
@@ -234,7 +231,7 @@ func (s *Server) postContainersKill(ctx context.Context, w http.ResponseWriter,
234 234
 		// Return error that's not caused because the container is stopped.
235 235
 		// Return error if the container is not running and the api is >= 1.20
236 236
 		// to keep backwards compatibility.
237
-		version := ctx.Version()
237
+		version := versionFromContext(ctx)
238 238
 		if version.GreaterThanOrEqualTo("1.20") || !isStopped {
239 239
 			return fmt.Errorf("Cannot kill container %s: %v", name, err)
240 240
 		}
... ...
@@ -373,7 +370,7 @@ func (s *Server) postContainersCreate(ctx context.Context, w http.ResponseWriter
373 373
 	if err != nil {
374 374
 		return err
375 375
 	}
376
-	version := ctx.Version()
376
+	version := versionFromContext(ctx)
377 377
 	adjustCPUShares := version.LessThan("1.19")
378 378
 
379 379
 	ccr, err := s.daemon.ContainerCreate(name, config, hostConfig, adjustCPUShares)
... ...
@@ -10,7 +10,7 @@ import (
10 10
 	"strings"
11 11
 
12 12
 	"github.com/docker/docker/api/types"
13
-	"github.com/docker/docker/context"
13
+	"golang.org/x/net/context"
14 14
 )
15 15
 
16 16
 // postContainersCopy is deprecated in favor of getContainersArchive.
... ...
@@ -12,12 +12,12 @@ import (
12 12
 	"github.com/docker/docker/api"
13 13
 	"github.com/docker/docker/api/types"
14 14
 	"github.com/docker/docker/autogen/dockerversion"
15
-	"github.com/docker/docker/context"
16 15
 	"github.com/docker/docker/pkg/ioutils"
17 16
 	"github.com/docker/docker/pkg/jsonmessage"
18 17
 	"github.com/docker/docker/pkg/parsers/filters"
19 18
 	"github.com/docker/docker/pkg/parsers/kernel"
20 19
 	"github.com/docker/docker/utils"
20
+	"golang.org/x/net/context"
21 21
 )
22 22
 
23 23
 func (s *Server) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -31,7 +31,7 @@ func (s *Server) getVersion(ctx context.Context, w http.ResponseWriter, r *http.
31 31
 		BuildTime:  dockerversion.BUILDTIME,
32 32
 	}
33 33
 
34
-	version := ctx.Version()
34
+	version := versionFromContext(ctx)
35 35
 
36 36
 	if version.GreaterThanOrEqualTo("1.19") {
37 37
 		v.Experimental = utils.ExperimentalBuild()
... ...
@@ -9,9 +9,9 @@ import (
9 9
 
10 10
 	"github.com/Sirupsen/logrus"
11 11
 	"github.com/docker/docker/api/types"
12
-	"github.com/docker/docker/context"
13 12
 	"github.com/docker/docker/pkg/stdcopy"
14 13
 	"github.com/docker/docker/runconfig"
14
+	"golang.org/x/net/context"
15 15
 )
16 16
 
17 17
 func (s *Server) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -13,7 +13,6 @@ import (
13 13
 	"github.com/docker/docker/api/types"
14 14
 	"github.com/docker/docker/builder"
15 15
 	"github.com/docker/docker/cliconfig"
16
-	"github.com/docker/docker/context"
17 16
 	"github.com/docker/docker/graph"
18 17
 	"github.com/docker/docker/pkg/ioutils"
19 18
 	"github.com/docker/docker/pkg/parsers"
... ...
@@ -21,6 +20,7 @@ import (
21 21
 	"github.com/docker/docker/pkg/ulimit"
22 22
 	"github.com/docker/docker/runconfig"
23 23
 	"github.com/docker/docker/utils"
24
+	"golang.org/x/net/context"
24 25
 )
25 26
 
26 27
 func (s *Server) postCommit(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -35,7 +35,7 @@ func (s *Server) postCommit(ctx context.Context, w http.ResponseWriter, r *http.
35 35
 	cname := r.Form.Get("container")
36 36
 
37 37
 	pause := boolValue(r, "pause")
38
-	version := ctx.Version()
38
+	version := versionFromContext(ctx)
39 39
 	if r.FormValue("pause") == "" && version.GreaterThanOrEqualTo("1.13") {
40 40
 		pause = true
41 41
 	}
... ...
@@ -282,7 +282,7 @@ func (s *Server) postBuild(ctx context.Context, w http.ResponseWriter, r *http.R
282 282
 
283 283
 	w.Header().Set("Content-Type", "application/json")
284 284
 
285
-	version := ctx.Version()
285
+	version := versionFromContext(ctx)
286 286
 	if boolValue(r, "forcerm") && version.GreaterThanOrEqualTo("1.12") {
287 287
 		buildConfig.Remove = true
288 288
 	} else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
... ...
@@ -4,7 +4,7 @@ import (
4 4
 	"fmt"
5 5
 	"net/http"
6 6
 
7
-	"github.com/docker/docker/context"
7
+	"golang.org/x/net/context"
8 8
 )
9 9
 
10 10
 // getContainersByName inspects containers configuration and serializes it as json.
... ...
@@ -16,7 +16,7 @@ func (s *Server) getContainersByName(ctx context.Context, w http.ResponseWriter,
16 16
 	var json interface{}
17 17
 	var err error
18 18
 
19
-	version := ctx.Version()
19
+	version := versionFromContext(ctx)
20 20
 
21 21
 	switch {
22 22
 	case version.LessThan("1.20"):
... ...
@@ -8,12 +8,14 @@ import (
8 8
 	"github.com/Sirupsen/logrus"
9 9
 	"github.com/docker/docker/api"
10 10
 	"github.com/docker/docker/autogen/dockerversion"
11
-	"github.com/docker/docker/context"
12 11
 	"github.com/docker/docker/errors"
13
-	"github.com/docker/docker/pkg/stringid"
14 12
 	"github.com/docker/docker/pkg/version"
13
+	"golang.org/x/net/context"
15 14
 )
16 15
 
16
+// apiVersionKey is the client's requested API version.
17
+const apiVersionKey = "api-version"
18
+
17 19
 // middleware is an adapter to allow the use of ordinary functions as Docker API filters.
18 20
 // Any function that has the appropriate signature can be register as a middleware.
19 21
 type middleware func(handler HTTPAPIFunc) HTTPAPIFunc
... ...
@@ -28,16 +30,6 @@ func (s *Server) loggingMiddleware(handler HTTPAPIFunc) HTTPAPIFunc {
28 28
 	}
29 29
 }
30 30
 
31
-// requestIDMiddleware generates a uniq ID for each request.
32
-// This ID travels inside the context for tracing purposes.
33
-func requestIDMiddleware(handler HTTPAPIFunc) HTTPAPIFunc {
34
-	return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
35
-		reqID := stringid.TruncateID(stringid.GenerateNonCryptoID())
36
-		ctx = context.WithValue(ctx, context.RequestID, reqID)
37
-		return handler(ctx, w, r, vars)
38
-	}
39
-}
40
-
41 31
 // userAgentMiddleware checks the User-Agent header looking for a valid docker client spec.
42 32
 func (s *Server) userAgentMiddleware(handler HTTPAPIFunc) HTTPAPIFunc {
43 33
 	return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -93,7 +85,7 @@ func versionMiddleware(handler HTTPAPIFunc) HTTPAPIFunc {
93 93
 		}
94 94
 
95 95
 		w.Header().Set("Server", "Docker/"+dockerversion.VERSION+" ("+runtime.GOOS+")")
96
-		ctx = context.WithValue(ctx, context.APIVersion, apiVersion)
96
+		ctx = context.WithValue(ctx, apiVersionKey, apiVersion)
97 97
 		return handler(ctx, w, r, vars)
98 98
 	}
99 99
 }
... ...
@@ -104,7 +96,6 @@ func versionMiddleware(handler HTTPAPIFunc) HTTPAPIFunc {
104 104
 //
105 105
 // Example: handleWithGlobalMiddlewares(s.getContainersName)
106 106
 //
107
-// requestIDMiddlware(
108 107
 //	s.loggingMiddleware(
109 108
 //		s.userAgentMiddleware(
110 109
 //			s.corsMiddleware(
... ...
@@ -112,14 +103,12 @@ func versionMiddleware(handler HTTPAPIFunc) HTTPAPIFunc {
112 112
 //			)
113 113
 //		)
114 114
 //	)
115
-// )
116 115
 func (s *Server) handleWithGlobalMiddlewares(handler HTTPAPIFunc) HTTPAPIFunc {
117 116
 	middlewares := []middleware{
118 117
 		versionMiddleware,
119 118
 		s.corsMiddleware,
120 119
 		s.userAgentMiddleware,
121 120
 		s.loggingMiddleware,
122
-		requestIDMiddleware,
123 121
 	}
124 122
 
125 123
 	h := handler
... ...
@@ -128,3 +117,16 @@ func (s *Server) handleWithGlobalMiddlewares(handler HTTPAPIFunc) HTTPAPIFunc {
128 128
 	}
129 129
 	return h
130 130
 }
131
+
132
+// versionFromContext returns an API version from the context using apiVersionKey.
133
+// It panics if the context value does not have version.Version type.
134
+func versionFromContext(ctx context.Context) (ver version.Version) {
135
+	if ctx == nil {
136
+		return
137
+	}
138
+	val := ctx.Value(apiVersionKey)
139
+	if val == nil {
140
+		return
141
+	}
142
+	return val.(version.Version)
143
+}
... ...
@@ -6,13 +6,13 @@ import (
6 6
 	"testing"
7 7
 
8 8
 	"github.com/docker/distribution/registry/api/errcode"
9
-	"github.com/docker/docker/context"
10 9
 	"github.com/docker/docker/errors"
10
+	"golang.org/x/net/context"
11 11
 )
12 12
 
13 13
 func TestVersionMiddleware(t *testing.T) {
14 14
 	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
15
-		if ctx.Version() == "" {
15
+		if versionFromContext(ctx) == "" {
16 16
 			t.Fatalf("Expected version, got empty string")
17 17
 		}
18 18
 		return nil
... ...
@@ -30,7 +30,7 @@ func TestVersionMiddleware(t *testing.T) {
30 30
 
31 31
 func TestVersionMiddlewareWithErrors(t *testing.T) {
32 32
 	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
33
-		if ctx.Version() == "" {
33
+		if versionFromContext(ctx) == "" {
34 34
 			t.Fatalf("Expected version, got empty string")
35 35
 		}
36 36
 		return nil
... ...
@@ -54,21 +54,3 @@ func TestVersionMiddlewareWithErrors(t *testing.T) {
54 54
 		t.Fatalf("Expected ErrorCodeNewerClientVersion, got %v", err)
55 55
 	}
56 56
 }
57
-
58
-func TestRequestIDMiddleware(t *testing.T) {
59
-	handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
60
-		if ctx.RequestID() == "" {
61
-			t.Fatalf("Expected request-id, got empty string")
62
-		}
63
-		return nil
64
-	}
65
-
66
-	h := requestIDMiddleware(handler)
67
-
68
-	req, _ := http.NewRequest("GET", "/containers/json", nil)
69
-	resp := httptest.NewRecorder()
70
-	ctx := context.Background()
71
-	if err := h(ctx, resp, req, map[string]string{}); err != nil {
72
-		t.Fatal(err)
73
-	}
74
-}
... ...
@@ -10,15 +10,14 @@ import (
10 10
 	"os"
11 11
 	"strings"
12 12
 
13
-	"github.com/gorilla/mux"
14
-
15 13
 	"github.com/Sirupsen/logrus"
16 14
 	"github.com/docker/distribution/registry/api/errcode"
17 15
 	"github.com/docker/docker/api"
18
-	"github.com/docker/docker/context"
19 16
 	"github.com/docker/docker/daemon"
20 17
 	"github.com/docker/docker/pkg/sockets"
21 18
 	"github.com/docker/docker/utils"
19
+	"github.com/gorilla/mux"
20
+	"golang.org/x/net/context"
22 21
 )
23 22
 
24 23
 // Config provides the configuration for the API server
... ...
@@ -5,7 +5,7 @@ import (
5 5
 	"net/http/httptest"
6 6
 	"testing"
7 7
 
8
-	"github.com/docker/docker/context"
8
+	"golang.org/x/net/context"
9 9
 )
10 10
 
11 11
 func TestMiddlewares(t *testing.T) {
... ...
@@ -19,12 +19,9 @@ func TestMiddlewares(t *testing.T) {
19 19
 	ctx := context.Background()
20 20
 
21 21
 	localHandler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
22
-		if ctx.Version() == "" {
22
+		if versionFromContext(ctx) == "" {
23 23
 			t.Fatalf("Expected version, got empty string")
24 24
 		}
25
-		if ctx.RequestID() == "" {
26
-			t.Fatalf("Expected request-id, got empty string")
27
-		}
28 25
 		return nil
29 26
 	}
30 27
 
... ...
@@ -5,7 +5,7 @@ import (
5 5
 	"net/http"
6 6
 
7 7
 	"github.com/docker/docker/api/types"
8
-	"github.com/docker/docker/context"
8
+	"golang.org/x/net/context"
9 9
 )
10 10
 
11 11
 func (s *Server) getVolumesList(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
12 12
deleted file mode 100644
... ...
@@ -1,64 +0,0 @@
1
-package context
2
-
3
-import (
4
-	"golang.org/x/net/context"
5
-
6
-	"github.com/docker/docker/pkg/version"
7
-)
8
-
9
-const (
10
-	// RequestID is the unique ID for each http request
11
-	RequestID = "request-id"
12
-
13
-	// APIVersion is the client's requested API version
14
-	APIVersion = "api-version"
15
-)
16
-
17
-// Context is just our own wrapper for the golang 'Context' - mainly
18
-// so we can add our over version of the funcs.
19
-type Context struct {
20
-	context.Context
21
-}
22
-
23
-// Background creates a new Context based on golang's default one.
24
-func Background() Context {
25
-	return Context{context.Background()}
26
-}
27
-
28
-// WithValue will return a Context that has this new key/value pair
29
-// associated with it. Just uses the golang version but then wraps it.
30
-func WithValue(ctx Context, key, value interface{}) Context {
31
-	return Context{context.WithValue(ctx, key, value)}
32
-}
33
-
34
-// RequestID is a utility func to make it easier to get the
35
-// request ID associated with this Context/request.
36
-func (ctx Context) RequestID() string {
37
-	val := ctx.Value(RequestID)
38
-	if val == nil {
39
-		return ""
40
-	}
41
-
42
-	id, ok := val.(string)
43
-	if !ok {
44
-		// Ideally we shouldn't panic but we also should never get here
45
-		panic("Context RequestID isn't a string")
46
-	}
47
-	return id
48
-}
49
-
50
-// Version is a utility func to make it easier to get the
51
-// API version string associated with this Context/request.
52
-func (ctx Context) Version() version.Version {
53
-	val := ctx.Value(APIVersion)
54
-	if val == nil {
55
-		return version.Version("")
56
-	}
57
-
58
-	ver, ok := val.(version.Version)
59
-	if !ok {
60
-		// Ideally we shouldn't panic but we also should never get here
61
-		panic("Context APIVersion isn't a version.Version")
62
-	}
63
-	return ver
64
-}
65 1
deleted file mode 100644
... ...
@@ -1,35 +0,0 @@
1
-package context
2
-
3
-import (
4
-	"testing"
5
-
6
-	"github.com/docker/docker/pkg/version"
7
-)
8
-
9
-func TestContext(t *testing.T) {
10
-	ctx := Background()
11
-
12
-	// First make sure getting non-existent values doesn't break
13
-	if id := ctx.RequestID(); id != "" {
14
-		t.Fatalf("RequestID() should have been '', was: %q", id)
15
-	}
16
-
17
-	if ver := ctx.Version(); ver != "" {
18
-		t.Fatalf("Version() should have been '', was: %q", ver)
19
-	}
20
-
21
-	// Test basic set/get
22
-	ctx = WithValue(ctx, RequestID, "123")
23
-	if ctx.RequestID() != "123" {
24
-		t.Fatalf("RequestID() should have been '123'")
25
-	}
26
-
27
-	// Now make sure after a 2nd set we can still get both
28
-	ctx = WithValue(ctx, APIVersion, version.Version("x.y"))
29
-	if id := ctx.RequestID(); id != "123" {
30
-		t.Fatalf("RequestID() should have been '123', was %q", id)
31
-	}
32
-	if ver := ctx.Version(); ver != "x.y" {
33
-		t.Fatalf("Version() should have been 'x.y', was %q", ver)
34
-	}
35
-}