From 7d4b8d5792c29eb89cc83ab246241094bdd0c63b Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Sun, 7 May 2023 21:08:42 +0200 Subject: [PATCH 1/4] chore --- .../docker/engine/OkDockerClientSpec.groovy | 51 +++++++++---------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/engine/src/test/groovy/de/gesellix/docker/engine/OkDockerClientSpec.groovy b/engine/src/test/groovy/de/gesellix/docker/engine/OkDockerClientSpec.groovy index 19961fd9..d4ce71b4 100644 --- a/engine/src/test/groovy/de/gesellix/docker/engine/OkDockerClientSpec.groovy +++ b/engine/src/test/groovy/de/gesellix/docker/engine/OkDockerClientSpec.groovy @@ -67,8 +67,7 @@ class OkDockerClientSpec extends Specification { cleanup: if (oldDockerHost) { System.setProperty("docker.host", oldDockerHost) - } - else { + } else { System.clearProperty("docker.host") } } @@ -108,8 +107,7 @@ class OkDockerClientSpec extends Specification { cleanup: if (oldDockerCertPath) { System.setProperty("docker.cert.path", oldDockerCertPath) - } - else { + } else { System.clearProperty("docker.cert.path") } } @@ -128,8 +126,7 @@ class OkDockerClientSpec extends Specification { cleanup: if (oldDockerCertPath) { System.setProperty("docker.cert.path", oldDockerCertPath) - } - else { + } else { System.clearProperty("docker.cert.path") } } @@ -322,8 +319,7 @@ class OkDockerClientSpec extends Specification { cleanup: if (oldDockerCertPath) { System.setProperty("docker.cert.path", oldDockerCertPath) - } - else { + } else { System.clearProperty("docker.cert.path") } } @@ -479,7 +475,7 @@ class OkDockerClientSpec extends Specification { when: def response = client.request(new EngineRequest(OPTIONS, "/a-resource") - .tap { apiVersion = "v1.23" }) + .tap { apiVersion = "v1.23" }) then: response.status.success and: @@ -522,7 +518,7 @@ class OkDockerClientSpec extends Specification { when: def response = client.request(new EngineRequest(OPTIONS, "/a-resource") - .tap { query = [baz: ["la/la"], answer: ["42"]] }) + .tap { query = [baz: ["la/la"], answer: ["42"]] }) then: response.status.success and: @@ -536,9 +532,9 @@ class OkDockerClientSpec extends Specification { given: def mockWebServer = new MockWebServer() mockWebServer.enqueue(new MockResponse() - .setResponseCode(101) - .addHeader("Connection", "Upgrade") - .addHeader("Upgrade", "tcp")) + .setResponseCode(101) + .addHeader("Connection", "Upgrade") + .addHeader("Upgrade", "tcp")) mockWebServer.start() def errors = [] @@ -575,14 +571,14 @@ class OkDockerClientSpec extends Specification { } client.request(new EngineRequest(OPTIONS, "/a-resource") - .tap { - attach = new AttachConfig(onResponse: onResponse) - headers = [ - "header-a" : "header-a-value", - "Upgrade" : "tcp", - "Connection": "Upgrade" - ] - }) + .tap { + attach = new AttachConfig(onResponse: onResponse) + headers = [ + "header-a" : "header-a-value", + "Upgrade" : "tcp", + "Connection": "Upgrade" + ] + }) then: latch.await(10, TimeUnit.SECONDS) and: @@ -675,8 +671,7 @@ class OkDockerClientSpec extends Specification { mockWebServer.shutdown() if (oldDockerCertPath) { System.setProperty("docker.cert.path", oldDockerCertPath) - } - else { + } else { System.clearProperty("docker.cert.path") } } @@ -785,7 +780,7 @@ class OkDockerClientSpec extends Specification { when: def response = client.request(new EngineRequest(OPTIONS, "/a-resource") - .tap { it.stdout = stdout }) + .tap { it.stdout = stdout }) then: stdout.toByteArray() == "holy ship".bytes @@ -859,7 +854,7 @@ class OkDockerClientSpec extends Specification { when: def response = client.request(new EngineRequest(OPTIONS, "/a-resource") - .tap { it.stdout = stdout }) + .tap { it.stdout = stdout }) then: stdout.toByteArray() == "holy ship".bytes @@ -946,7 +941,7 @@ class OkDockerClientSpec extends Specification { when: def response = client.request(new EngineRequest(OPTIONS, "/a-resource") - .tap { it.stdout = stdout }) + .tap { it.stdout = stdout }) then: stdout.toByteArray() == actualText.bytes @@ -1045,8 +1040,8 @@ class OkDockerClientSpec extends Specification { def hosts = isWindows ? new File("${System.getenv("SystemRoot")}\\System32\\drivers\\etc\\hosts") : new File("/etc/hosts") if (hosts.isFile()) { whitelist.addAll(hosts.readLines() - .grep({ it.startsWith("127.0.0.1 ") }) - .collect({ it.substring("127.0.0.1 ".length()).toLowerCase() })) + .grep({ it.startsWith("127.0.0.1 ") }) + .collect({ it.substring("127.0.0.1 ".length()).toLowerCase() })) } def isAllowed = host.toLowerCase() in whitelist || host.endsWith(".internal") if (!isAllowed) { From b4a2ffa3d4c31f2b3c301643d4f1fe82dccac96f Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Sun, 7 May 2023 21:10:46 +0200 Subject: [PATCH 2/4] bump gesellix/echo-server to 2023-04-05T20-08-00 --- .../test/groovy/de/gesellix/docker/engine/TestConstants.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrationtest/src/test/groovy/de/gesellix/docker/engine/TestConstants.groovy b/integrationtest/src/test/groovy/de/gesellix/docker/engine/TestConstants.groovy index 15d8b0f5..c0f13974 100644 --- a/integrationtest/src/test/groovy/de/gesellix/docker/engine/TestConstants.groovy +++ b/integrationtest/src/test/groovy/de/gesellix/docker/engine/TestConstants.groovy @@ -12,7 +12,7 @@ class TestConstants { TestConstants() { imageRepo = "gesellix/echo-server" - imageTag = "2023-03-12T23-40-00" + imageTag = "2023-04-05T20-08-00" imageName = "$imageRepo:$imageTag" if (System.getenv("GITHUB_ACTOR")) { From f45d7f6601d8dfa2b9614c810c74efa81a03d614 Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Sun, 7 May 2023 21:11:24 +0200 Subject: [PATCH 3/4] Accept the application/vnd.docker.multiplexed-stream response header as of api v1.42 --- .../docker/engine/OkDockerClient.java | 1 + .../docker/engine/OkDockerClientSpec.groovy | 95 ++++++++++++++++--- 2 files changed, 83 insertions(+), 13 deletions(-) diff --git a/engine/src/main/java/de/gesellix/docker/engine/OkDockerClient.java b/engine/src/main/java/de/gesellix/docker/engine/OkDockerClient.java index e536c722..ec6afb88 100644 --- a/engine/src/main/java/de/gesellix/docker/engine/OkDockerClient.java +++ b/engine/src/main/java/de/gesellix/docker/engine/OkDockerClient.java @@ -347,6 +347,7 @@ public EngineResponse handleResponse(Response httpResponse, EngineRequest config mimeType = ""; } switch (mimeType) { + case "application/vnd.docker.multiplexed-stream": case "application/vnd.docker.raw-stream": InputStream rawStream = new RawInputStream(body.byteStream()); if (config.getStdout() != null) { diff --git a/engine/src/test/groovy/de/gesellix/docker/engine/OkDockerClientSpec.groovy b/engine/src/test/groovy/de/gesellix/docker/engine/OkDockerClientSpec.groovy index d4ce71b4..fe8a8c3d 100644 --- a/engine/src/test/groovy/de/gesellix/docker/engine/OkDockerClientSpec.groovy +++ b/engine/src/test/groovy/de/gesellix/docker/engine/OkDockerClientSpec.groovy @@ -138,13 +138,14 @@ class OkDockerClientSpec extends Specification { expect: client.getMimeType(contentType) == expectedMimeType where: - contentType | expectedMimeType - null | null - "application/json" | "application/json" - "text/plain" | "text/plain" - "text/plain; charset=utf-8" | "text/plain" - "text/html" | "text/html" - "application/vnd.docker.raw-stream" | "application/vnd.docker.raw-stream" + contentType | expectedMimeType + null | null + "application/json" | "application/json" + "text/plain" | "text/plain" + "text/plain; charset=utf-8" | "text/plain" + "text/html" | "text/html" + "application/vnd.docker.raw-stream" | "application/vnd.docker.raw-stream" + "application/vnd.docker.multiplexed-stream" | "application/vnd.docker.multiplexed-stream" } def "getCharset"() { @@ -154,12 +155,13 @@ class OkDockerClientSpec extends Specification { expect: client.getCharset(contentType) == expectedCharset where: - contentType | expectedCharset - "application/json" | "utf-8" - "text/plain" | "utf-8" - "text/plain; charset=ISO-8859-1" | "ISO-8859-1" - "text/html" | "utf-8" - "application/vnd.docker.raw-stream" | "utf-8" + contentType | expectedCharset + "application/json" | "utf-8" + "text/plain" | "utf-8" + "text/plain; charset=ISO-8859-1" | "ISO-8859-1" + "text/html" | "utf-8" + "application/vnd.docker.raw-stream" | "utf-8" + "application/vnd.docker.multiplexed-stream" | "utf-8" } @Unroll @@ -953,6 +955,73 @@ class OkDockerClientSpec extends Specification { response.content == null } + def "request with docker multiplexed-stream response"() { + given: + def actualText = "holy ship" + def headerAndPayload = new RawHeaderAndPayload(STDOUT, actualText.bytes) + def responseBody = new ByteArrayInputStream(headerAndPayload.bytes as byte[]) + def mediaType = MediaType.parse("application/vnd.docker.multiplexed-stream") + def client = new OkDockerClient() { + + @Override + OkHttpClient newClient(OkHttpClient.Builder clientBuilder) { + clientBuilder + .addInterceptor(new ConstantResponseInterceptor(ResponseBody.create(responseBody.bytes, mediaType))) + .build() + } + } + client.dockerClientConfig.apply(new DockerEnv(dockerHost: "http://127.0.0.1:2375")) + + when: + def response = client.request(new EngineRequest(OPTIONS, "/a-resource")) + + then: + response.stream instanceof RawInputStream + and: + IOUtils.toString(response.stream as RawInputStream) == actualText + and: + response.content == null + } + + def "request with docker multiplexed-stream response on stdout"() { + given: + def actualText = "holy ship" + def headerAndPayload = new RawHeaderAndPayload(STDOUT, actualText.bytes) + def responseBody = new ByteArrayInputStream(headerAndPayload.bytes as byte[]) + def mediaType = MediaType.parse("application/vnd.docker.multiplexed-stream") + def client = new OkDockerClient() { + + @Override + OkHttpClient newClient(OkHttpClient.Builder clientBuilder) { + clientBuilder + .addInterceptor(new ConstantResponseInterceptor(ResponseBody.create(responseBody.bytes, mediaType))) + .build() + } + } + client.dockerClientConfig.apply(new DockerEnv(dockerHost: "https://127.0.0.1:2376")) + client.socketFactories["https"] = new SslSocketConfigFactory() { + + @Override + DockerSslSocket createDockerSslSocket(String certPath) { + return null + } + } + def stdout = new ByteArrayOutputStream() + + when: + def response = client.request(new EngineRequest(OPTIONS, "/a-resource") + .tap { it.stdout = stdout }) + + then: + stdout.toByteArray() == actualText.bytes + and: + responseBody.available() == 0 + and: + response.stream == null + and: + response.content == null + } + static class TestContentHandlerFactory implements ContentHandlerFactory { def contentHandler = null From 17aa04c217f3f498db5e2b2f0078e3dfc9f9bbd9 Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Sun, 7 May 2023 21:25:40 +0200 Subject: [PATCH 4/4] Bump test constants --- .../groovy/de/gesellix/docker/engine/TestConstants.groovy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integrationtest/src/test/groovy/de/gesellix/docker/engine/TestConstants.groovy b/integrationtest/src/test/groovy/de/gesellix/docker/engine/TestConstants.groovy index c0f13974..1b498931 100644 --- a/integrationtest/src/test/groovy/de/gesellix/docker/engine/TestConstants.groovy +++ b/integrationtest/src/test/groovy/de/gesellix/docker/engine/TestConstants.groovy @@ -19,11 +19,11 @@ class TestConstants { // TODO consider checking the Docker api version instead of "GITHUB_ACTOR" if (LocalDocker.isNativeWindows()) { versionDetails = [ - ApiVersion : { it == "1.41" }, + ApiVersion : { it == "1.42" }, Arch : { it in ["amd64", "arm64"] }, - BuildTime : { it =~ "2022-\\d{2}-\\d{2}T\\w+" }, + BuildTime : { it =~ "2023-\\d{2}-\\d{2}T\\w+" }, GitCommit : { it =~ "\\w{6,}" }, - GoVersion : { it == "go1.18.7" }, + GoVersion : { it == "go1.19.8" }, KernelVersion: { it =~ "\\d.\\d{1,2}.\\d{1,2}\\w*" }, MinAPIVersion: { it == "1.24" }, Os : { it == "windows" },