diff --git a/src/main/java/com/amihaiemil/docker/Image.java b/src/main/java/com/amihaiemil/docker/Image.java index 5cf6343f..aa91cff8 100644 --- a/src/main/java/com/amihaiemil/docker/Image.java +++ b/src/main/java/com/amihaiemil/docker/Image.java @@ -76,4 +76,13 @@ public interface Image extends JsonObject { void tag( String repo, String name ) throws IOException, UnexpectedResponseException; + + /** + * Run this image. + * @return The container for the running image. + * @throws IOException If something goes wrong. + * @throws UnexpectedResponseException If the status response is not + * the expected one. + */ + Container run() throws IOException, UnexpectedResponseException; } diff --git a/src/main/java/com/amihaiemil/docker/RtDocker.java b/src/main/java/com/amihaiemil/docker/RtDocker.java index fa91c911..080d6bd2 100644 --- a/src/main/java/com/amihaiemil/docker/RtDocker.java +++ b/src/main/java/com/amihaiemil/docker/RtDocker.java @@ -78,7 +78,7 @@ public final Containers containers() { @Override public final Images images() { return new RtImages( - this.client, URI.create(this.baseUri.toString() + "/images") + this.client, URI.create(this.baseUri.toString() + "/images"), this ); } diff --git a/src/main/java/com/amihaiemil/docker/RtImage.java b/src/main/java/com/amihaiemil/docker/RtImage.java index 455b074f..7c369a44 100644 --- a/src/main/java/com/amihaiemil/docker/RtImage.java +++ b/src/main/java/com/amihaiemil/docker/RtImage.java @@ -51,16 +51,27 @@ final class RtImage extends JsonResource implements Image { */ private final URI baseUri; + /** + * Docker API. + */ + private final Docker docker; + /** * Ctor. * @param rep JsonObject representation of this Image. * @param client The http client. * @param uri The URI for this image. + * @param dkr The docker entry point. + * @checkstyle ParameterNumber (5 lines) */ - RtImage(final JsonObject rep, final HttpClient client, final URI uri) { + RtImage( + final JsonObject rep, final HttpClient client, + final URI uri, final Docker dkr + ) { super(rep); this.client = client; this.baseUri = uri; + this.docker = dkr; } @Override @@ -77,7 +88,8 @@ public Iterable history() { json -> new RtImage( json, this.client, - this.baseUri + this.baseUri, + this.docker ) ); } @@ -115,4 +127,15 @@ public void tag( tag.releaseConnection(); } } + + @Override + public Container run() throws IOException, UnexpectedResponseException { + final Container container = this.docker.containers().create( + this.baseUri.getPath().substring( + this.baseUri.getPath().lastIndexOf('/') + 1 + ) + ); + container.start(); + return container; + } } diff --git a/src/main/java/com/amihaiemil/docker/RtImages.java b/src/main/java/com/amihaiemil/docker/RtImages.java index f94d9dc6..881de05e 100644 --- a/src/main/java/com/amihaiemil/docker/RtImages.java +++ b/src/main/java/com/amihaiemil/docker/RtImages.java @@ -53,14 +53,21 @@ final class RtImages implements Images { */ private final URI baseUri; + /** + * Docker API. + */ + private final Docker docker; + /** * Ctor. * @param client The http client. * @param uri The URI for this Images API. + * @param dkr The docker entry point. */ - RtImages(final HttpClient client, final URI uri) { + RtImages(final HttpClient client, final URI uri, final Docker dkr) { this.client = client; this.baseUri = uri; + this.docker = dkr; } @Override @@ -83,7 +90,8 @@ public Image pull( this.client, URI.create( this.baseUri.toString() + "/" + name - ) + ), + this.docker ); } finally { create.releaseConnection(); @@ -125,7 +133,8 @@ public Iterator iterator() { this.client, URI.create( this.baseUri.toString() + "/" + json.getString("Id") - ) + ), + this.docker ) ); } diff --git a/src/test/java/com/amihaiemil/docker/RtImageTestCase.java b/src/test/java/com/amihaiemil/docker/RtImageTestCase.java index 1c012844..f4b6c20e 100644 --- a/src/test/java/com/amihaiemil/docker/RtImageTestCase.java +++ b/src/test/java/com/amihaiemil/docker/RtImageTestCase.java @@ -29,12 +29,15 @@ import com.amihaiemil.docker.mock.Condition; import com.amihaiemil.docker.mock.Response; import java.net.URI; +import java.util.concurrent.atomic.AtomicBoolean; import javax.json.Json; import javax.json.JsonObject; 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 RtImage. @@ -44,6 +47,10 @@ * @checkstyle MethodName (500 lines) */ public final class RtImageTestCase { + /** + * Mock docker. + */ + private static final Docker DOCKER = Mockito.mock(Docker.class); /** * RtImage can return info about itself. @@ -72,7 +79,8 @@ public void inspectsItself() throws Exception { req -> req.getRequestLine().getUri().endsWith("/456/json") ) ), - URI.create("http://localhost:80/1.30/images/456") + URI.create("http://localhost:80/1.30/images/456"), + DOCKER ); final JsonObject info = image.inspect(); MatcherAssert.assertThat(info.keySet(), Matchers.hasSize(4)); @@ -105,7 +113,8 @@ public void returnsHistory() { Json.createArrayBuilder().build().toString() ) ), - URI.create("http://localhost:80/1.30/images/456") + URI.create("http://localhost:80/1.30/images/456"), + DOCKER ).history(), Matchers.allOf( Matchers.notNullValue(), @@ -135,7 +144,8 @@ public void deleteSendsCorrectRequest() throws Exception { ) ) ), - URI.create("http://localhost/images/test") + URI.create("http://localhost/images/test"), + DOCKER ).delete(); } @@ -151,7 +161,8 @@ public void deleteErrorOn404() throws Exception { new AssertRequest( new Response(HttpStatus.SC_NOT_FOUND) ), - URI.create("http://localhost/images/test") + URI.create("http://localhost/images/test"), + DOCKER ).delete(); } @@ -167,7 +178,8 @@ public void deleteErrorOn409() throws Exception { new AssertRequest( new Response(HttpStatus.SC_CONFLICT) ), - URI.create("http://localhost/images/test") + URI.create("http://localhost/images/test"), + DOCKER ).delete(); } @@ -183,7 +195,8 @@ public void deleteErrorOn500() throws Exception { new AssertRequest( new Response(HttpStatus.SC_INTERNAL_SERVER_ERROR) ), - URI.create("http://localhost/images/test") + URI.create("http://localhost/images/test"), + DOCKER ).delete(); } @@ -210,7 +223,8 @@ public void tagsOk() throws Exception { ) ) ), - URI.create("http://localhost/images/123") + URI.create("http://localhost/images/123"), + DOCKER ).tag("myrepo/myimage", "mytag"); } @@ -226,7 +240,8 @@ public void tagErrorIfResponseIs400() throws Exception { new AssertRequest( new Response(HttpStatus.SC_BAD_REQUEST) ), - URI.create("https://localhost") + URI.create("https://localhost"), + DOCKER ).tag("myrepo/myimage", "mytag"); } @@ -242,7 +257,8 @@ public void tagErrorIfResponseIs404() throws Exception { new AssertRequest( new Response(HttpStatus.SC_NOT_FOUND) ), - URI.create("https://localhost") + URI.create("https://localhost"), + DOCKER ).tag("myrepo/myimage", "mytag"); } @@ -258,7 +274,8 @@ public void tagErrorIfResponseIs409() throws Exception { new AssertRequest( new Response(HttpStatus.SC_CONFLICT) ), - URI.create("https://localhost") + URI.create("https://localhost"), + DOCKER ).tag("myrepo/myimage", "mytag"); } @@ -274,7 +291,42 @@ public void tagErrorIfResponseIs500() throws Exception { new AssertRequest( new Response(HttpStatus.SC_INTERNAL_SERVER_ERROR) ), - URI.create("https://localhost") + URI.create("https://localhost"), + DOCKER ).tag("myrepo/myimage", "mytag"); } + + /** + * RtImage can run itself. + * @throws Exception If something goes wrong. + */ + @Test + public void runsItselfOk() throws Exception { + final AtomicBoolean started = new AtomicBoolean(false); + final Container container = Mockito.mock(Container.class); + Mockito.doAnswer( + invocation -> { + started.set(true); + return null; + } + ).when(container).start(); + final Containers containers = Mockito.mock(Containers.class); + Mockito.doReturn(container) + .when(containers) + .create(Mockito.eq("image123")); + Mockito.doReturn(containers).when(DOCKER).containers(); + MatcherAssert.assertThat( + new RtImage( + Mockito.mock(JsonObject.class), + Mockito.mock(HttpClient.class), + URI.create("http://localhost/images/image123"), + DOCKER + ).run(), + Matchers.notNullValue() + ); + MatcherAssert.assertThat( + started.get(), + Matchers.is(true) + ); + } } diff --git a/src/test/java/com/amihaiemil/docker/RtImagesTestCase.java b/src/test/java/com/amihaiemil/docker/RtImagesTestCase.java index ca683ac5..dcc7b921 100644 --- a/src/test/java/com/amihaiemil/docker/RtImagesTestCase.java +++ b/src/test/java/com/amihaiemil/docker/RtImagesTestCase.java @@ -35,6 +35,7 @@ import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.Test; +import org.mockito.Mockito; /** * Unit tests for {@link RtImages}. @@ -44,6 +45,11 @@ * @checkstyle MethodName (500 lines) */ public final class RtImagesTestCase { + /** + * Mock docker. + */ + private static final Docker DOCKER = Mockito.mock(Docker.class); + /** * Must return the same number of images as there are elements in the * json array returned by the service. @@ -64,7 +70,9 @@ public void iteratesImages() { .add("Id", "sha256:3e314f95dcace0f5e") ).build().toString() ) - ), URI.create("http://localhost") + ), + URI.create("http://localhost"), + DOCKER ).forEach(image -> count.incrementAndGet()); MatcherAssert.assertThat( count.get(), @@ -85,7 +93,9 @@ public void iteratesZeroImages() throws Exception { HttpStatus.SC_OK, Json.createArrayBuilder().build().toString() ) - ), URI.create("http://localhost") + ), + URI.create("http://localhost"), + DOCKER ).forEach(image -> count.incrementAndGet()); MatcherAssert.assertThat( count.get(), @@ -103,7 +113,8 @@ public void iterateFailsIfResponseIs500() throws Exception { new AssertRequest( new Response(HttpStatus.SC_INTERNAL_SERVER_ERROR) ), - URI.create("http://localhost") + URI.create("http://localhost"), + DOCKER ).iterator(); } @@ -131,7 +142,8 @@ public void createSetsGivenParameters() throws Exception { } ) ), - URI.create("http://localhost") + URI.create("http://localhost"), + DOCKER ).pull("testImage", "1.23"); } @@ -146,7 +158,8 @@ public void createErrorOnStatus404() throws Exception { new AssertRequest( new Response(HttpStatus.SC_NOT_FOUND) ), - URI.create("http://localhost") + URI.create("http://localhost"), + DOCKER ).pull("", ""); } @@ -161,7 +174,8 @@ public void createErrorOnStatus500() throws Exception { new AssertRequest( new Response(HttpStatus.SC_INTERNAL_SERVER_ERROR) ), - URI.create("http://localhost") + URI.create("http://localhost"), + DOCKER ).pull("", ""); } @@ -185,7 +199,8 @@ public void prunesOk() throws Exception { .getUri().endsWith("/images/prune") ) ), - URI.create("http://localhost/images") + URI.create("http://localhost/images"), + DOCKER ).prune(); } @@ -200,7 +215,8 @@ public void pruneThrowsErrorOnResponse500() throws Exception { new AssertRequest( new Response(HttpStatus.SC_INTERNAL_SERVER_ERROR) ), - URI.create("http://localhost/images") + URI.create("http://localhost/images"), + DOCKER ).prune(); } }