From 00946c0e4e6ef35ae03d0d02383b8088454d7212 Mon Sep 17 00:00:00 2001 From: George Aristy Date: Tue, 8 May 2018 14:33:13 -0400 Subject: [PATCH 1/2] (#96) Implemented Image.delete() --- .../java/com/amihaiemil/docker/Image.java | 16 ++- .../java/com/amihaiemil/docker/RtImage.java | 29 ++++- .../java/com/amihaiemil/docker/RtImages.java | 3 +- .../amihaiemil/docker/RtImageTestCase.java | 122 +++++++++++++++++- 4 files changed, 163 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/amihaiemil/docker/Image.java b/src/main/java/com/amihaiemil/docker/Image.java index b0741724..7adae419 100644 --- a/src/main/java/com/amihaiemil/docker/Image.java +++ b/src/main/java/com/amihaiemil/docker/Image.java @@ -34,8 +34,9 @@ * @version $Id$ * @see Docker Images API * @since 0.0.1 - * @todo #86:30min Continue implementing the operations that affect a single - * docker image. See the link referenced above. + * @todo #96:30min Finish implementing the operations that affect a single + * docker image (I think `tag` is the only one remaining). See the link + * referenced above. */ public interface Image { @@ -55,5 +56,14 @@ public interface Image { * @see Image History */ Images history(); - + + /** + * The parent {@link Images}. + * @return The parent {@link Images} API. + * @throws IOException If something goes wrong. + * @throws UnexpectedResponseException If the status response is not + * the expected one (200 OK). + * @see Remove an image + */ + Images delete() throws IOException, UnexpectedResponseException; } diff --git a/src/main/java/com/amihaiemil/docker/RtImage.java b/src/main/java/com/amihaiemil/docker/RtImage.java index fa6c88dc..b3896907 100644 --- a/src/main/java/com/amihaiemil/docker/RtImage.java +++ b/src/main/java/com/amihaiemil/docker/RtImage.java @@ -28,7 +28,9 @@ import java.io.IOException; import java.net.URI; import javax.json.JsonObject; +import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpDelete; /** * Runtime {@link Image}. @@ -47,14 +49,21 @@ final class RtImage implements Image { */ private final URI baseUri; + /** + * The enclosing {@link Images} for this image. + */ + private final Images parent; + /** * Ctor. * @param client The http client. * @param uri The URI for this image. + * @param images The parent Images API. */ - RtImage(final HttpClient client, final URI uri) { + RtImage(final HttpClient client, final URI uri, final Images images) { this.client = client; this.baseUri = uri; + this.parent = images; } @Override @@ -69,4 +78,22 @@ public Images history() { this.client, URI.create(this.baseUri.toString() + "/history") ); } + + @Override + public Images delete() throws IOException, UnexpectedResponseException { + final HttpDelete delete = new HttpDelete(this.baseUri); + try { + final int status = this.client.execute(delete) + .getStatusLine() + .getStatusCode(); + if (status != HttpStatus.SC_OK) { + throw new UnexpectedResponseException( + delete.getRequestLine().getUri(), status, HttpStatus.SC_OK + ); + } + } finally { + delete.releaseConnection(); + } + return this.parent; + } } diff --git a/src/main/java/com/amihaiemil/docker/RtImages.java b/src/main/java/com/amihaiemil/docker/RtImages.java index 59e510d8..22ca9cf6 100644 --- a/src/main/java/com/amihaiemil/docker/RtImages.java +++ b/src/main/java/com/amihaiemil/docker/RtImages.java @@ -86,7 +86,8 @@ public Iterable iterate() throws IOException { this.client, URI.create( this.baseUri.toString() + "/" + json.getString("Id") - ) + ), + this )).collect(Collectors.toList()); } finally { get.releaseConnection(); diff --git a/src/test/java/com/amihaiemil/docker/RtImageTestCase.java b/src/test/java/com/amihaiemil/docker/RtImageTestCase.java index b8686faa..8ca648ae 100644 --- a/src/test/java/com/amihaiemil/docker/RtImageTestCase.java +++ b/src/test/java/com/amihaiemil/docker/RtImageTestCase.java @@ -28,7 +28,9 @@ import com.amihaiemil.docker.mock.AssertRequest; import com.amihaiemil.docker.mock.Condition; import com.amihaiemil.docker.mock.Response; +import java.io.IOException; import java.net.URI; +import java.net.URL; import javax.json.Json; import javax.json.JsonObject; import org.apache.http.HttpStatus; @@ -41,6 +43,7 @@ * @author Mihai Andronache (amihaiemil@gmail.com) * @version $Id$ * @since 0.0.1 + * @checkstyle MethodName (500 lines) */ public final class RtImageTestCase { @@ -70,7 +73,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"), + new MockImages() ); final JsonObject info = image.inspect(); MatcherAssert.assertThat(info.keySet(), Matchers.hasSize(4)); @@ -102,7 +106,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"), + new MockImages() ).history(), Matchers.allOf( Matchers.notNullValue(), @@ -110,4 +115,117 @@ public void returnsHistory() { ) ); } + + + /** + * RtImage.delete() must send a DELETE request to the image's url. + * @throws Exception If something goes wrong. + */ + @Test + public void deleteSendsCorrectRequest() throws Exception { + new RtImage( + new AssertRequest( + new Response(HttpStatus.SC_OK), + new Condition( + "RtImages.delete() must send a DELETE HTTP request", + req -> "DELETE".equals(req.getRequestLine().getMethod()) + ), + new Condition( + "RtImages.delete() must send the request to the image url", + req -> "http://localhost/images/test".equals( + req.getRequestLine().getUri() + ) + ) + ), + URI.create("http://localhost/images/test"), + new MockImages() + ).delete(); + } + + /** + * RtImage.delete() can delete itself and return the parent images. + * @throws Exception If something goes wrong. + */ + @Test + public void deleteItself() throws Exception { + final Images images = new MockImages(); + MatcherAssert.assertThat( + new RtImage( + new AssertRequest( + new Response(HttpStatus.SC_OK) + ), + URI.create("http://localhost/images/test"), + images + ).delete(), + Matchers.is(images) + ); + } + + /** + * RtImage.delete() must throw UnexpectedResponseException if service + * responds with 404. + * @throws Exception The UnexpectedResponseException + */ + @Test(expected = UnexpectedResponseException.class) + public void deleteErrorOn404() throws Exception { + new RtImage( + new AssertRequest( + new Response(HttpStatus.SC_NOT_FOUND) + ), + URI.create("http://localhost/images/test"), + new MockImages() + ).delete(); + } + + /** + * RtImage.delete() must throw UnexpectedResponseException if service + * responds with 409. + * @throws Exception The UnexpectedResponseException + */ + @Test(expected = UnexpectedResponseException.class) + public void deleteErrorOn409() throws Exception { + new RtImage( + new AssertRequest( + new Response(HttpStatus.SC_CONFLICT) + ), + URI.create("http://localhost/images/test"), + new MockImages() + ).delete(); + } + + /** + * RtImage.delete() must throw UnexpectedResponseException if service + * responds with 500. + * @throws Exception The UnexpectedResponseException + */ + @Test(expected = UnexpectedResponseException.class) + public void deleteErrorOn500() throws Exception { + new RtImage( + new AssertRequest( + new Response(HttpStatus.SC_INTERNAL_SERVER_ERROR) + ), + URI.create("http://localhost/images/test"), + new MockImages() + ).delete(); + } + + /** + * Mock {@link Images}. + */ + private static class MockImages implements Images { + @Override + public Iterable iterate() + throws IOException, UnexpectedResponseException { + throw new UnsupportedOperationException(); + } + @Override + // @checkstyle ParameterNumber (1 line) + public Images create( + final String name, final URL source, + final String repo, final String tag + ) throws IOException, UnexpectedResponseException { + throw new UnsupportedOperationException(); + } + } + } From f535538a3259414457662865c5b01c1b6f591ef4 Mon Sep 17 00:00:00 2001 From: George Aristy Date: Wed, 9 May 2018 14:13:33 -0400 Subject: [PATCH 2/2] (#96) Implemented Image.delete() As per PR review: * Made Image.delete() return void --- .../java/com/amihaiemil/docker/Image.java | 3 +- .../java/com/amihaiemil/docker/RtImage.java | 12 +--- .../java/com/amihaiemil/docker/RtImages.java | 3 +- .../amihaiemil/docker/RtImageTestCase.java | 60 ++----------------- 4 files changed, 10 insertions(+), 68 deletions(-) diff --git a/src/main/java/com/amihaiemil/docker/Image.java b/src/main/java/com/amihaiemil/docker/Image.java index 7adae419..329f4f4f 100644 --- a/src/main/java/com/amihaiemil/docker/Image.java +++ b/src/main/java/com/amihaiemil/docker/Image.java @@ -59,11 +59,10 @@ public interface Image { /** * The parent {@link Images}. - * @return The parent {@link Images} API. * @throws IOException If something goes wrong. * @throws UnexpectedResponseException If the status response is not * the expected one (200 OK). * @see Remove an image */ - Images delete() throws IOException, UnexpectedResponseException; + void delete() throws IOException, UnexpectedResponseException; } diff --git a/src/main/java/com/amihaiemil/docker/RtImage.java b/src/main/java/com/amihaiemil/docker/RtImage.java index b3896907..b2bda47b 100644 --- a/src/main/java/com/amihaiemil/docker/RtImage.java +++ b/src/main/java/com/amihaiemil/docker/RtImage.java @@ -49,21 +49,14 @@ final class RtImage implements Image { */ private final URI baseUri; - /** - * The enclosing {@link Images} for this image. - */ - private final Images parent; - /** * Ctor. * @param client The http client. * @param uri The URI for this image. - * @param images The parent Images API. */ - RtImage(final HttpClient client, final URI uri, final Images images) { + RtImage(final HttpClient client, final URI uri) { this.client = client; this.baseUri = uri; - this.parent = images; } @Override @@ -80,7 +73,7 @@ public Images history() { } @Override - public Images delete() throws IOException, UnexpectedResponseException { + public void delete() throws IOException, UnexpectedResponseException { final HttpDelete delete = new HttpDelete(this.baseUri); try { final int status = this.client.execute(delete) @@ -94,6 +87,5 @@ public Images delete() throws IOException, UnexpectedResponseException { } finally { delete.releaseConnection(); } - return this.parent; } } diff --git a/src/main/java/com/amihaiemil/docker/RtImages.java b/src/main/java/com/amihaiemil/docker/RtImages.java index 22ca9cf6..59e510d8 100644 --- a/src/main/java/com/amihaiemil/docker/RtImages.java +++ b/src/main/java/com/amihaiemil/docker/RtImages.java @@ -86,8 +86,7 @@ public Iterable iterate() throws IOException { this.client, URI.create( this.baseUri.toString() + "/" + json.getString("Id") - ), - this + ) )).collect(Collectors.toList()); } finally { get.releaseConnection(); diff --git a/src/test/java/com/amihaiemil/docker/RtImageTestCase.java b/src/test/java/com/amihaiemil/docker/RtImageTestCase.java index 8ca648ae..0673871b 100644 --- a/src/test/java/com/amihaiemil/docker/RtImageTestCase.java +++ b/src/test/java/com/amihaiemil/docker/RtImageTestCase.java @@ -28,9 +28,7 @@ import com.amihaiemil.docker.mock.AssertRequest; import com.amihaiemil.docker.mock.Condition; import com.amihaiemil.docker.mock.Response; -import java.io.IOException; import java.net.URI; -import java.net.URL; import javax.json.Json; import javax.json.JsonObject; import org.apache.http.HttpStatus; @@ -73,8 +71,7 @@ public void inspectsItself() throws Exception { req -> req.getRequestLine().getUri().endsWith("/456/json") ) ), - URI.create("http://localhost:80/1.30/images/456"), - new MockImages() + URI.create("http://localhost:80/1.30/images/456") ); final JsonObject info = image.inspect(); MatcherAssert.assertThat(info.keySet(), Matchers.hasSize(4)); @@ -106,8 +103,7 @@ public void returnsHistory() { Json.createArrayBuilder().build().toString() ) ), - URI.create("http://localhost:80/1.30/images/456"), - new MockImages() + URI.create("http://localhost:80/1.30/images/456") ).history(), Matchers.allOf( Matchers.notNullValue(), @@ -116,7 +112,6 @@ public void returnsHistory() { ); } - /** * RtImage.delete() must send a DELETE request to the image's url. * @throws Exception If something goes wrong. @@ -137,30 +132,10 @@ public void deleteSendsCorrectRequest() throws Exception { ) ) ), - URI.create("http://localhost/images/test"), - new MockImages() + URI.create("http://localhost/images/test") ).delete(); } - /** - * RtImage.delete() can delete itself and return the parent images. - * @throws Exception If something goes wrong. - */ - @Test - public void deleteItself() throws Exception { - final Images images = new MockImages(); - MatcherAssert.assertThat( - new RtImage( - new AssertRequest( - new Response(HttpStatus.SC_OK) - ), - URI.create("http://localhost/images/test"), - images - ).delete(), - Matchers.is(images) - ); - } - /** * RtImage.delete() must throw UnexpectedResponseException if service * responds with 404. @@ -172,8 +147,7 @@ public void deleteErrorOn404() throws Exception { new AssertRequest( new Response(HttpStatus.SC_NOT_FOUND) ), - URI.create("http://localhost/images/test"), - new MockImages() + URI.create("http://localhost/images/test") ).delete(); } @@ -188,8 +162,7 @@ public void deleteErrorOn409() throws Exception { new AssertRequest( new Response(HttpStatus.SC_CONFLICT) ), - URI.create("http://localhost/images/test"), - new MockImages() + URI.create("http://localhost/images/test") ).delete(); } @@ -204,28 +177,7 @@ public void deleteErrorOn500() throws Exception { new AssertRequest( new Response(HttpStatus.SC_INTERNAL_SERVER_ERROR) ), - URI.create("http://localhost/images/test"), - new MockImages() + URI.create("http://localhost/images/test") ).delete(); } - - /** - * Mock {@link Images}. - */ - private static class MockImages implements Images { - @Override - public Iterable iterate() - throws IOException, UnexpectedResponseException { - throw new UnsupportedOperationException(); - } - @Override - // @checkstyle ParameterNumber (1 line) - public Images create( - final String name, final URL source, - final String repo, final String tag - ) throws IOException, UnexpectedResponseException { - throw new UnsupportedOperationException(); - } - } - }