Browse code

Error out if client API version is too old

Signed-off-by: Antonio Murdaca <runcom@linux.com>

Antonio Murdaca authored on 2015/06/18 06:57:32
Showing 6 changed files
... ...
@@ -138,7 +138,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
138 138
 	if err != nil {
139 139
 		return err
140 140
 	}
141
-	req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), params)
141
+	req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.Version, path), params)
142 142
 	if err != nil {
143 143
 		return err
144 144
 	}
... ...
@@ -53,7 +53,7 @@ func (cli *DockerCli) clientRequest(method, path string, in io.Reader, headers m
53 53
 	if expectedPayload && in == nil {
54 54
 		in = bytes.NewReader([]byte{})
55 55
 	}
56
-	req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), in)
56
+	req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.Version, path), in)
57 57
 	if err != nil {
58 58
 		return nil, nil, -1, err
59 59
 	}
... ...
@@ -26,7 +26,7 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
26 26
 	if dockerversion.VERSION != "" {
27 27
 		fmt.Fprintf(cli.out, "Client version: %s\n", dockerversion.VERSION)
28 28
 	}
29
-	fmt.Fprintf(cli.out, "Client API version: %s\n", api.APIVERSION)
29
+	fmt.Fprintf(cli.out, "Client API version: %s\n", api.Version)
30 30
 	fmt.Fprintf(cli.out, "Go version (client): %s\n", runtime.Version())
31 31
 	if dockerversion.GITCOMMIT != "" {
32 32
 		fmt.Fprintf(cli.out, "Git commit (client): %s\n", dockerversion.GITCOMMIT)
... ...
@@ -16,8 +16,14 @@ import (
16 16
 
17 17
 // Common constants for daemon and client.
18 18
 const (
19
-	APIVERSION            version.Version = "1.20"       // Current REST API version
20
-	DefaultDockerfileName string          = "Dockerfile" // Default filename with Docker commands, read by docker build
19
+	// Current REST API version
20
+	Version version.Version = "1.20"
21
+
22
+	// Minimun REST API version supported
23
+	MinVersion version.Version = "1.12"
24
+
25
+	// Default filename with Docker commands, read by docker build
26
+	DefaultDockerfileName string = "Dockerfile"
21 27
 )
22 28
 
23 29
 type ByPrivatePort []types.Port
... ...
@@ -244,7 +244,7 @@ func (s *Server) postAuth(version version.Version, w http.ResponseWriter, r *htt
244 244
 func (s *Server) getVersion(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
245 245
 	v := &types.Version{
246 246
 		Version:    dockerversion.VERSION,
247
-		ApiVersion: api.APIVERSION,
247
+		ApiVersion: api.Version,
248 248
 		GitCommit:  dockerversion.GITCOMMIT,
249 249
 		GoVersion:  runtime.Version(),
250 250
 		Os:         runtime.GOOS,
... ...
@@ -1477,14 +1477,18 @@ func makeHttpHandler(logging bool, localMethod string, localRoute string, handle
1477 1477
 		}
1478 1478
 		version := version.Version(mux.Vars(r)["version"])
1479 1479
 		if version == "" {
1480
-			version = api.APIVERSION
1480
+			version = api.Version
1481 1481
 		}
1482 1482
 		if corsHeaders != "" {
1483 1483
 			writeCorsHeaders(w, r, corsHeaders)
1484 1484
 		}
1485 1485
 
1486
-		if version.GreaterThan(api.APIVERSION) {
1487
-			http.Error(w, fmt.Errorf("client is newer than server (client API version: %s, server API version: %s)", version, api.APIVERSION).Error(), http.StatusBadRequest)
1486
+		if version.GreaterThan(api.Version) {
1487
+			http.Error(w, fmt.Errorf("client is newer than server (client API version: %s, server API version: %s)", version, api.Version).Error(), http.StatusBadRequest)
1488
+			return
1489
+		}
1490
+		if version.LessThan(api.MinVersion) {
1491
+			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)
1488 1492
 			return
1489 1493
 		}
1490 1494
 
... ...
@@ -3,15 +3,18 @@ package main
3 3
 import (
4 4
 	"net/http"
5 5
 	"net/http/httputil"
6
+	"strconv"
7
+	"strings"
6 8
 	"time"
7 9
 
10
+	"github.com/docker/docker/api"
8 11
 	"github.com/go-check/check"
9 12
 )
10 13
 
11 14
 func (s *DockerSuite) TestApiOptionsRoute(c *check.C) {
12 15
 	status, _, err := sockRequest("OPTIONS", "/", nil)
13
-	c.Assert(status, check.Equals, http.StatusOK)
14 16
 	c.Assert(err, check.IsNil)
17
+	c.Assert(status, check.Equals, http.StatusOK)
15 18
 }
16 19
 
17 20
 func (s *DockerSuite) TestApiGetEnabledCors(c *check.C) {
... ...
@@ -26,7 +29,7 @@ func (s *DockerSuite) TestApiGetEnabledCors(c *check.C) {
26 26
 	//c.Assert(res.Header.Get("Access-Control-Allow-Headers"), check.Equals, "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth")
27 27
 }
28 28
 
29
-func (s *DockerSuite) TestVersionStatusCode(c *check.C) {
29
+func (s *DockerSuite) TestApiVersionStatusCode(c *check.C) {
30 30
 	conn, err := sockConn(time.Duration(10 * time.Second))
31 31
 	c.Assert(err, check.IsNil)
32 32
 
... ...
@@ -40,3 +43,31 @@ func (s *DockerSuite) TestVersionStatusCode(c *check.C) {
40 40
 	res, err := client.Do(req)
41 41
 	c.Assert(res.StatusCode, check.Equals, http.StatusBadRequest)
42 42
 }
43
+
44
+func (s *DockerSuite) TestApiClientVersionNewerThanServer(c *check.C) {
45
+	v := strings.Split(string(api.Version), ".")
46
+	vMinInt, err := strconv.Atoi(v[1])
47
+	c.Assert(err, check.IsNil)
48
+	vMinInt++
49
+	v[1] = strconv.Itoa(vMinInt)
50
+	version := strings.Join(v, ".")
51
+
52
+	status, body, err := sockRequest("GET", "/v"+version+"/version", nil)
53
+	c.Assert(err, check.IsNil)
54
+	c.Assert(status, check.Equals, http.StatusBadRequest)
55
+	c.Assert(len(string(body)), check.Not(check.Equals), 0) // Expected not empty body
56
+}
57
+
58
+func (s *DockerSuite) TestApiClientVersionOldNotSupported(c *check.C) {
59
+	v := strings.Split(string(api.MinVersion), ".")
60
+	vMinInt, err := strconv.Atoi(v[1])
61
+	c.Assert(err, check.IsNil)
62
+	vMinInt--
63
+	v[1] = strconv.Itoa(vMinInt)
64
+	version := strings.Join(v, ".")
65
+
66
+	status, body, err := sockRequest("GET", "/v"+version+"/version", nil)
67
+	c.Assert(err, check.IsNil)
68
+	c.Assert(status, check.Equals, http.StatusBadRequest)
69
+	c.Assert(len(string(body)), check.Not(check.Equals), 0) // Expected not empty body
70
+}