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>
| ... | ... |
@@ -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 |
+} |