|
12 | 12 | import de.gesellix.docker.remote.api.EngineApiClient; |
13 | 13 | import de.gesellix.docker.remote.api.ExecConfig; |
14 | 14 | import de.gesellix.docker.remote.api.ExecStartConfig; |
| 15 | +import de.gesellix.docker.remote.api.HostConfig; |
15 | 16 | import de.gesellix.docker.remote.api.IdResponse; |
16 | 17 | import de.gesellix.docker.remote.api.RestartPolicy; |
17 | 18 | import de.gesellix.docker.remote.api.core.Cancellable; |
|
22 | 23 | import de.gesellix.docker.remote.api.testutil.DisabledIfDaemonOnWindowsOs; |
23 | 24 | import de.gesellix.docker.remote.api.testutil.DisabledIfNotPausable; |
24 | 25 | import de.gesellix.docker.remote.api.testutil.DockerEngineAvailable; |
| 26 | +import de.gesellix.docker.remote.api.testutil.EnabledIfSupportsWebSocket; |
25 | 27 | import de.gesellix.docker.remote.api.testutil.Failsafe; |
26 | 28 | import de.gesellix.docker.remote.api.testutil.InjectDockerClient; |
| 29 | +import de.gesellix.docker.remote.api.testutil.SocatContainer; |
27 | 30 | import de.gesellix.docker.remote.api.testutil.TarUtil; |
28 | 31 | import de.gesellix.docker.remote.api.testutil.TestImage; |
| 32 | +import de.gesellix.docker.websocket.DefaultWebSocketListener; |
| 33 | +import okhttp3.Response; |
| 34 | +import okhttp3.WebSocket; |
| 35 | +import okhttp3.WebSocketListener; |
29 | 36 | import okio.BufferedSink; |
| 37 | +import okio.ByteString; |
30 | 38 | import okio.Okio; |
31 | 39 | import okio.Sink; |
32 | 40 |
|
| 41 | +import org.jetbrains.annotations.NotNull; |
33 | 42 | import org.junit.jupiter.api.BeforeEach; |
34 | 43 | import org.junit.jupiter.api.Test; |
35 | 44 | import org.slf4j.Logger; |
|
48 | 57 | import java.util.TimerTask; |
49 | 58 | import java.util.UUID; |
50 | 59 | import java.util.concurrent.CountDownLatch; |
| 60 | +import java.util.concurrent.ExecutorService; |
| 61 | +import java.util.concurrent.Executors; |
| 62 | +import java.util.concurrent.TimeUnit; |
51 | 63 | import java.util.stream.Collectors; |
52 | 64 |
|
53 | 65 | import static de.gesellix.docker.remote.api.testutil.Constants.LABEL_KEY; |
54 | 66 | import static de.gesellix.docker.remote.api.testutil.Constants.LABEL_VALUE; |
55 | 67 | import static de.gesellix.docker.remote.api.testutil.Failsafe.removeContainer; |
| 68 | +import static de.gesellix.docker.websocket.WebsocketStatusCode.NORMAL_CLOSURE; |
56 | 69 | import static java.time.temporal.ChronoUnit.SECONDS; |
57 | 70 | import static java.util.Collections.singletonList; |
58 | 71 | import static java.util.Collections.singletonMap; |
@@ -220,18 +233,18 @@ public void containerArchiveInfoGetAndPut() throws IOException { |
220 | 233 | assertEquals("The wind\ncaught it.\n", fileContent.replaceAll("\r", "")); |
221 | 234 |
|
222 | 235 | String testPath = testImage.isWindowsContainer() |
223 | | - ? "tmp\\test" |
224 | | - : "/tmp/test/"; |
| 236 | + ? "tmp\\test" |
| 237 | + : "/tmp/test/"; |
225 | 238 | List<String> execCmd = testImage.isWindowsContainer() |
226 | | - ? Arrays.asList("cmd", "/C", "mkdir " + testPath) |
227 | | - : Arrays.asList("mkdir", testPath); |
| 239 | + ? Arrays.asList("cmd", "/C", "mkdir " + testPath) |
| 240 | + : Arrays.asList("mkdir", testPath); |
228 | 241 |
|
229 | 242 | containerApi.containerStart("container-archive-info-test", null); |
230 | 243 | IdResponse containerExec = engineApiClient.getExecApi().containerExec( |
231 | 244 | "container-archive-info-test", |
232 | 245 | new ExecConfig(null, null, null, null, null, null, null, |
233 | | - execCmd, |
234 | | - null, null, null)); |
| 246 | + execCmd, |
| 247 | + null, null, null)); |
235 | 248 | engineApiClient.getExecApi().execStart( |
236 | 249 | containerExec.getId(), |
237 | 250 | new ExecStartConfig(null, null, null)); |
@@ -391,8 +404,7 @@ public void run() { |
391 | 404 |
|
392 | 405 | try { |
393 | 406 | wait.await(); |
394 | | - } |
395 | | - catch (InterruptedException e) { |
| 407 | + } catch (InterruptedException e) { |
396 | 408 | e.printStackTrace(); |
397 | 409 | } |
398 | 410 |
|
@@ -453,8 +465,7 @@ public void run() { |
453 | 465 |
|
454 | 466 | try { |
455 | 467 | wait.await(); |
456 | | - } |
457 | | - catch (InterruptedException e) { |
| 468 | + } catch (InterruptedException e) { |
458 | 469 | e.printStackTrace(); |
459 | 470 | } |
460 | 471 | Optional<Frame> anyFrame = callback.frames.stream().findAny(); |
@@ -760,6 +771,103 @@ public void containerStatsOnce() { |
760 | 771 | removeContainer(engineApiClient, "container-stats-test"); |
761 | 772 | } |
762 | 773 |
|
| 774 | + @Test |
| 775 | + @EnabledIfSupportsWebSocket |
| 776 | + public void containerAttachWebSocketNonInteractive() throws InterruptedException { |
| 777 | + SocatContainer socatContainer = new SocatContainer(engineApiClient); |
| 778 | + EngineApiClient tcpClient = socatContainer.startSocatContainer(); |
| 779 | + |
| 780 | + removeContainer(engineApiClient, "container-attach-ws-non-interactive-test"); |
| 781 | + |
| 782 | + imageApi.imageCreate(testImage.getImageName(), null, null, testImage.getImageTag(), null, null, null, null, null); |
| 783 | + |
| 784 | + HostConfig hostConfig = new HostConfig(); |
| 785 | + hostConfig.setAutoRemove(true); |
| 786 | + ContainerCreateRequest containerCreateRequest = new ContainerCreateRequest( |
| 787 | + null, null, null, |
| 788 | + true, true, true, |
| 789 | + null, |
| 790 | + true, true, null, |
| 791 | + null, |
| 792 | + null, |
| 793 | + null, |
| 794 | + null, |
| 795 | + testImage.getImageWithTag(), |
| 796 | + null, null, singletonList("/cat"), |
| 797 | + null, null, |
| 798 | + null, |
| 799 | + singletonMap(LABEL_KEY, LABEL_VALUE), |
| 800 | + null, null, |
| 801 | + null, |
| 802 | + hostConfig, |
| 803 | + null |
| 804 | + ); |
| 805 | + containerApi.containerCreate(containerCreateRequest, "container-attach-ws-non-interactive-test"); |
| 806 | + containerApi.containerStart("container-attach-ws-non-interactive-test", null); |
| 807 | + |
| 808 | + ExecutorService executor = Executors.newSingleThreadExecutor(); |
| 809 | + String ourMessage = "hallo welt " + UUID.randomUUID(); |
| 810 | + |
| 811 | + CountDownLatch messageReceived = new CountDownLatch(1); |
| 812 | + List<String> receivedMessages = new ArrayList<>(); |
| 813 | + WebSocketListener listener = new DefaultWebSocketListener() { |
| 814 | + @Override |
| 815 | + public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) { |
| 816 | + super.onOpen(webSocket, response); |
| 817 | + executor.execute(() -> webSocket.send(ourMessage)); |
| 818 | + } |
| 819 | + |
| 820 | + @Override |
| 821 | + public void onFailure(@NotNull WebSocket webSocket, Throwable t, Response response) { |
| 822 | + super.onFailure(webSocket, t, response); |
| 823 | + } |
| 824 | + |
| 825 | + @Override |
| 826 | + public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) { |
| 827 | + super.onMessage(webSocket, text); |
| 828 | + receivedMessages.add(text); |
| 829 | + messageReceived.countDown(); |
| 830 | + } |
| 831 | + |
| 832 | + @Override |
| 833 | + public void onMessage(@NotNull WebSocket webSocket, ByteString bytes) { |
| 834 | + super.onMessage(webSocket, bytes); |
| 835 | + receivedMessages.add(bytes.utf8()); |
| 836 | + messageReceived.countDown(); |
| 837 | + } |
| 838 | + |
| 839 | + @Override |
| 840 | + public void onClosing(@NotNull WebSocket webSocket, int code, @NotNull String reason) { |
| 841 | + super.onClosing(webSocket, code, reason); |
| 842 | + } |
| 843 | + |
| 844 | + @Override |
| 845 | + public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) { |
| 846 | + super.onClosed(webSocket, code, reason); |
| 847 | + } |
| 848 | + }; |
| 849 | + |
| 850 | + WebSocket webSocket = tcpClient.getContainerApi().containerAttachWebsocket( |
| 851 | + "container-attach-ws-non-interactive-test", |
| 852 | + null, true, true, true, true, true, |
| 853 | + listener); |
| 854 | + |
| 855 | +// boolean enqueued = webSocket.send(ourMessage); |
| 856 | +// assertTrue(enqueued); |
| 857 | + |
| 858 | + Duration timeout = Duration.of(5, SECONDS); |
| 859 | + boolean success = messageReceived.await(timeout.toMillis(), TimeUnit.MILLISECONDS); |
| 860 | + |
| 861 | + webSocket.close(NORMAL_CLOSURE.getCode(), "cleanup"); |
| 862 | + socatContainer.stopSocatContainer(); |
| 863 | + |
| 864 | + assertTrue(success); |
| 865 | + |
| 866 | + assertTrue(receivedMessages.contains(ourMessage)); |
| 867 | + |
| 868 | + removeContainer(engineApiClient, "container-attach-ws-non-interactive-test"); |
| 869 | + } |
| 870 | + |
763 | 871 | @Test |
764 | 872 | public void containerAttachNonInteractive() { |
765 | 873 | removeContainer(engineApiClient, "container-attach-non-interactive-test"); |
@@ -809,8 +917,7 @@ public void run() { |
809 | 917 |
|
810 | 918 | try { |
811 | 919 | wait.await(); |
812 | | - } |
813 | | - catch (InterruptedException e) { |
| 920 | + } catch (InterruptedException e) { |
814 | 921 | e.printStackTrace(); |
815 | 922 | } |
816 | 923 |
|
@@ -893,8 +1000,7 @@ public void run() { |
893 | 1000 |
|
894 | 1001 | try { |
895 | 1002 | wait.await(); |
896 | | - } |
897 | | - catch (InterruptedException e) { |
| 1003 | + } catch (InterruptedException e) { |
898 | 1004 | e.printStackTrace(); |
899 | 1005 | } |
900 | 1006 | assertSame(Frame.StreamType.RAW, callback.frames.stream().findAny().get().getStreamType()); |
|
0 commit comments