Browse code

Add regression tests for invalid platform status codes

Before we handled containerd errors, using an invalid platform produced a 500 status:

```bash
curl -v \
-X POST \
--unix-socket /var/run/docker.sock \
"http://localhost:2375/v1.40/images/create?fromImage=hello-world&platform=foobar&tag=latest" \
-H "Content-Type: application/json"
```

```
* Connected to localhost (docker.sock) port 80 (#0)
> POST /v1.40/images/create?fromImage=hello-world&platform=foobar&tag=latest HTTP/1.1
> Host: localhost:2375
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Type: application/json
>
< HTTP/1.1 500 Internal Server Error
< Api-Version: 1.40
< Content-Length: 85
< Content-Type: application/json
< Date: Mon, 15 Jul 2019 15:25:44 GMT
< Docker-Experimental: true
< Ostype: linux
< Server: Docker/19.03.0-rc2 (linux)
<
{"message":"\"foobar\": unknown operating system or architecture: invalid argument"}
```

That problem is now fixed, and the API correctly returns a 4xx status:

```bash
curl -v \
-X POST \
--unix-socket /var/run/docker.sock \
"http://localhost:2375/v1.40/images/create?fromImage=hello-world&platform=foobar&tag=latest" \
-H "Content-Type: application/json"
```

```
* Connected to localhost (/var/run/docker.sock) port 80 (#0)
> POST /v1.40/images/create?fromImage=hello-world&platform=foobar&tag=latest HTTP/1.1
> Host: localhost:2375
> User-Agent: curl/7.52.1
> Accept: */*
> Content-Type: application/json
>
< HTTP/1.1 400 Bad Request
< Api-Version: 1.41
< Content-Type: application/json
< Docker-Experimental: true
< Ostype: linux
< Server: Docker/dev (linux)
< Date: Mon, 15 Jul 2019 15:13:42 GMT
< Content-Length: 85
<
{"message":"\"foobar\": unknown operating system or architecture: invalid argument"}
* Curl_http_done: called premature == 0
```

This patch adds tests to validate the behaviour

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2019/07/16 01:19:31
Showing 3 changed files
... ...
@@ -177,7 +177,7 @@ func statusCodeFromDistributionError(err error) int {
177 177
 }
178 178
 
179 179
 // statusCodeFromContainerdError returns status code for containerd errors when
180
-// consumed directory (not through gRPC)
180
+// consumed directly (not through gRPC)
181 181
 func statusCodeFromContainerdError(err error) int {
182 182
 	switch {
183 183
 	case containerderrors.IsInvalidArgument(err):
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"github.com/docker/docker/api/types"
14 14
 	"github.com/docker/docker/api/types/filters"
15 15
 	"github.com/docker/docker/api/types/versions"
16
+	"github.com/docker/docker/errdefs"
16 17
 	"github.com/docker/docker/internal/test/fakecontext"
17 18
 	"github.com/docker/docker/pkg/jsonmessage"
18 19
 	"gotest.tools/assert"
... ...
@@ -562,6 +563,35 @@ func TestBuildPreserveOwnership(t *testing.T) {
562 562
 	}
563 563
 }
564 564
 
565
+func TestBuildPlatformInvalid(t *testing.T) {
566
+	skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "experimental in older versions")
567
+
568
+	ctx := context.Background()
569
+	defer setupTest(t)()
570
+
571
+	dockerfile := `FROM busybox
572
+`
573
+
574
+	buf := bytes.NewBuffer(nil)
575
+	w := tar.NewWriter(buf)
576
+	writeTarRecord(t, w, "Dockerfile", dockerfile)
577
+	err := w.Close()
578
+	assert.NilError(t, err)
579
+
580
+	apiclient := testEnv.APIClient()
581
+	_, err = apiclient.ImageBuild(ctx,
582
+		buf,
583
+		types.ImageBuildOptions{
584
+			Remove:      true,
585
+			ForceRemove: true,
586
+			Platform:    "foobar",
587
+		})
588
+
589
+	assert.Assert(t, err != nil)
590
+	assert.ErrorContains(t, err, "unknown operating system or architecture")
591
+	assert.Assert(t, errdefs.IsInvalidParameter(err))
592
+}
593
+
565 594
 func writeTarRecord(t *testing.T, w *tar.Writer, fn, contents string) {
566 595
 	err := w.WriteHeader(&tar.Header{
567 596
 		Name:     fn,
568 597
new file mode 100644
... ...
@@ -0,0 +1,24 @@
0
+package image
1
+
2
+import (
3
+	"context"
4
+	"testing"
5
+
6
+	"github.com/docker/docker/api/types"
7
+	"github.com/docker/docker/api/types/versions"
8
+	"github.com/docker/docker/errdefs"
9
+	"gotest.tools/assert"
10
+	"gotest.tools/skip"
11
+)
12
+
13
+func TestImagePullPlatformInvalid(t *testing.T) {
14
+	skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "experimental in older versions")
15
+	defer setupTest(t)()
16
+	client := testEnv.APIClient()
17
+	ctx := context.Background()
18
+
19
+	_, err := client.ImagePull(ctx, "docker.io/library/hello-world:latest", types.ImagePullOptions{Platform: "foobar"})
20
+	assert.Assert(t, err != nil)
21
+	assert.ErrorContains(t, err, "unknown operating system or architecture")
22
+	assert.Assert(t, errdefs.IsInvalidParameter(err))
23
+}