Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions src/main/java/com/amihaiemil/docker/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@
* @version $Id$
* @see <a href="https://docs.docker.com/engine/api/v1.35/#tag/Image">Docker Images API</a>
* @since 0.0.1
* @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 {

Expand All @@ -58,11 +55,25 @@ public interface Image {
Images history();

/**
* The parent {@link Images}.
* Remove an image, along with any untagged parent images that were
* referenced by that image.
* @throws IOException If something goes wrong.
* @throws UnexpectedResponseException If the status response is not
* the expected one (200 OK).
* @see <a href="https://docs.docker.com/engine/api/v1.35/#operation/ImageDelete">Remove an image</a>
*/
void delete() throws IOException, UnexpectedResponseException;

/**
* Tags this image so that it becomes part of a repository.
* @param repo The repository to tag in. Eg.: "someuser/someimage"
* @param name The name of the new tag.
* @throws IOException If something goes wrong.
* @throws UnexpectedResponseException If the status response is not
* the expected one.
* @see <a href="https://docs.docker.com/engine/api/v1.35/#operation/ImageTag">Tag an image</a>
*/
void tag(
String repo, String name
) throws IOException, UnexpectedResponseException;
}
22 changes: 22 additions & 0 deletions src/main/java/com/amihaiemil/docker/RtImage.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;

/**
* Runtime {@link Image}.
Expand Down Expand Up @@ -88,4 +89,25 @@ public void delete() throws IOException, UnexpectedResponseException {
delete.releaseConnection();
}
}

@Override
public void tag(
final String repo, final String name
) throws IOException, UnexpectedResponseException {
final HttpPost tag = new HttpPost(
new UncheckedUriBuilder(
this.baseUri.toString() + "/tag"
).addParameter("repo", repo)
.addParameter("tag", name)
.build()
);
try {
this.client.execute(
tag,
new MatchStatus(tag.getURI(), HttpStatus.SC_CREATED)
);
} finally {
tag.releaseConnection();
}
}
}
86 changes: 86 additions & 0 deletions src/test/java/com/amihaiemil/docker/RtImageTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,90 @@ public void deleteErrorOn500() throws Exception {
URI.create("http://localhost/images/test")
).delete();
}

/**
* RtImage.tag() must send a POST request to the image's URL.
*
* Note the escaped forward slash in the query parameters.
* @throws Exception If something goes wrong.
*/
@Test
public void tagsOk() throws Exception {
new RtImage(
new AssertRequest(
new Response(HttpStatus.SC_CREATED),
new Condition(
"RtImage.tag() must send a POST request",
req -> "POST".equals(req.getRequestLine().getMethod())
),
new Condition(
"RtImage.tag() not building the URL correctly",
req -> req.getRequestLine().getUri().endsWith(
"/images/123/tag?repo=myrepo%2Fmyimage&tag=mytag"
)
)
),
URI.create("http://localhost/images/123")
).tag("myrepo/myimage", "mytag");
}

/**
* RtImage.tag() must throw UnexpectedResponseException if docker responds
* with 400.
* @throws Exception The UnexpectedResponseException.
*/
@Test(expected = UnexpectedResponseException.class)
public void tagErrorIfResponseIs400() throws Exception {
new RtImage(
new AssertRequest(
new Response(HttpStatus.SC_BAD_REQUEST)
),
URI.create("https://localhost")
).tag("myrepo/myimage", "mytag");
}

/**
* RtImage.tag() must throw UnexpectedResponseException if docker responds
* with 404.
* @throws Exception The UnexpectedResponseException.
*/
@Test(expected = UnexpectedResponseException.class)
public void tagErrorIfResponseIs404() throws Exception {
new RtImage(
new AssertRequest(
new Response(HttpStatus.SC_NOT_FOUND)
),
URI.create("https://localhost")
).tag("myrepo/myimage", "mytag");
}

/**
* RtImage.tag() must throw UnexpectedResponseException if docker responds
* with 409.
* @throws Exception The UnexpectedResponseException.
*/
@Test(expected = UnexpectedResponseException.class)
public void tagErrorIfResponseIs409() throws Exception {
new RtImage(
new AssertRequest(
new Response(HttpStatus.SC_CONFLICT)
),
URI.create("https://localhost")
).tag("myrepo/myimage", "mytag");
}

/**
* RtImage.tag() must throw UnexpectedResponseException if docker responds
* with 500.
* @throws Exception The UnexpectedResponseException.
*/
@Test(expected = UnexpectedResponseException.class)
public void tagErrorIfResponseIs500() throws Exception {
new RtImage(
new AssertRequest(
new Response(HttpStatus.SC_INTERNAL_SERVER_ERROR)
),
URI.create("https://localhost")
).tag("myrepo/myimage", "mytag");
}
}