stream = Stream.generate(
+ () -> {
+ JsonObject read = null;
+ try {
+ final byte[] tmp = new byte[4096];
+ while (content.read(tmp) != -1) {
+ try {
+ final JsonReader reader = Json.createReader(
+ new ByteArrayInputStream(tmp)
+ );
+ read = reader.readObject();
+ break;
+ //@checkstyle IllegalCatch (1 line)
+ } catch (final Exception exception) {
+ //Couldn't parse byte[] to Json,
+ //try to read more bytes.
+ }
+ }
+ } catch (final IOException ex) {
+ throw new IllegalStateException(
+ "IOException when reading streamed JsonObjects!"
+ );
+ }
+ return read;
+ }
+ ).onClose(
+ () -> {
+ try {
+ ((CloseableHttpResponse) response).close();
+ } catch (final IOException ex) {
+ //There is a bug in Apache HTTPClient, when closing
+ //an infinite InputStream: IOException is thrown
+ //because the client still tries to read the remainder
+ // of the closed Stream. We should ignore this case.
+ }
+ }
+ );
+ return stream;
+ }
+ }
+
+ @Override
+ public Docker docker() {
+ return this.docker;
+ }
+
+ /**
+ * Build up the URI for the monitoring operation.
+ * Add the since/until query params if they are present
+ * and also add the filters.
+ * @return URI.
+ */
+ private URI buildMonitorUri() {
+ final URIBuilder uriBuilder = new UncheckedUriBuilder(
+ this.baseUri.toString()
+ );
+ if (this.since != null) {
+ uriBuilder.addParameter(
+ "since",
+ String.valueOf(
+ ZonedDateTime.of(
+ this.since, ZoneId.systemDefault()
+ ).toInstant().toEpochMilli()
+ )
+ );
+ }
+ if (this.until != null) {
+ uriBuilder.addParameter(
+ "until",
+ String.valueOf(
+ ZonedDateTime.of(
+ this.until, ZoneId.systemDefault()
+ ).toInstant().toEpochMilli()
+ )
+ );
+ }
+ final FilteredUriBuilder uri = new FilteredUriBuilder(
+ uriBuilder,
+ this.filters
+ );
+ return uri.build();
+ }
+}
diff --git a/src/main/java/com/amihaiemil/docker/RtExec.java b/src/main/java/com/amihaiemil/docker/RtExec.java
new file mode 100644
index 00000000..213e5a67
--- /dev/null
+++ b/src/main/java/com/amihaiemil/docker/RtExec.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2018-2020, Mihai Emil Andronache
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1)Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2)Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3)Neither the name of docker-java-api nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.amihaiemil.docker;
+
+import org.apache.http.client.HttpClient;
+
+import javax.json.JsonObject;
+import java.io.IOException;
+import java.net.URI;
+
+/**
+ * Exec. A batch of commands that are running inside a Container.
+ * @author Mihai Andronache (amihaiemil@gmail.com)
+ * @version $Id$
+ * @since 0.0.12
+ */
+final class RtExec implements Exec {
+ /**
+ * Apache HttpClient which sends the requests.
+ */
+ private final HttpClient client;
+
+ /**
+ * URI of this Exec.
+ */
+ private final URI baseUri;
+
+ /**
+ * Docker API.
+ */
+ private final Docker docker;
+
+ /**
+ * Ctor.
+ * @param client HTTP Client used to send the requests.
+ * @param uri The URI for this Images API.
+ * @param dkr The docker entry point.
+ * @checkstyle ParameterNumber (10 lines)
+ */
+ RtExec(final HttpClient client, final URI uri, final Docker dkr) {
+ this.client = client;
+ this.baseUri = uri;
+ this.docker = dkr;
+ }
+
+ @Override
+ public JsonObject inspect()
+ throws IOException, UnexpectedResponseException {
+ return new Inspection(this.client, this.baseUri.toString() + "/json");
+ }
+
+}
diff --git a/src/main/java/com/amihaiemil/docker/RtExecs.java b/src/main/java/com/amihaiemil/docker/RtExecs.java
new file mode 100644
index 00000000..e359b609
--- /dev/null
+++ b/src/main/java/com/amihaiemil/docker/RtExecs.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2018-2020, Mihai Emil Andronache
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1)Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2)Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3)Neither the name of docker-java-api nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.amihaiemil.docker;
+
+import org.apache.http.client.HttpClient;
+
+import java.net.URI;
+
+/**
+ * RESTful Execs API.
+ * @author Mihai Andronache (amihaiemil@gmail.com)
+ * @version $Id$
+ * @since 0.0.12
+ */
+final class RtExecs implements Execs {
+ /**
+ * Apache HttpClient which sends the requests.
+ */
+ private final HttpClient client;
+
+ /**
+ * Base URI for the Exec API.
+ */
+ private final URI baseUri;
+
+ /**
+ * Docker API.
+ */
+ private final Docker docker;
+
+ /**
+ * Ctor.
+ * @param client HTTP Client used to send the requests.
+ * @param uri The URI for this Images API.
+ * @param dkr The docker entry point.
+ * @checkstyle ParameterNumber (10 lines)
+ */
+ RtExecs(final HttpClient client, final URI uri, final Docker dkr) {
+ this.client = client;
+ this.baseUri = uri;
+ this.docker = dkr;
+ }
+
+ @Override
+ public Exec get(final String execId) {
+ return new RtExec(
+ this.client,
+ URI.create(this.baseUri.toString() + "/" + execId),
+ this.docker
+ );
+ }
+
+ @Override
+ public Docker docker() {
+ return this.docker;
+ }
+}
diff --git a/src/main/java/com/amihaiemil/docker/RtInfo.java b/src/main/java/com/amihaiemil/docker/RtInfo.java
new file mode 100644
index 00000000..65db46bc
--- /dev/null
+++ b/src/main/java/com/amihaiemil/docker/RtInfo.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2018-2020, Mihai Emil Andronache
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1)Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2)Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3)Neither the name of docker-java-api nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.amihaiemil.docker;
+
+import javax.json.JsonObject;
+
+/**
+ * Info about the Docker engine, in JSON format.
+ * @author Mihai Andronache (amihaiemil@gmail.com)
+ * @version $Id$
+ * @since 0.0.13
+ */
+final class RtInfo extends JsonResource implements Info {
+
+ /**
+ * Docker to which iot refers to.
+ */
+ private final Docker docker;
+
+ /**
+ * Constructor.
+ * @param rep This info in JSON format.
+ * @param docker The Docker to which it refers to.
+ */
+ RtInfo(final JsonObject rep, final Docker docker) {
+ super(rep);
+ this.docker = docker;
+ }
+
+ @Override
+ public Docker docker() {
+ return this.docker;
+ }
+}
diff --git a/src/main/java/com/amihaiemil/docker/RtLogs.java b/src/main/java/com/amihaiemil/docker/RtLogs.java
index 38da2adc..7b982ab8 100644
--- a/src/main/java/com/amihaiemil/docker/RtLogs.java
+++ b/src/main/java/com/amihaiemil/docker/RtLogs.java
@@ -110,7 +110,7 @@ public String fetch() throws IOException, UnexpectedResponseException {
try {
return this.client.execute(
fetch,
- new ReadString(
+ new ReadLogString(
new MatchStatus(
fetch.getURI(),
HttpStatus.SC_OK
diff --git a/src/main/java/com/amihaiemil/docker/RtVersion.java b/src/main/java/com/amihaiemil/docker/RtVersion.java
index fc9718df..42fb3176 100644
--- a/src/main/java/com/amihaiemil/docker/RtVersion.java
+++ b/src/main/java/com/amihaiemil/docker/RtVersion.java
@@ -39,14 +39,26 @@
* @since 0.0.11
*/
final class RtVersion extends JsonResource implements Version {
+
+ /**
+ * Docker to which this Version belongs.
+ */
+ private final Docker docker;
+
/**
* Ctor.
* @param client The http client.
* @param uri The URI for this version.
+ * @param dkr Parent Docker.
* @throws IOException If an I/O error occurs.
*/
- RtVersion(final HttpClient client, final URI uri) throws IOException {
+ RtVersion(
+ final HttpClient client,
+ final URI uri,
+ final Docker dkr
+ ) throws IOException {
super(fetch(client, uri));
+ this.docker = dkr;
}
/**
@@ -134,4 +146,9 @@ public String arch() {
public boolean experimental() {
return this.getBoolean("Experimental");
}
+
+ @Override
+ public Docker docker() {
+ return this.docker;
+ }
}
diff --git a/src/main/java/com/amihaiemil/docker/TcpDocker.java b/src/main/java/com/amihaiemil/docker/TcpDocker.java
new file mode 100644
index 00000000..8b54980c
--- /dev/null
+++ b/src/main/java/com/amihaiemil/docker/TcpDocker.java
@@ -0,0 +1,127 @@
+/**
+ * Copyright (c) 2018-2019, Mihai Emil Andronache
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1)Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2)Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3)Neither the name of docker-java-api nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.amihaiemil.docker;
+
+import java.net.URI;
+import java.nio.file.Path;
+
+import org.apache.http.client.HttpClient;
+
+/**
+ * Use this to communicate with a remote Docker API.
+ *
+ * @author George Aristy (george.aristy@gmail.com)
+ * @version $Id$
+ * @since 0.0.1
+ * @checkstyle ParameterNumber (150 lines)
+ */
+public final class TcpDocker extends RtDocker {
+
+ /**
+ * Tcp Docker engine. API version is 1.35 by default.
+ * @param uri Remote Docker URI.
+ * @param keys Path to the keystore.
+ * @param trust Path to the truststore.
+ * @param storePwd Password for the keystore.
+ * @param keyPwd Passphrase for the key.
+ */
+ TcpDocker(
+ final URI uri, final Path keys, final Path trust,
+ final char[] storePwd, final char[] keyPwd) {
+ this(uri, "v1.35", keys, trust, storePwd, keyPwd);
+ }
+
+ /**
+ * Tcp Docker engine.
+ * @param uri Remote Docker URI.
+ * @param version API version (eg. v1.35).
+ * @param keys Path to the keystore.
+ * @param trust Path to the truststore.
+ * @param storePwd Password for the keystore.
+ * @param keyPwd Passphrase for the key.
+ */
+ TcpDocker(
+ final URI uri, final String version,
+ final Path keys, final Path trust,
+ final char[] storePwd, final char[] keyPwd) {
+ this(
+ new SslHttpClient(keys, trust, storePwd, keyPwd),
+ uri, version
+ );
+ }
+
+ /**
+ * Tcp Docker engine.
+ *
+ * An insecure docker API v1.35 endpoint is assumed.
+ *
+ * @param uri Remote Docker URI.
+ */
+ public TcpDocker(final URI uri) {
+ this(new PlainHttpClient(), uri);
+ }
+
+ /**
+ * Tcp Docker engine.
+ *
+ * An insecure docker API v1.35 endpoint is assumed.
+ *
+ * @param uri Remote Docker URI.
+ * @param auth Remote Docker {@link Auth}
+ */
+ public TcpDocker(final URI uri, final Auth auth) {
+ this(new AuthHttpClient(new PlainHttpClient(), auth), uri);
+ }
+
+ /**
+ * Tcp Docker engine. You have to configure your own HttpClient,
+ * most likely with some authentication mechanism, depending on where
+ * the Docker engine is on the Network.
+ *
+ * By default, the API version is 1.35.
+ *
+ * @param client The http client to use.
+ * @param uri Remote Docker URI.
+ */
+ public TcpDocker(final HttpClient client, final URI uri) {
+ this(client, uri, "v1.35");
+ }
+
+ /**
+ * Tcp Docker engine. You have to configure your own HttpClient,
+ * most likely with some authentication mechanism, depending on where
+ * the Docker engine is on the Network.
+ *
+ * @param client The http client to use.
+ * @param uri Remote Docker URI.
+ * @param version API version (eg. v1.35).
+ */
+ public TcpDocker(
+ final HttpClient client, final URI uri, final String version
+ ) {
+ super(client, URI.create(uri.toString() + "/" + version));
+ }
+}
diff --git a/src/main/java/com/amihaiemil/docker/UnixDocker.java b/src/main/java/com/amihaiemil/docker/UnixDocker.java
new file mode 100644
index 00000000..02f27054
--- /dev/null
+++ b/src/main/java/com/amihaiemil/docker/UnixDocker.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2018-2019, Mihai Emil Andronache
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1)Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2)Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3)Neither the name of docker-java-api nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.amihaiemil.docker;
+
+import java.io.File;
+import java.net.URI;
+import org.apache.http.client.HttpClient;
+
+/**
+ * Local Docker API. Use this when you want to communicate with the local
+ * Docker engine.
+ *
+ *
+ * final Docker docker = new LocalUnixDocker("unix:///var/run/docker.sock");
+ *
+ *
+ * This implementation manages an internal pool of 10 http connections. Users
+ * who wish to alter this behaviour may provide their own {@link HttpClient}
+ * via the specific constructor.
+ *
+ * @author Mihai Andronache (amihaiemil@gmail.com)
+ * @version $Id$
+ * @since 0.0.1
+ */
+public final class UnixDocker extends RtDocker {
+
+ /**
+ * Unix Docker engine.
+ * @param unixSocket Unix socket File on disk.
+ * (most likely /var/run/docker.sock).
+ */
+ public UnixDocker(final File unixSocket){
+ this(unixSocket, "v1.35");
+ }
+
+ /**
+ * Unix Docker engine.
+ * @param unixSocket Unix socket File on disk.
+ * (most likely /var/run/docker.sock).
+ * @param version API version (e.g. v1.30).
+ */
+ public UnixDocker(final File unixSocket, final String version){
+ this(new UnixHttpClient(unixSocket), version);
+ }
+
+ /**
+ * Unix Docker engine.
+ *
+ * Users may supply their own {@link HttpClient} that must register a
+ * {@link UnixSocketFactory}.
+ * @param client The http client to use.
+ * @param version API version (e.g. v1.30).
+ */
+ public UnixDocker(final HttpClient client, final String version) {
+ super(client, URI.create("unix://localhost:80/" + version));
+ }
+
+}
diff --git a/src/main/java/com/amihaiemil/docker/Version.java b/src/main/java/com/amihaiemil/docker/Version.java
index 09601a13..5b6c35eb 100644
--- a/src/main/java/com/amihaiemil/docker/Version.java
+++ b/src/main/java/com/amihaiemil/docker/Version.java
@@ -49,4 +49,10 @@ public interface Version extends JsonObject {
* @return Whether experimental docker features are enabled
*/
boolean experimental();
+
+ /**
+ * The Docker engine to which this Version belongs.
+ * @return Docker.
+ */
+ Docker docker();
}
diff --git a/src/test/java/com/amihaiemil/docker/ListedContainersTestCase.java b/src/test/java/com/amihaiemil/docker/ListedContainersTestCase.java
index 29b8d3f7..5ec7d7e6 100644
--- a/src/test/java/com/amihaiemil/docker/ListedContainersTestCase.java
+++ b/src/test/java/com/amihaiemil/docker/ListedContainersTestCase.java
@@ -49,7 +49,7 @@ public final class ListedContainersTestCase {
*/
@Test
public void iterateAll() {
- Docker docker = new LocalDocker(
+ Docker docker = new UnixDocker(
new AssertRequest(
new Response(
HttpStatus.SC_OK,
@@ -116,7 +116,7 @@ public void includeFiltersInRequest() {
"randomLabel=test"
)
);
- new LocalDocker(
+ new UnixDocker(
new AssertRequest(
new Response(
HttpStatus.SC_OK,
@@ -159,7 +159,7 @@ public void includeAddedFiltersInRequest() {
);
final Map> added = new HashMap<>();
added.put("dangling", Collections.singletonList("true"));
- new LocalDocker(
+ new UnixDocker(
new AssertRequest(
new Response(
HttpStatus.SC_OK,
diff --git a/src/test/java/com/amihaiemil/docker/ListedNetworksTestCase.java b/src/test/java/com/amihaiemil/docker/ListedNetworksTestCase.java
index 61447e52..f84a811a 100644
--- a/src/test/java/com/amihaiemil/docker/ListedNetworksTestCase.java
+++ b/src/test/java/com/amihaiemil/docker/ListedNetworksTestCase.java
@@ -100,6 +100,51 @@ public void filterResults() throws IOException {
);
}
+ /**
+ * {@link ListedNetworks} can filter networks
+ * filters.
+ */
+ @Test
+ public void filterTest() {
+ final Map> filters = new HashMap<>();
+ filters.put(
+ "scope",
+ Arrays.asList(
+ "local"
+ )
+ );
+ MatcherAssert.assertThat(
+ "Could not filter networks",
+ new ListedNetworks(
+ //@checkstyle LineLength (50 lines)
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_OK,
+ "[{\"Id\": \"id1\", \"scope\":\"local\"}, {\"Id\":\"cde2\"}]"
+ ),
+ new Condition(
+ // @checkstyle LineLength (11 lines)
+ "iterate() query parameters must include the filters provided",
+ req -> {
+ final List params = new UncheckedUriBuilder(
+ req.getRequestLine().getUri()
+ ).getQueryParams();
+ // @checkstyle BooleanExpressionComplexity (5 lines)
+ return params.size() == 1
+ && "filters".equals(params.get(0).getName())
+ && params.get(0).getValue().contains("scope")
+ && params.get(0).getValue().contains("local");
+ }
+ )
+ ),
+ URI.create("http://localhost/networks/id1"),
+ DOCKER
+ ).filter(filters).iterator().next().getString("Id"),
+ new IsEqual<>("id1")
+ );
+
+ }
+
/**
* {@link ListedNetworks} can iterate over them without
* filters.
diff --git a/src/test/java/com/amihaiemil/docker/LocalDockerITCase.java b/src/test/java/com/amihaiemil/docker/LocalDockerITCase.java
index 4785b2a0..f48bec1d 100644
--- a/src/test/java/com/amihaiemil/docker/LocalDockerITCase.java
+++ b/src/test/java/com/amihaiemil/docker/LocalDockerITCase.java
@@ -26,19 +26,16 @@
package com.amihaiemil.docker;
import java.io.File;
-import java.io.Reader;
import java.nio.file.Paths;
-import org.apache.commons.io.IOUtils;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.hamcrest.collection.IsIterableWithSize;
import org.junit.Test;
-import org.junit.Ignore;
import org.mockito.internal.matchers.GreaterOrEqual;
/**
- * Integration tests for LocalDocker.
+ * Integration tests for LocalUnixDocker.
* @author Mihai Andronache (amihaiemil@gmail.com)
* @version $Id$
* @since 0.0.1
@@ -46,7 +43,7 @@
public final class LocalDockerITCase {
/**
- * LocalDocker can ping the Docker Engine.
+ * LocalUnixDocker can ping the Docker Engine.
* @throws Exception If something goes wrong.
*/
@Test
@@ -56,25 +53,9 @@ public void pingsDocker() throws Exception {
);
MatcherAssert.assertThat(docker.ping(), Matchers.is(Boolean.TRUE));
}
+
/**
- * Docker can follow the events stream. Ignored for now,
- * doesn't work yet.
- * @throws Exception If something goes wrong.
- */
- @Test
- @Ignore
- public void followsEvents() throws Exception {
- final Reader reader = new LocalDocker(
- new File("/var/run/docker.sock")
- ).events();
- final String events = IOUtils.toString(reader);
- MatcherAssert.assertThat(
- events.trim(),
- Matchers.notNullValue()
- );
- }
- /**
- * LocalDocker can list {@link Volumes}.
+ * LocalUnixDocker can list {@link Volumes}.
* @throws Exception If something goes wrong.
*/
@Test
diff --git a/src/test/java/com/amihaiemil/docker/LocalDockerTestCase.java b/src/test/java/com/amihaiemil/docker/LocalDockerTestCase.java
index e4ca6b6e..3663814c 100644
--- a/src/test/java/com/amihaiemil/docker/LocalDockerTestCase.java
+++ b/src/test/java/com/amihaiemil/docker/LocalDockerTestCase.java
@@ -34,7 +34,7 @@
import org.junit.Test;
/**
- * Unit tests for LocalDocker.
+ * Unit tests for LocalUnixDocker.
* @author Mihai Andronache (amihaiemil@gmail.com)
* @version $Id$
* @since 0.0.1
@@ -42,7 +42,7 @@
public final class LocalDockerTestCase {
/**
- * LocalDocker can be instantiated.
+ * LocalUnixDocker can be instantiated.
*/
@Test
public void canBeInstantiate() {
@@ -89,7 +89,7 @@ public void pingFalseIfResponseIsNotOk() throws Exception {
}
/**
- * LocalDocker can return the Containers.
+ * LocalUnixDocker can return the Containers.
*/
@Test
public void getsContainers() {
@@ -102,7 +102,7 @@ public void getsContainers() {
}
/**
- * LocalDocker can return the Swarm.
+ * LocalUnixDocker can return the Swarm.
*/
@Test
public void returnsSwarm() {
@@ -115,7 +115,7 @@ public void returnsSwarm() {
}
/**
- * LocalDocker can return Images.
+ * LocalUnixDocker can return Images.
*/
@Test
public void returnsImages() {
@@ -128,7 +128,7 @@ public void returnsImages() {
}
/**
- * LocalDocker can return its HttpClient.
+ * LocalUnixDocker can return its HttpClient.
*/
@Test
public void returnsHttpClient() {
@@ -144,7 +144,7 @@ public void returnsHttpClient() {
}
/**
- * LocalDocker can return Volumes.
+ * LocalUnixDocker can return Volumes.
*/
@Test
public void returnsVolumes() {
@@ -157,27 +157,33 @@ public void returnsVolumes() {
}
/**
- * LocalDocker throws UnsupportedOperationException for Networks.
+ * LocalUnixDocker can return Networks.
*/
- @Test(expected = UnsupportedOperationException.class)
- public void unsupportedOperationNetworks() {
- new LocalDocker(
- new File("/var/run/docker.sock")
- ).networks();
+ @Test
+ public void returnsNetworks() {
+ MatcherAssert.assertThat(
+ new LocalDocker(
+ new File("/var/run/docker.sock")
+ ).networks(),
+ Matchers.notNullValue()
+ );
}
/**
- * LocalDocker throws UnsupportedOperationException for Exec.
+ * LocalUnixDocker can return Execs.
*/
- @Test(expected = UnsupportedOperationException.class)
- public void unsupportedOperationExec() {
- new LocalDocker(
- new File("/var/run/docker.sock")
- ).exec();
+ @Test
+ public void returnsExecs() {
+ MatcherAssert.assertThat(
+ new LocalDocker(
+ new File("/var/run/docker.sock")
+ ).execs(),
+ Matchers.notNullValue()
+ );
}
/**
- * LocalDocker throws UnsupportedOperationException for Plugins.
+ * LocalUnixDocker throws UnsupportedOperationException for Plugins.
*/
@Test(expected = UnsupportedOperationException.class)
public void unsupportedOperationPlugins() {
diff --git a/src/test/java/com/amihaiemil/docker/RemoteDockerTestCase.java b/src/test/java/com/amihaiemil/docker/RemoteDockerTestCase.java
index 5945a375..89294b9b 100644
--- a/src/test/java/com/amihaiemil/docker/RemoteDockerTestCase.java
+++ b/src/test/java/com/amihaiemil/docker/RemoteDockerTestCase.java
@@ -81,7 +81,7 @@ public void pingFalseIfResponseIsNotOk() throws Exception {
}
/**
- * RemoteDocker can return the Containers.
+ * RemoteTcpDockercan return the Containers.
*/
@Test
public void getsContainers() {
@@ -95,7 +95,7 @@ public void getsContainers() {
}
/**
- * RemoteDocker can return the Swarm.
+ * RemoteTcpDockercan return the Swarm.
*/
@Test
public void returnsSwarm() {
@@ -110,7 +110,7 @@ public void returnsSwarm() {
/**
- * RemoteDocker can return Images.
+ * RemoteTcpDockercan return Images.
*/
@Test
public void returnsImages() {
@@ -124,7 +124,7 @@ public void returnsImages() {
}
/**
- * LocalDocker can return its HttpClient.
+ * LocalUnixDocker can return its HttpClient.
*/
@Test
public void returnsHttpClient() {
@@ -142,7 +142,7 @@ public void returnsHttpClient() {
}
/**
- * LocalDocker should have AuthHttpClient.
+ * LocalUnixDocker should have AuthHttpClient.
*/
@Test
public void returnsAuthHttpClient() {
@@ -159,7 +159,7 @@ public void returnsAuthHttpClient() {
}
/**
- * RemoteDocker can return Volumes.
+ * RemoteTcpDockercan return Volumes.
*/
@Test
public void returnsVolumes() {
diff --git a/src/test/java/com/amihaiemil/docker/RtContainerITCase.java b/src/test/java/com/amihaiemil/docker/RtContainerITCase.java
index a008b7b9..7a23b5b8 100644
--- a/src/test/java/com/amihaiemil/docker/RtContainerITCase.java
+++ b/src/test/java/com/amihaiemil/docker/RtContainerITCase.java
@@ -49,7 +49,7 @@ public final class RtContainerITCase {
*/
@Test
public void renamesContainer() throws Exception {
- final Container container = new LocalDocker(
+ final Container container = new UnixDocker(
new File("/var/run/docker.sock")
).containers().create("Toomes", "hello-world");
MatcherAssert.assertThat(
@@ -70,7 +70,7 @@ public void renamesContainer() throws Exception {
*/
@Test
public void startStopContainer() throws Exception {
- final Container container = new LocalDocker(
+ final Container container = new UnixDocker(
new File("/var/run/docker.sock")
).containers().create("TestStart", this.containerJsonObject());
container.start();
@@ -88,7 +88,7 @@ public void startStopContainer() throws Exception {
*/
@Test
public void killContainer() throws Exception {
- final Container container = new LocalDocker(
+ final Container container = new UnixDocker(
new File("/var/run/docker.sock")
).containers().create("TestKill", this.containerJsonObject());
container.start();
@@ -110,7 +110,8 @@ public void killContainer() throws Exception {
*/
@Test
public void restartContainer() throws Exception {
- final Container container = new LocalDocker(
+ final Container container = new UnixDocker(
+
new File("/var/run/docker.sock")
).containers().create("TestRestart", this.containerJsonObject());
container.start();
@@ -145,7 +146,7 @@ private JsonObject containerJsonObject() {
*/
@Test
public void pauseContainer() throws Exception {
- final Container container = new LocalDocker(
+ final Container container = new UnixDocker(
new File("/var/run/docker.sock")
).containers().create("TestPause", this.containerJsonObject());
container.start();
@@ -164,7 +165,8 @@ public void pauseContainer() throws Exception {
*/
@Test
public void unpauseContainer() throws Exception {
- final Container container = new LocalDocker(
+ final Container container = new UnixDocker(
+
new File("/var/run/docker.sock")
).containers().create("TestUnpause", this.containerJsonObject());
container.start();
@@ -204,4 +206,37 @@ private boolean pausedState(final Container container) throws IOException {
.getBoolean("Paused");
}
+
+ /**
+ * {@link RtContainer} Can create Exec of Docker container it represents.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void execContainer() throws Exception {
+ final Container container = new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).containers().create("TestStart", this.containerJsonObject());
+ container.start();
+ MatcherAssert.assertThat(
+ this.runningState(container),
+ new IsEqual<>(true)
+ );
+ final JsonObject json = Json.createObjectBuilder()
+ .add("Cmd", Json.createArrayBuilder().add("date").build())
+ .add("Tty", true)
+ .add("AttachStdout", true)
+ .build();
+ Exec exec = container.exec(json);
+ MatcherAssert.assertThat(
+ container.inspect().getJsonArray("ExecIDs").size(),
+ new IsEqual<>(1)
+ );
+ MatcherAssert.assertThat(
+ container.inspect().getJsonArray("ExecIDs").getString(0),
+ new IsEqual<>(exec.inspect().getString("ID"))
+ );
+ container.stop();
+ container.remove();
+ }
+
}
diff --git a/src/test/java/com/amihaiemil/docker/RtContainerTestCase.java b/src/test/java/com/amihaiemil/docker/RtContainerTestCase.java
index 5e1b1ccc..1282d83d 100644
--- a/src/test/java/com/amihaiemil/docker/RtContainerTestCase.java
+++ b/src/test/java/com/amihaiemil/docker/RtContainerTestCase.java
@@ -36,7 +36,10 @@
import org.mockito.Mockito;
import javax.json.Json;
import javax.json.JsonObject;
+import java.io.IOException;
import java.net.URI;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
/**
* Unit tests for RtContainer.
@@ -627,4 +630,170 @@ public void getsLogs() {
Matchers.notNullValue()
);
}
+
+ /**
+ * RtContainer can wait with no problem.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void waitsOk() throws Exception {
+ int retval = new RtContainer(
+ Json.createObjectBuilder().add("Id", "123").build(),
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_OK,
+ Json.createObjectBuilder()
+ .add("StatusCode", 0)
+ .build().toString()
+ ),
+ new Condition(
+ "Method should be a POST",
+ req -> req.getRequestLine().getMethod().equals("POST")
+ ),
+ new Condition(
+ "Resource path must be /123/wait",
+ req -> req.getRequestLine().getUri().endsWith("/wait")
+ )
+ ),
+ URI.create("http://localhost:80/1.30/containers/123"),
+ Mockito.mock(Docker.class)
+ ).waitOn(null);
+ assertEquals(0, retval);
+ }
+
+ /**
+ * RtContainer can wait with a condition.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void waitsOkWithCondition() throws Exception {
+ int retval = new RtContainer(
+ Json.createObjectBuilder().add("Id", "123").build(),
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_OK,
+ Json.createObjectBuilder()
+ .add("StatusCode", 0)
+ .build().toString()
+ ),
+ new Condition(
+ "Method should be a POST",
+ req -> req.getRequestLine().getMethod().equals("POST")
+ ),
+ new Condition(
+ "Resource path must be /123/wait",
+ req -> req.getRequestLine().getUri().endsWith("ition=next-exit")
+ )
+ ),
+ URI.create("http://localhost:80/1.30/containers/123"),
+ Mockito.mock(Docker.class)
+ ).waitOn("next-exit");
+ assertEquals(0, retval);
+ }
+
+ /**
+ * RtContainer throws URE if it receives a server error on remove.
+ * @throws Exception If something goes wrong.
+ */
+ @Test(expected = UnexpectedResponseException.class)
+ public void waitWithServerError() throws Exception {
+ new RtContainer(
+ Json.createObjectBuilder().build(),
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_INTERNAL_SERVER_ERROR
+ )
+ ),
+ URI.create("http://localhost:80/1.30/containers/123"),
+ Mockito.mock(Docker.class)
+ ).waitOn(null);
+ }
+
+ /**
+ * Can create Exec.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void createTest() throws Exception {
+ final JsonObject json = Json.createObjectBuilder()
+ .add("Cmd", Json.createArrayBuilder().add("date").build())
+ .add("Tty", "true")
+ .add("AttachStdin", "true")
+ .build();
+
+ RtContainer rtContainer = new RtContainer(
+ Json.createObjectBuilder().add("Id", "123").build(),
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_CREATED,
+ Json.createObjectBuilder()
+ .add("Id", "01e1564097")
+ .build().toString()
+ ),
+ new Condition(
+ "Method should be a POST",
+ req -> req.getRequestLine().getMethod().equals("POST")
+ ),
+ new Condition(
+ "Resource path must be /123/exec",
+ req -> req.getRequestLine().getUri().endsWith("/123/exec")
+ )
+ ),
+ URI.create("http://localhost:80/1.30/containers/123"),
+ Mockito.mock(Docker.class)
+ );
+ when(rtContainer.docker().execs()).thenReturn(
+ new RtExecs(
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_OK,
+ "{\"Id\": \"exec123\"}"
+ ),
+ new Condition(
+ "must send a GET request",
+ req -> "GET".equals(req.getRequestLine().getMethod())
+ ),
+ new Condition(
+ "resource URL should end with '/exec123/json'",
+ req -> req.getRequestLine()
+ .getUri().endsWith("/exec123/json")
+ )
+ ),
+ URI.create("http://localhost/exec"),
+ Mockito.mock(Docker.class)
+ )
+ );
+ rtContainer.exec(json);
+ }
+
+ /**
+ * Must fail if docker responds with error code 500.
+ * @throws IOException due to code 500
+ */
+ @Test(expected = UnexpectedResponseException.class)
+ public void execWithServerError() throws IOException {
+ final JsonObject json = Json.createObjectBuilder()
+ .add("Tty", "true")
+ .add("AttachStdin", "true")
+ .build();
+
+ new RtContainer(
+ Json.createObjectBuilder().add("Id", "123").build(),
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_INTERNAL_SERVER_ERROR
+ ),
+ new Condition(
+ "Method should be a POST",
+ req -> req.getRequestLine().getMethod().equals("POST")
+ ),
+ new Condition(
+ "Resource path must be /123/exec",
+ req -> req.getRequestLine().getUri().endsWith("/123/exec")
+ )
+ ),
+ URI.create("http://localhost:80/1.30/containers/123"),
+ Mockito.mock(Docker.class)
+ ).exec(json);
+ }
}
diff --git a/src/test/java/com/amihaiemil/docker/RtContainersITCase.java b/src/test/java/com/amihaiemil/docker/RtContainersITCase.java
index 1586c342..0288552f 100644
--- a/src/test/java/com/amihaiemil/docker/RtContainersITCase.java
+++ b/src/test/java/com/amihaiemil/docker/RtContainersITCase.java
@@ -44,7 +44,7 @@ public final class RtContainersITCase {
*/
@Test
public void iteratesContainers() {
- final Containers containers = new LocalDocker(
+ final Containers containers = new UnixDocker(
new File("/var/run/docker.sock")
).containers();
for(final Container container : containers) {
diff --git a/src/test/java/com/amihaiemil/docker/RtContainersTestCase.java b/src/test/java/com/amihaiemil/docker/RtContainersTestCase.java
index 0a7de5bd..6c87c1dc 100644
--- a/src/test/java/com/amihaiemil/docker/RtContainersTestCase.java
+++ b/src/test/java/com/amihaiemil/docker/RtContainersTestCase.java
@@ -48,7 +48,7 @@
* @checkstyle MethodName (500 lines)
*/
public final class RtContainersTestCase {
-
+
/**
* RtContainers can return its parent Docker.
*/
@@ -69,7 +69,7 @@ public void returnsDocker() {
Matchers.is(parent)
);
}
-
+
/**
* Must return the same number of containers as there are elements in the
* json array returned by the service.
@@ -106,7 +106,7 @@ public void returnsAllContainers() throws Exception {
Matchers.is(2)
);
}
-
+
/**
* Must return the same number of containers as there are elements in the
* json array returned by the service.
@@ -141,7 +141,7 @@ public void iteratesRunningContainers() throws Exception {
Matchers.is(2)
);
}
-
+
/**
* The iterator works when there are no containers.
* @throws Exception If an error occurs.
@@ -162,7 +162,7 @@ public void iteratesZeroContainers() throws Exception {
Matchers.is(0)
);
}
-
+
/**
* Must throw {@link UnexpectedResponseException} if response code is 500.
* @throws Exception The UnexpectedException.
@@ -177,7 +177,7 @@ public void iterateFailsIfResponseIs500() throws Exception {
Mockito.mock(Docker.class)
).iterator();
}
-
+
/**
* Must throw {@link UnexpectedResponseException} if response code is 400.
* @throws Exception The UnexpectedException.
@@ -192,7 +192,7 @@ public void iterateFailsIfResponseIs400() throws Exception {
Mockito.mock(Docker.class)
).iterator();
}
-
+
/**
* The request should be well-formed.
* @throws Exception If something goes wrong.
@@ -280,7 +280,7 @@ public void createsWith404() throws IOException {
)
),
URI.create("http://localhost/test"),
- Mockito.mock(Docker.class)
+ Mockito.mock(Docker.class)
).create("some_image");
}
@@ -356,7 +356,7 @@ public void createsWithImageName() throws Exception {
)
),
URI.create("http://localhost/test"),
- Mockito.mock(Docker.class)
+ Mockito.mock(Docker.class)
).create("some_name", "some_image");
}
@@ -394,7 +394,7 @@ public void createsWithPayloadForCreateJson() throws Exception {
)
),
URI.create("http://localhost/test"),
- Mockito.mock(Docker.class)
+ Mockito.mock(Docker.class)
).create(json);
}
@@ -456,7 +456,7 @@ public void createEscapesNameParameter() throws Exception {
)
),
URI.create("http://localhost/docker"),
- Mockito.mock(Docker.class)
+ Mockito.mock(Docker.class)
).create("Adrian Toomes", "some/image");
}
@@ -499,7 +499,7 @@ public void createsContainerWithId() throws Exception {
)
),
URI.create("http://localhost/test"),
- Mockito.mock(Docker.class)
+ Mockito.mock(Docker.class)
).create(
Json.createObjectBuilder()
.add("Image", "ubuntu").build()
@@ -507,4 +507,25 @@ public void createsContainerWithId() throws Exception {
Matchers.is("df2419f4")
);
}
+
+ /**
+ * RtContainers.get() returns an RtContainer with the container id.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void getContainerWithId() throws Exception {
+ MatcherAssert.assertThat(
+ new ListedContainers(
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_OK,
+ "{ \"Id\": \"df2419f4\", \"Warnings\": [ ] }"
+ )
+ ),
+ URI.create("http://localhost/test"),
+ Mockito.mock(Docker.class)
+ ).get("df2419f4").getString("Id"),
+ Matchers.is("df2419f4")
+ );
+ }
}
diff --git a/src/test/java/com/amihaiemil/docker/RtDockerSystemITCase.java b/src/test/java/com/amihaiemil/docker/RtDockerSystemITCase.java
index a42a1a1b..5425e9b0 100644
--- a/src/test/java/com/amihaiemil/docker/RtDockerSystemITCase.java
+++ b/src/test/java/com/amihaiemil/docker/RtDockerSystemITCase.java
@@ -45,7 +45,8 @@ public final class RtDockerSystemITCase {
*/
@Test
public void showDiskSpaceInfo() throws Exception {
- final Docker docker = new LocalDocker(
+ final Docker docker = new UnixDocker(
+
new File("/var/run/docker.sock")
);
DiskSpaceInfo info = docker.system().diskUsage();
diff --git a/src/test/java/com/amihaiemil/docker/RtEventsTestCase.java b/src/test/java/com/amihaiemil/docker/RtEventsTestCase.java
new file mode 100644
index 00000000..0c4ada34
--- /dev/null
+++ b/src/test/java/com/amihaiemil/docker/RtEventsTestCase.java
@@ -0,0 +1,265 @@
+/**
+ * Copyright (c) 2018-2020, Mihai Emil Andronache
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1)Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2)Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3)Neither the name of docker-java-api nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.amihaiemil.docker;
+
+import com.amihaiemil.docker.mock.AssertRequest;
+import com.amihaiemil.docker.mock.Condition;
+import com.amihaiemil.docker.mock.Response;
+import org.apache.http.HttpStatus;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import javax.json.JsonObject;
+import java.net.URI;
+import java.net.URLDecoder;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Unit tests for {@link RtEvents}.
+ * @author Mihai Andronache (amihaiemil@gmail.com)
+ * @version $Id$
+ * @since 0.0.13
+ */
+public final class RtEventsTestCase {
+
+ /**
+ * RtEvents can monitor evens without filters.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void monitorsAll() throws Exception {
+ final Events all = new RtEvents(
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_OK,
+ "{\"id\": \"eventId\"}"
+ ),
+ new Condition(
+ "monitor() must send a GET request",
+ req -> "GET".equals(req.getRequestLine().getMethod())
+ ),
+ new Condition(
+ "monitor() resource URL must be '/events'",
+ req -> req.getRequestLine()
+ .getUri().endsWith("/events")
+ )
+ ),
+ URI.create("http://localhost/1.40/events"),
+ Mockito.mock(Docker.class)
+ );
+ final List events = all.monitor().limit(1)
+ .collect(Collectors.toList());
+ MatcherAssert.assertThat(events, Matchers.iterableWithSize(1));
+ MatcherAssert.assertThat(
+ events.get(0).getString("id"),
+ Matchers.equalTo("eventId")
+ );
+ }
+
+ /**
+ * RtEvents can monitor evens with the Since filter.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void monitorsSince() throws Exception {
+ final LocalDateTime since = LocalDateTime.parse("2020-04-01T00:00");
+ final long sinceMillis = ZonedDateTime.of(
+ since,
+ ZoneId.systemDefault()
+ ).toInstant().toEpochMilli();
+ final Events all = new RtEvents(
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_OK,
+ "{\"id\": \"eventId\"}"
+ ),
+ new Condition(
+ "monitor() must send a GET request",
+ req -> "GET".equals(req.getRequestLine().getMethod())
+ ),
+ new Condition(
+ "monitor() resource URL must be '/events?since=...'",
+ req -> req.getRequestLine()
+ .getUri().endsWith("/events?since=" + sinceMillis)
+ )
+ ),
+ URI.create("http://localhost/1.40/events"),
+ Mockito.mock(Docker.class)
+ ).since(since);
+ final List events = all.monitor().limit(1)
+ .collect(Collectors.toList());
+ MatcherAssert.assertThat(events, Matchers.iterableWithSize(1));
+ MatcherAssert.assertThat(
+ events.get(0).getString("id"),
+ Matchers.equalTo("eventId")
+ );
+ }
+
+ /**
+ * RtEvents can monitor evens with the Until filter.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void monitorsUntil() throws Exception {
+ final LocalDateTime until = LocalDateTime.parse("2020-06-01T00:00");
+ final long untilMillis = ZonedDateTime.of(
+ until,
+ ZoneId.systemDefault()
+ ).toInstant().toEpochMilli();
+ final Events all = new RtEvents(
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_OK,
+ "{\"id\": \"eventId\"}"
+ ),
+ new Condition(
+ "monitor() must send a GET request",
+ req -> "GET".equals(req.getRequestLine().getMethod())
+ ),
+ new Condition(
+ "monitor() resource URL must be '/events?until=...'",
+ req -> req.getRequestLine()
+ .getUri().endsWith("/events?until=" + untilMillis)
+ )
+ ),
+ URI.create("http://localhost/1.40/events"),
+ Mockito.mock(Docker.class)
+ ).until(until);
+ final List events = all.monitor().limit(1)
+ .collect(Collectors.toList());
+ MatcherAssert.assertThat(events, Matchers.iterableWithSize(1));
+ MatcherAssert.assertThat(
+ events.get(0).getString("id"),
+ Matchers.equalTo("eventId")
+ );
+ }
+
+ /**
+ * RtEvents can monitor evens with the a filter map.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void monitorsWithFilter() throws Exception {
+ final Events all = new RtEvents(
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_OK,
+ "{\"id\": \"eventId\"}"
+ ),
+ new Condition(
+ "monitor() must send a GET request",
+ req -> "GET".equals(req.getRequestLine().getMethod())
+ ),
+ new Condition(
+ "monitor() resource URL must be '/events?filters=...",
+ req -> URLDecoder.decode(
+ req.getRequestLine().getUri()
+ ).endsWith(
+ "/events?filters={\"type\":[\"container\"]}"
+ )
+ )
+ ),
+ URI.create("http://localhost/1.40/events"),
+ Mockito.mock(Docker.class)
+ ).filter(
+ () -> {
+ final Map> filters = new HashMap<>();
+ filters.put("type", Arrays.asList("container"));
+ return filters;
+ }
+ );
+ final List events = all.monitor().limit(1)
+ .collect(Collectors.toList());
+ MatcherAssert.assertThat(events, Matchers.iterableWithSize(1));
+ MatcherAssert.assertThat(
+ events.get(0).getString("id"),
+ Matchers.equalTo("eventId")
+ );
+ }
+
+ /**
+ * RtEvents can monitor evens with the a filter map and also the
+ * Since/Until flags.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void monitorsWithSinceUntilAndFilters() throws Exception {
+ final LocalDateTime since = LocalDateTime.parse("2020-04-01T00:00");
+ final long sinceMillis = ZonedDateTime.of(
+ since,
+ ZoneId.systemDefault()
+ ).toInstant().toEpochMilli();
+ final LocalDateTime until = LocalDateTime.parse("2020-06-01T00:00");
+ final long untilMillis = ZonedDateTime.of(
+ until,
+ ZoneId.systemDefault()
+ ).toInstant().toEpochMilli();
+ final Events all = new RtEvents(
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_OK,
+ "{\"id\": \"eventId\"}"
+ ),
+ new Condition(
+ "monitor() must send a GET request",
+ req -> "GET".equals(req.getRequestLine().getMethod())
+ ),
+ new Condition(
+ "monitor() resource URL must be "
+ + "'/events?since=...&until=...&filters=...",
+ req -> URLDecoder.decode(
+ req.getRequestLine().getUri()
+ ).endsWith(
+ "/events?since=" + sinceMillis
+ + "&until=" + untilMillis
+ + "&filters={\"type\":[\"container\"]}"
+ )
+ )
+ ),
+ URI.create("http://localhost/1.40/events"),
+ Mockito.mock(Docker.class)
+ ).since(since).until(until).filter(
+ () -> {
+ final Map> filters = new HashMap<>();
+ filters.put("type", Arrays.asList("container"));
+ return filters;
+ }
+ );
+ final List events = all.monitor().limit(1)
+ .collect(Collectors.toList());
+ MatcherAssert.assertThat(events, Matchers.iterableWithSize(1));
+ MatcherAssert.assertThat(
+ events.get(0).getString("id"),
+ Matchers.equalTo("eventId")
+ );
+ }
+}
diff --git a/src/test/java/com/amihaiemil/docker/RtExecsTestCase.java b/src/test/java/com/amihaiemil/docker/RtExecsTestCase.java
new file mode 100644
index 00000000..152f974b
--- /dev/null
+++ b/src/test/java/com/amihaiemil/docker/RtExecsTestCase.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2018-2020, Mihai Emil Andronache
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1)Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2)Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3)Neither the name of docker-java-api nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.amihaiemil.docker;
+
+import com.amihaiemil.docker.mock.AssertRequest;
+import com.amihaiemil.docker.mock.Condition;
+import com.amihaiemil.docker.mock.Response;
+import org.apache.http.HttpStatus;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import javax.json.Json;
+import java.net.URI;
+
+/**
+ * Unit tests for {@link RtExecs}.
+ * @author Mihai Andronache (amihaiemil@gmail.com)
+ * @version $Id$
+ * @since 0.0.12
+ */
+public final class RtExecsTestCase {
+
+ /**
+ * An Exec can return its JSON inspection.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void execReturnsItsInspection() throws Exception {
+ final Execs all = new RtExecs(
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_OK,
+ "{\"Id\": \"exec123\"}"
+ ),
+ new Condition(
+ "inspect() must send a GET request",
+ req -> "GET".equals(req.getRequestLine().getMethod())
+ ),
+ new Condition(
+ "inspect() resource URL should end with '/exec123/json'",
+ req -> req.getRequestLine()
+ .getUri().endsWith("/exec123/json")
+ )
+ ),
+ URI.create("http://localhost/exec"),
+ Mockito.mock(Docker.class)
+ );
+ final Exec exec = all.get("exec123");
+ MatcherAssert.assertThat(exec, Matchers.notNullValue());
+ MatcherAssert.assertThat(
+ exec.inspect(),
+ Matchers.equalTo(
+ Json.createObjectBuilder()
+ .add("Id", "exec123")
+ .build()
+ )
+ );
+ }
+
+}
diff --git a/src/test/java/com/amihaiemil/docker/RtImageITCase.java b/src/test/java/com/amihaiemil/docker/RtImageITCase.java
index 01e9b2d7..8158ce9c 100644
--- a/src/test/java/com/amihaiemil/docker/RtImageITCase.java
+++ b/src/test/java/com/amihaiemil/docker/RtImageITCase.java
@@ -45,7 +45,7 @@ public final class RtImageITCase {
*/
@Test
public void returnsHistory() throws Exception {
- final Image img = new LocalDocker(
+ final Image img = new UnixDocker(
new File("/var/run/docker.sock")
).images().pull("hello-world", "latest");
for(final Image parent:img.history()) {
diff --git a/src/test/java/com/amihaiemil/docker/RtImagesITCase.java b/src/test/java/com/amihaiemil/docker/RtImagesITCase.java
index 457b10d2..e7c9b0a1 100644
--- a/src/test/java/com/amihaiemil/docker/RtImagesITCase.java
+++ b/src/test/java/com/amihaiemil/docker/RtImagesITCase.java
@@ -49,7 +49,7 @@ public final class RtImagesITCase {
*/
@Test
public void iteratesImages() throws Exception {
- final Images images = new LocalDocker(
+ final Images images = new UnixDocker(
new File("/var/run/docker.sock")
).images();
for(final Image img : images) {
@@ -80,7 +80,8 @@ public void filterImage() throws Exception {
"ubuntu"
)
);
- final Images images = new LocalDocker(
+
+ final Images images = new UnixDocker(
new File("/var/run/docker.sock")
).images();
Images filtered = images.filter(filters);
diff --git a/src/test/java/com/amihaiemil/docker/RtLogsITCase.java b/src/test/java/com/amihaiemil/docker/RtLogsITCase.java
index 98c484fc..61bf95d5 100644
--- a/src/test/java/com/amihaiemil/docker/RtLogsITCase.java
+++ b/src/test/java/com/amihaiemil/docker/RtLogsITCase.java
@@ -51,13 +51,13 @@ public final class RtLogsITCase {
*/
@Test
public void fetchesLogs() throws Exception {
- final Container container = new LocalDocker(
+ final Container container = new UnixDocker(
new File("/var/run/docker.sock")
).images().pull("hello-world", "latest").run();
final String logs = container.logs().fetch();
MatcherAssert.assertThat(
- logs.trim(),
- new StringStartsWith("Hello from Docker!")
+ logs,
+ new StringStartsWith("\nHello from Docker!")
);
}
@@ -68,7 +68,7 @@ public void fetchesLogs() throws Exception {
@Test
@Ignore
public void followsLogs() throws Exception {
- final Container container = new LocalDocker(
+ final Container container = new UnixDocker(
new File("/var/run/docker.sock")
).images().pull("ubuntu", "latest").run();
final String logs = IOUtils.toString(container.logs().follow());
diff --git a/src/test/java/com/amihaiemil/docker/RtLogsTestCase.java b/src/test/java/com/amihaiemil/docker/RtLogsTestCase.java
index 4ac3d27f..a3e6c97a 100644
--- a/src/test/java/com/amihaiemil/docker/RtLogsTestCase.java
+++ b/src/test/java/com/amihaiemil/docker/RtLogsTestCase.java
@@ -99,7 +99,7 @@ public void followsLogs() throws Exception {
);
}
}
-
+
/**
* RtLogs can fetch the Container's logs (return them as a String).
* @throws Exception If something goes wrong.
@@ -109,12 +109,8 @@ public void fetchesLogs() throws Exception {
final Logs logs = new RtLogs(
Mockito.mock(Container.class),
new AssertRequest(
- new Response(
- HttpStatus.SC_OK,
- Json.createObjectBuilder()
- .add("logs", "...fetched logs...")
- .build().toString()
- ),
+ new Response(HttpStatus.SC_OK,
+ this.prepareMessage("...fetched logs...")),
new Condition(
"Method should be a GET",
req -> req.getRequestLine().getMethod().equals("GET")
@@ -130,10 +126,37 @@ public void fetchesLogs() throws Exception {
);
MatcherAssert.assertThat(
logs.fetch(),
- Matchers.equalTo("{\"logs\":\"...fetched logs...\"}")
+ Matchers.equalTo("...fetched logs...")
);
}
-
+
+ /**
+ * Docker logs contains header -
+ * header := [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}
+ * STREAM_TYPE
+ * 0: stdin (is written on stdout)
+ * 1: stdout
+ * 2: stderr
+ *
+ * SIZE1, SIZE2, SIZE3, SIZE4 are the four bytes of the uint32 size
+ * encoded as big endian.
+ *
+ * @param message Message from container
+ * @return String with header.
+ */
+ private String prepareMessage(final String message) {
+ char[] chars = new char[8];
+ chars[0] = 1;
+ chars[1] = 0;
+ chars[2] = 0;
+ chars[3] = 0;
+ chars[4] = 0;
+ chars[5] = 0;
+ chars[6] = 0;
+ chars[7] = (char) message.length();
+ return new String(chars) + message;
+ }
+
/**
* RtLogs.toString() fetches the logs as String.
*/
@@ -144,9 +167,7 @@ public void toStringFetch() {
new AssertRequest(
new Response(
HttpStatus.SC_OK,
- Json.createObjectBuilder()
- .add("logs", "toString logs")
- .build().toString()
+ this.prepareMessage("toString logs")
),
new Condition(
"Method should be a GET",
@@ -163,7 +184,7 @@ public void toStringFetch() {
);
MatcherAssert.assertThat(
logs.toString(),
- Matchers.equalTo("{\"logs\":\"toString logs\"}")
+ Matchers.equalTo("toString logs")
);
}
@@ -178,9 +199,7 @@ public void logStdout() throws Exception {
new AssertRequest(
new Response(
HttpStatus.SC_OK,
- Json.createObjectBuilder()
- .add("logs", "stdout logs")
- .build().toString()
+ this.prepareMessage("stdout logs")
),
new Condition(
"Method should be a GET",
@@ -197,7 +216,7 @@ public void logStdout() throws Exception {
);
MatcherAssert.assertThat(
logs.stdout().fetch(),
- Matchers.equalTo("{\"logs\":\"stdout logs\"}")
+ Matchers.equalTo("stdout logs")
);
}
@@ -212,9 +231,7 @@ public void logStderr() throws Exception {
new AssertRequest(
new Response(
HttpStatus.SC_OK,
- Json.createObjectBuilder()
- .add("logs", "stderr logs")
- .build().toString()
+ this.prepareMessage("stderr logs")
),
new Condition(
"Method should be a GET",
@@ -231,7 +248,7 @@ public void logStderr() throws Exception {
);
MatcherAssert.assertThat(
logs.stderr().fetch(),
- Matchers.equalTo("{\"logs\":\"stderr logs\"}")
+ Matchers.equalTo("stderr logs")
);
}
diff --git a/src/test/java/com/amihaiemil/docker/RtVersionTestCase.java b/src/test/java/com/amihaiemil/docker/RtVersionTestCase.java
index a69df7bf..283faa9b 100644
--- a/src/test/java/com/amihaiemil/docker/RtVersionTestCase.java
+++ b/src/test/java/com/amihaiemil/docker/RtVersionTestCase.java
@@ -45,7 +45,9 @@ public final void queryDockerVersion() throws IOException {
return ((ReadJsonObject) invocation.getArguments()[1])
.handleResponse(response);
});
+
Docker docker = new LocalDocker(client, "v1.35");
+
Version version = docker.version();
assertEquals("19.03.3", version.version());
assertEquals("Docker Engine - Community", version.platformName());
diff --git a/src/test/java/com/amihaiemil/docker/TcpDockerTestCase.java b/src/test/java/com/amihaiemil/docker/TcpDockerTestCase.java
new file mode 100644
index 00000000..7df3a819
--- /dev/null
+++ b/src/test/java/com/amihaiemil/docker/TcpDockerTestCase.java
@@ -0,0 +1,188 @@
+/**
+ * Copyright (c) 2018-2019, Mihai Emil Andronache
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1)Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2)Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3)Neither the name of docker-java-api nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.amihaiemil.docker;
+
+import com.amihaiemil.docker.mock.AssertRequest;
+import com.amihaiemil.docker.mock.Response;
+
+import java.net.URI;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.HttpClient;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+/**
+ * Unit tests for {@link TcpDocker}.
+ * @author George Aristy (george.aristy@gmail.com)
+ * @version $Id$
+ * @since 0.0.1
+ * @checkstyle MethodName (500 lines)
+ */
+
+public final class TcpDockerTestCase {
+
+ /**
+ * Ping must be TRUE if response is OK.
+ * @throws Exception If an error occurs.
+ */
+ @Test
+ public void pingTrueIfResponseIsOk() throws Exception {
+ MatcherAssert.assertThat(
+ new TcpDocker(
+ new AssertRequest(
+ new Response(HttpStatus.SC_OK, "")
+ ),
+ URI.create("http://remotedocker")
+ ).ping(),
+ Matchers.is(true)
+ );
+ }
+
+ /**
+ * Ping must be False if response is not OK.
+ * @throws Exception If an error occurs.
+ */
+ @Test
+ public void pingFalseIfResponseIsNotOk() throws Exception {
+ MatcherAssert.assertThat(
+ new TcpDocker(
+ new AssertRequest(
+ new Response(HttpStatus.SC_NOT_FOUND, "")
+ ),
+ URI.create("http://remotedocker")
+ ).ping(),
+ Matchers.is(false)
+ );
+ }
+
+ /**
+ * TcpDocker can return the Containers.
+ */
+ @Test
+ public void getsContainers() {
+ MatcherAssert.assertThat(
+ new TcpDocker(
+ Mockito.mock(HttpClient.class),
+ URI.create("http://localhost")
+ ).containers(),
+ Matchers.notNullValue()
+ );
+ }
+
+ /**
+ * TcpDocker can return the Swarm.
+ */
+ @Test
+ public void returnsSwarm() {
+ MatcherAssert.assertThat(
+ new TcpDocker(
+ Mockito.mock(HttpClient.class),
+ URI.create("http://localhost")
+ ).swarm(),
+ Matchers.notNullValue()
+ );
+ }
+
+
+ /**
+ * TcpDocker can return Images.
+ */
+ @Test
+ public void returnsImages() {
+ MatcherAssert.assertThat(
+ new TcpDocker(
+ Mockito.mock(HttpClient.class),
+ URI.create("http://localhost")
+ ).images(),
+ Matchers.notNullValue()
+ );
+ }
+
+ /**
+ * UnixDocker can return its HttpClient.
+ */
+ @Test
+ public void returnsHttpClient() {
+ final HttpClient client = Mockito.mock(HttpClient.class);
+ MatcherAssert.assertThat(
+ new TcpDocker(
+ client,
+ URI.create("http://localhost")
+ ).httpClient(),
+ Matchers.allOf(
+ Matchers.notNullValue(),
+ Matchers.sameInstance(client)
+ )
+ );
+ }
+
+ /**
+ * UnixDocker should have AuthHttpClient.
+ */
+ @Test
+ public void returnsAuthHttpClient() {
+ MatcherAssert.assertThat(
+ new TcpDocker(
+ URI.create("http://localhost"),
+ new Credentials("user", "pwd", "user@email.com", "server.com")
+ ).httpClient(),
+ Matchers.allOf(
+ Matchers.notNullValue(),
+ Matchers.instanceOf(AuthHttpClient.class)
+ )
+ );
+ }
+
+ /**
+ * TcpDocker can return Volumes.
+ */
+ @Test
+ public void returnsVolumes() {
+ MatcherAssert.assertThat(
+ new TcpDocker(
+ Mockito.mock(HttpClient.class),
+ URI.create("http://localhost")
+ ).volumes(),
+ Matchers.notNullValue()
+ );
+ }
+
+ /**
+ * TcpDocker can return Networks.
+ */
+ @Test
+ public void returnsNetworks() {
+ MatcherAssert.assertThat(
+ new TcpDocker(
+ Mockito.mock(HttpClient.class),
+ URI.create("http://localhost")
+ ).networks(),
+ Matchers.notNullValue()
+ );
+ }
+}
diff --git a/src/test/java/com/amihaiemil/docker/UnixDockerITCase.java b/src/test/java/com/amihaiemil/docker/UnixDockerITCase.java
new file mode 100644
index 00000000..da348fa7
--- /dev/null
+++ b/src/test/java/com/amihaiemil/docker/UnixDockerITCase.java
@@ -0,0 +1,262 @@
+/**
+ * Copyright (c) 2018-2019, Mihai Emil Andronache
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1)Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2)Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3)Neither the name of docker-java-api nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.amihaiemil.docker;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.hamcrest.collection.IsIterableWithSize;
+import org.junit.Test;
+import org.mockito.internal.matchers.GreaterOrEqual;
+
+import javax.json.JsonObject;
+
+/**
+ * Integration tests for LocalUnixDocker.
+ * @author Mihai Andronache (amihaiemil@gmail.com)
+ * @version $Id$
+ * @since 0.0.1
+ */
+public final class UnixDockerITCase {
+
+ /**
+ * UnixDocker can ping the Docker Engine.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void pingsDocker() throws Exception {
+ final Docker docker = new UnixDocker(
+ new File("/var/run/docker.sock")
+ );
+ MatcherAssert.assertThat(docker.ping(), Matchers.is(Boolean.TRUE));
+ }
+
+ /**
+ * UnixDocker can return Info about Docker.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void returnsInfo() throws Exception {
+ final Docker docker = new UnixDocker(
+ new File("/var/run/docker.sock")
+ );
+ final Info info = docker.info();
+ MatcherAssert.assertThat(info, Matchers.notNullValue());
+ MatcherAssert.assertThat(info.docker(), Matchers.is(docker));
+ MatcherAssert.assertThat(
+ info.getString("OSType"),
+ Matchers.equalTo("linux")
+ );
+ }
+
+ /**
+ * UnixDocker can return the Version of Docker.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void returnsVersion() throws Exception {
+ final Docker docker = new UnixDocker(
+ new File("/var/run/docker.sock")
+ );
+ final Version version = docker.version();
+ MatcherAssert.assertThat(version, Matchers.notNullValue());
+ MatcherAssert.assertThat(version.docker(), Matchers.is(docker));
+ MatcherAssert.assertThat(
+ version.platformName(),
+ Matchers.equalTo("Docker Engine - Community")
+ );
+ }
+
+
+ /**
+ * Docker can return its Events unfiltered.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void returnsUnfilteredEvents() throws Exception {
+ final Thread pull = new Thread(
+ () -> {
+ try {
+ Thread.sleep(2000);
+ final Image img = new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).images().pull("hello-world", "latest");
+ } catch (final IOException | InterruptedException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+ );
+ pull.start();
+ try {
+ final Events events = new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).events();
+ final JsonObject pulled = events
+ .monitor()
+ .limit(1)
+ .collect(Collectors.toList())
+ .get(0);
+ MatcherAssert.assertThat(pulled, Matchers.notNullValue());
+ } finally {
+ pull.stop();
+ }
+ }
+
+ /**
+ * Docker can return its Events with filtering at streaming time.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void returnsFilteredStreamOfEvents() throws Exception {
+ final Thread pull = new Thread(
+ () -> {
+ try {
+ Thread.sleep(2000);
+ final Images images = new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).images();
+ images.pull("hello-world", "latest");
+ images.pull("ubuntu", "latest");
+ images.pull("hello-world", "latest");
+ images.pull("ubuntu", "latest");
+ } catch (final IOException | InterruptedException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+ );
+ pull.start();
+ try {
+ final Events events = new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).events();
+ final List pulled = events
+ .monitor()
+ .filter(json -> json.getString("id").startsWith("ubuntu"))
+ .limit(2)
+ .collect(Collectors.toList());
+ MatcherAssert.assertThat(
+ pulled,
+ Matchers.iterableWithSize(2)
+ );
+ MatcherAssert.assertThat(
+ pulled.get(0).getString("id"),
+ Matchers.equalTo("ubuntu:latest")
+ );
+ MatcherAssert.assertThat(
+ pulled.get(1).getString("id"),
+ Matchers.equalTo("ubuntu:latest")
+ );
+ } finally {
+ pull.stop();
+ }
+ }
+
+ /**
+ * Docker can return its Events which are filter at request time.
+ * @checkstyle LineLength (100 lines)
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void returnsFilteredEvents() throws Exception {
+ final Thread pull = new Thread(
+ () -> {
+ try {
+ Thread.sleep(2000);
+ final Container started = new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).images().pull("hello-world", "latest").run();
+ } catch (final IOException | InterruptedException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+ );
+ pull.start();
+ try {
+ final Events events = new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).events();
+ final List streamed = events
+ .filter(
+ () -> {
+ final Map> filters = new HashMap<>();
+ filters.put("type", Arrays.asList("container"));
+ return filters;
+ }
+ )
+ .monitor()
+ .limit(3)
+ .collect(Collectors.toList());
+ MatcherAssert.assertThat(
+ streamed,
+ Matchers.iterableWithSize(3)
+ );
+ for(final JsonObject event : streamed) {
+ MatcherAssert.assertThat(
+ event.getString("Type"),
+ Matchers.equalTo("container")
+ );
+ }
+ MatcherAssert.assertThat(
+ streamed.get(0).getString("status"),
+ Matchers.equalTo("create")
+ );
+ MatcherAssert.assertThat(
+ streamed.get(1).getString("status"),
+ Matchers.equalTo("start")
+ );
+ MatcherAssert.assertThat(
+ streamed.get(2).getString("status"),
+ Matchers.equalTo("die")
+ );
+ } finally {
+ pull.stop();
+ }
+ }
+
+ /**
+ * UnixDocker can list {@link Volumes}.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void listVolumes() throws Exception {
+ final Docker docker = new UnixDocker(
+ Paths.get("/var/run/docker.sock").toFile()
+ );
+ MatcherAssert.assertThat(
+ docker.volumes(),
+ new IsIterableWithSize<>(new GreaterOrEqual<>(0))
+ );
+ }
+
+}
diff --git a/src/test/java/com/amihaiemil/docker/UnixDockerTestCase.java b/src/test/java/com/amihaiemil/docker/UnixDockerTestCase.java
new file mode 100644
index 00000000..b21cb98f
--- /dev/null
+++ b/src/test/java/com/amihaiemil/docker/UnixDockerTestCase.java
@@ -0,0 +1,231 @@
+/**
+ * Copyright (c) 2018-2019, Mihai Emil Andronache
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1)Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2)Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3)Neither the name of docker-java-api nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.amihaiemil.docker;
+
+import com.amihaiemil.docker.mock.AssertRequest;
+import com.amihaiemil.docker.mock.Condition;
+import com.amihaiemil.docker.mock.Response;
+import java.io.File;
+import org.apache.http.HttpStatus;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+
+import javax.json.Json;
+
+/**
+ * Unit tests for LocalUnixDocker.
+ * @author Mihai Andronache (amihaiemil@gmail.com)
+ * @version $Id$
+ * @since 0.0.1
+ */
+public final class UnixDockerTestCase {
+
+ /**
+ * UnixDocker can be instantiated.
+ */
+ @Test
+ public void canBeInstantiate() {
+ MatcherAssert.assertThat(
+ new UnixDocker(
+ new File("/var/run/docker.sock")
+ ),
+ Matchers.notNullValue()
+ );
+ }
+
+ /**
+ * Ping must be TRUE if response is OK.
+ * @throws Exception If an error occurs.
+ */
+ @Test
+ public void pingTrueIfResponseIsOk() throws Exception {
+ MatcherAssert.assertThat(
+ new UnixDocker(
+ new AssertRequest(
+ new Response(HttpStatus.SC_OK, "")
+ ),
+ "v1.35"
+ ).ping(),
+ Matchers.is(true)
+ );
+ }
+
+ /**
+ * Ping must be False if response is not OK.
+ * @throws Exception If an error occurs.
+ */
+ @Test
+ public void pingFalseIfResponseIsNotOk() throws Exception {
+ MatcherAssert.assertThat(
+ new UnixDocker(
+ new AssertRequest(
+ new Response(HttpStatus.SC_NOT_FOUND, "")
+ ),
+ "v1.35"
+ ).ping(),
+ Matchers.is(false)
+ );
+ }
+
+ /**
+ * UnixDocker can return the Containers.
+ */
+ @Test
+ public void getsContainers() {
+ MatcherAssert.assertThat(
+ new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).containers(),
+ Matchers.notNullValue()
+ );
+ }
+
+ /**
+ * UnixDocker can return the Swarm.
+ */
+ @Test
+ public void returnsSwarm() {
+ MatcherAssert.assertThat(
+ new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).swarm(),
+ Matchers.notNullValue()
+ );
+ }
+
+ /**
+ * UnixDocker can return Images.
+ */
+ @Test
+ public void returnsImages() {
+ MatcherAssert.assertThat(
+ new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).images(),
+ Matchers.notNullValue()
+ );
+ }
+
+ /**
+ * UnixDocker can return its HttpClient.
+ */
+ @Test
+ public void returnsHttpClient() {
+ MatcherAssert.assertThat(
+ new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).httpClient(),
+ Matchers.allOf(
+ Matchers.notNullValue(),
+ Matchers.instanceOf(UnixHttpClient.class)
+ )
+ );
+ }
+
+ /**
+ * UnixDocker can return Volumes.
+ */
+ @Test
+ public void returnsVolumes() {
+ MatcherAssert.assertThat(
+ new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).volumes(),
+ Matchers.notNullValue()
+ );
+ }
+
+ /**
+ * UnixDocker can return Networks.
+ */
+ @Test
+ public void returnsNetworks() {
+ MatcherAssert.assertThat(
+ new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).networks(),
+ Matchers.notNullValue()
+ );
+ }
+
+ /**
+ * UnixDocker can return Execs.
+ */
+ @Test
+ public void returnsExecs() {
+ MatcherAssert.assertThat(
+ new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).execs(),
+ Matchers.notNullValue()
+ );
+ }
+
+ /**
+ * UnixDocker throws UnsupportedOperationException for Plugins.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void unsupportedOperationPlugins() {
+ new UnixDocker(
+ new File("/var/run/docker.sock")
+ ).plugins();
+ }
+
+ /**
+ * RtDocker can return info about itself.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void returnsInfo() throws Exception {
+ final Docker docker = new UnixDocker(
+ new AssertRequest(
+ new Response(
+ HttpStatus.SC_OK,
+ "{\"info\": \"running\"}"
+ ),
+ new Condition(
+ "info() must send a GET request",
+ req -> "GET".equals(req.getRequestLine().getMethod())
+ ),
+ new Condition(
+ "info() resource URL must be unix://localhost:80/1.40/info",
+ req -> req.getRequestLine()
+ .getUri().equals("unix://localhost:80/1.40/info")
+ )
+ ),
+ "1.40"
+ );
+ MatcherAssert.assertThat(
+ docker.info(),
+ Matchers.equalTo(
+ Json.createObjectBuilder()
+ .add("info", "running")
+ .build()
+ )
+ );
+ }
+}