diff --git a/CHANGELOG.md b/CHANGELOG.md index b76a052d8..808cae3c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,16 @@ Change Log === + Latest SNAPSHOT --- -* [#248](https://github.com/docker-java/docker-java/pull/233) Removed deprecated start options + +* [#263](https://github.com/docker-java/docker-java/pull/263) Refactoring of streaming commands APIs (event, stats, log, attach) +* [#262](https://github.com/docker-java/docker-java/pull/262) Accept filters in list containers +* [#260](https://github.com/docker-java/docker-java/pull/260) Add labels to create and inspect container + +v.1.4.0 +--- +* [#248](https://github.com/docker-java/docker-java/pull/248) Removed deprecated start options * [#247](https://github.com/docker-java/docker-java/pull/247) Add Domainname attribute on create command * [#245](https://github.com/docker-java/docker-java/pull/245) Added ReadonlyRootfs option * [#233](https://github.com/docker-java/docker-java/pull/233) Labels are array of Strings (fixes #232) diff --git a/README.md b/README.md index a4c18a0ce..5c6c55d31 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Java API client for [Docker](http://docs.docker.io/ "Docker") -Supports a subset of the Docker Remote API [v1.18](https://github.com/docker/docker/blob/master/docs/reference/api/docker_remote_api_v1.18.md), Docker Server version 1.6.x +Supports a subset of the Docker Remote API [v1.19](https://github.com/docker/docker/blob/master/docs/reference/api/docker_remote_api_v1.19.md), Docker Server version 1.7.x The current implementation is based on Jersey 2.x and therefore classpath incompatible with older Jersey 1.x dependent libraries! @@ -64,7 +64,7 @@ Run build without integration tests: com.github.docker-java docker-java - 1.3.0 + 1.4.0 ### Latest SNAPSHOT version @@ -74,7 +74,7 @@ You can find the latest SNAPSHOT version including javadoc and source files on [ com.github.docker-java docker-java - 1.3.1-SNAPSHOT + 1.4.1-SNAPSHOT ## Documentation diff --git a/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java b/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java index 3b558b6d9..9ad44b2c4 100644 --- a/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java @@ -1,5 +1,7 @@ package com.github.dockerjava.api.command; +import java.util.Map; + import com.github.dockerjava.api.ConflictException; import com.github.dockerjava.api.NotFoundException; import com.github.dockerjava.api.model.Bind; @@ -41,6 +43,26 @@ public static interface Exec extends DockerCmdExec labels); + /** * Add link to another container. */ @@ -238,4 +282,9 @@ public static interface Exec extends DockerCmdExec getLabels(); + } diff --git a/src/main/java/com/github/dockerjava/api/command/EventsCmd.java b/src/main/java/com/github/dockerjava/api/command/EventsCmd.java index 057bed644..e691bbc94 100644 --- a/src/main/java/com/github/dockerjava/api/command/EventsCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/EventsCmd.java @@ -1,6 +1,7 @@ package com.github.dockerjava.api.command; import com.github.dockerjava.api.model.Event; +import com.github.dockerjava.api.model.Filters; /** * Get events @@ -19,6 +20,10 @@ public interface EventsCmd extends AsyncDockerCmd { public String getUntil(); + public Filters getFilters(); + + public EventsCmd withFilters(Filters filters); + public static interface Exec extends DockerCmdExec { } } diff --git a/src/main/java/com/github/dockerjava/api/command/ListContainersCmd.java b/src/main/java/com/github/dockerjava/api/command/ListContainersCmd.java index 6d641f2e3..c2a116bed 100644 --- a/src/main/java/com/github/dockerjava/api/command/ListContainersCmd.java +++ b/src/main/java/com/github/dockerjava/api/command/ListContainersCmd.java @@ -3,6 +3,7 @@ import java.util.List; import com.github.dockerjava.api.model.Container; +import com.github.dockerjava.api.model.Filters; /** * List containers @@ -31,6 +32,8 @@ public interface ListContainersCmd extends DockerCmd> { public String getBeforeId(); + public Filters getFilters(); + public ListContainersCmd withShowAll(boolean showAll); public ListContainersCmd withShowSize(boolean showSize); @@ -41,6 +44,8 @@ public interface ListContainersCmd extends DockerCmd> { public ListContainersCmd withBefore(String before); + public ListContainersCmd withFilters(Filters filters); + public static interface Exec extends DockerCmdExec> { } diff --git a/src/main/java/com/github/dockerjava/api/model/Container.java b/src/main/java/com/github/dockerjava/api/model/Container.java index 6a97e20b9..8152974e3 100644 --- a/src/main/java/com/github/dockerjava/api/model/Container.java +++ b/src/main/java/com/github/dockerjava/api/model/Container.java @@ -1,5 +1,7 @@ package com.github.dockerjava.api.model; +import java.util.Map; + import org.apache.commons.lang.builder.ToStringBuilder; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -31,6 +33,9 @@ public class Container { @JsonProperty("Ports") public Port[] ports; + @JsonProperty("Labels") + public Map labels; + @JsonProperty("Status") private String status; @@ -58,6 +63,10 @@ public Port[] getPorts() { return ports; } + public Map getLabels() { + return labels; + } + public String[] getNames() { return names; } diff --git a/src/main/java/com/github/dockerjava/api/model/ContainerConfig.java b/src/main/java/com/github/dockerjava/api/model/ContainerConfig.java index 8ea673a36..0478e5ef0 100644 --- a/src/main/java/com/github/dockerjava/api/model/ContainerConfig.java +++ b/src/main/java/com/github/dockerjava/api/model/ContainerConfig.java @@ -51,6 +51,9 @@ public class ContainerConfig { @JsonProperty("Image") private String image; + @JsonProperty("Labels") + private Map labels; + @JsonProperty("MacAddress") private String macAddress; @@ -184,6 +187,10 @@ public String[] getOnBuild() { return onBuild; } + public Map getLabels() { + return labels; + } + @Override public String toString() { return ToStringBuilder.reflectionToString(this); diff --git a/src/main/java/com/github/dockerjava/api/model/Event.java b/src/main/java/com/github/dockerjava/api/model/Event.java index 27eb22216..14637d6e7 100644 --- a/src/main/java/com/github/dockerjava/api/model/Event.java +++ b/src/main/java/com/github/dockerjava/api/model/Event.java @@ -1,10 +1,12 @@ package com.github.dockerjava.api.model; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.apache.commons.lang.builder.ToStringBuilder; /** * Representation of a Docker event. */ +@JsonIgnoreProperties(ignoreUnknown = true) public class Event { private String status; @@ -14,6 +16,9 @@ public class Event { private long time; + @JsonIgnoreProperties + private Node node; + /** * Default constructor for the deserialization. */ @@ -22,7 +27,7 @@ public Event() { /** * Constructor. - * + * * @param id * Container ID * @param status @@ -46,7 +51,7 @@ public Event(String status, String id, String from, long time) { * Status of docker image or container. List of statuses is available in Docker API * v.1.16 - * + * * @return Status string */ public String getStatus() { @@ -55,7 +60,7 @@ public String getStatus() { /** * Get ID of docker container. - * + * * @return Container ID */ public String getId() { @@ -64,7 +69,7 @@ public String getId() { /** * Get source image of the container. - * + * * @return Name of the parent container */ public String getFrom() { @@ -73,13 +78,20 @@ public String getFrom() { /** * Get the event time. The time is specified in milliseconds since January 1, 1970, 00:00:00 GMT - * + * * @return Event time in the specified format. */ public long getTime() { return time; } + /** + * Returns the node when working against docker swarm + */ + public Node getNode() { + return node; + } + @Override public String toString() { return ToStringBuilder.reflectionToString(this); diff --git a/src/main/java/com/github/dockerjava/api/model/EventFilters.java b/src/main/java/com/github/dockerjava/api/model/EventFilters.java new file mode 100644 index 000000000..08cb7ad11 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/model/EventFilters.java @@ -0,0 +1,37 @@ +package com.github.dockerjava.api.model; + +import java.util.List; + +/** + * Representation of a Docker event filter. + * + * @author Carlos Sanchez + * + */ +public class EventFilters extends Filters { + + /** + * Default constructor for the deserialization. + */ + public EventFilters() { + } + + /** + * Constructor. + * + * @param event + * event to filter + */ + public EventFilters(String... event) { + super(); + withEvent(event); + } + + public Filters withEvent(String... event) { + return withFilter("event", event); + } + + public List getEvent() { + return getFilter("event"); + } +} diff --git a/src/main/java/com/github/dockerjava/api/model/Filters.java b/src/main/java/com/github/dockerjava/api/model/Filters.java new file mode 100644 index 000000000..b912b541a --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/model/Filters.java @@ -0,0 +1,103 @@ +package com.github.dockerjava.api.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.ws.rs.core.MediaType; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; + +/** + * Representation of Docker filters. + * + * @author Carlos Sanchez + * + */ +public class Filters { + + private static ObjectMapper OBJECT_MAPPER = new JacksonJaxbJsonProvider().locateMapper(Map.class, + MediaType.APPLICATION_JSON_TYPE); + + private Map> filters = new HashMap>(); + + public Filters() { + } + + public Filters withFilter(String key, String... value) { + filters.put(key, Arrays.asList(value)); + return this; + } + + public List getFilter(String key) { + return filters.get(key); + } + + public Filters withImages(String... image) { + withFilter("image", image); + return this; + } + + public List getImage() { + return getFilter("image"); + } + + public Filters withContainers(String... container) { + withFilter("container", container); + return this; + } + + public List getContainer() { + return getFilter("container"); + } + + /** + * Filter by labels + * + * @param labels + * string array in the form ["key"] or ["key=value"] or a mix of both + * @return + */ + public Filters withLabels(String... labels) { + withFilter("label", labels); + return this; + } + + /** + * Filter by labels + * + * @param labels + * {@link Map} of labels that contains label keys and values + * @return + */ + public Filters withLabels(Map labels) { + withFilter("label", labelsMapToList(labels).toArray(new String[labels.size()])); + return this; + } + + private static List labelsMapToList(Map labels) { + List result = new ArrayList(); + for (Entry entry : labels.entrySet()) { + String rest = (entry.getValue() != null & !entry.getValue().isEmpty()) ? "=" + entry.getValue() : ""; + + String label = entry.getKey() + rest; + + result.add(label); + } + return result; + } + + @Override + public String toString() { + try { + return OBJECT_MAPPER.writeValueAsString(filters); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com/github/dockerjava/api/model/Node.java b/src/main/java/com/github/dockerjava/api/model/Node.java new file mode 100644 index 000000000..4bbeeec38 --- /dev/null +++ b/src/main/java/com/github/dockerjava/api/model/Node.java @@ -0,0 +1,37 @@ +package com.github.dockerjava.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A node as returned by the /events API, for instance, when Swarm is used. + */ +public class Node { + + @JsonProperty("Name") + private String name; + + @JsonProperty("Id") + private String id; + + @JsonProperty("Addr") + private String addr; + + @JsonProperty("Ip") + private String ip; + + public String getName() { + return name; + } + + public String getId() { + return id; + } + + public String getAddr() { + return addr; + } + + public String getIp() { + return ip; + } +} diff --git a/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java b/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java index d9a408c35..94d199a6f 100644 --- a/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java +++ b/src/main/java/com/github/dockerjava/core/async/ResultCallbackTemplate.java @@ -8,15 +8,20 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.github.dockerjava.api.async.ResultCallback; /** - * Template implementation of {@link ResultCallback} + * Abstract template implementation of {@link ResultCallback} * * @author marcus * */ -public class ResultCallbackTemplate implements ResultCallback { +public abstract class ResultCallbackTemplate implements ResultCallback { + + private final static Logger LOGGER = LoggerFactory.getLogger(ResultCallbackTemplate.class); private final CountDownLatch finished = new CountDownLatch(1); @@ -34,6 +39,7 @@ public void onNext(T object) { @Override public void onError(Throwable throwable) { try { + LOGGER.error("Error during callback", throwable); throw new RuntimeException(throwable); } finally { try { diff --git a/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java index cc082b61f..32835b301 100644 --- a/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java @@ -2,6 +2,8 @@ import static com.google.common.base.Preconditions.checkNotNull; +import java.util.Map; + import org.apache.commons.lang.builder.ToStringBuilder; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -53,6 +55,9 @@ public class CreateContainerCmdImpl extends AbstrDockerCmd labels; + + @JsonProperty("CpusetMems") + private String cpusetMems; + + @JsonProperty("BlkioWeight") + private Integer blkioWeight; + + @JsonProperty("OomKillDisable") + private Boolean oomKillDisable; + public CreateContainerCmdImpl(CreateContainerCmd.Exec exec, String image) { super(exec); checkNotNull(image, "image was not specified"); @@ -155,6 +172,26 @@ public int getCpuShares() { return cpuShares; } + @Override + public Integer getCpuPeriod() { + return cpuPeriod; + } + + @Override + public String getCpusetMems() { + return cpusetMems; + } + + @Override + public Integer getBlkioWeight() { + return blkioWeight; + } + + @Override + public Boolean isOomKillDisable() { + return oomKillDisable; + } + @Override @JsonIgnore public Device[] getDevices() { @@ -221,6 +258,12 @@ public Link[] getLinks() { return hostConfig.getLinks(); } + @Override + @JsonIgnore + public Map getLabels() { + return labels; + } + @Override @JsonIgnore public LxcConf[] getLxcConf() { @@ -398,6 +441,30 @@ public CreateContainerCmdImpl withCpuShares(int cpuShares) { return this; } + @Override + public CreateContainerCmd withCpuPeriod(Integer cpuPeriod) { + this.cpuPeriod = cpuPeriod; + return this; + } + + @Override + public CreateContainerCmd withCpusetMems(String cpusetMems) { + this.cpusetMems = cpusetMems; + return null; + } + + @Override + public CreateContainerCmd withBlkioWeight(Integer blkioWeight) { + this.blkioWeight = blkioWeight; + return null; + } + + @Override + public CreateContainerCmd withOomKillDisable(Boolean oomKillDisable) { + this.oomKillDisable = oomKillDisable; + return null; + } + @Override public CreateContainerCmd withDevices(Device... devices) { this.hostConfig.setDevices(devices); @@ -471,6 +538,13 @@ public CreateContainerCmdImpl withImage(String image) { return this; } + @Override + public CreateContainerCmdImpl withLabels(Map labels) { + checkNotNull(labels, "labels was not specified"); + this.labels = labels; + return this; + } + @Override public CreateContainerCmdImpl withLinks(Link... links) { checkNotNull(links, "links was not specified"); diff --git a/src/main/java/com/github/dockerjava/core/command/EventsCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/EventsCmdImpl.java index d1de2e60f..50cf34ff3 100644 --- a/src/main/java/com/github/dockerjava/core/command/EventsCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/EventsCmdImpl.java @@ -1,8 +1,11 @@ package com.github.dockerjava.core.command; +import static com.google.common.base.Preconditions.*; + import com.github.dockerjava.api.async.ResultCallback; import com.github.dockerjava.api.command.EventsCmd; import com.github.dockerjava.api.model.Event; +import com.github.dockerjava.api.model.Filters; /** * Stream docker events @@ -13,6 +16,8 @@ public class EventsCmdImpl extends AbstrDockerCmd implements Ev private String until; + private Filters filters; + private ResultCallback resultCallback; public EventsCmdImpl(EventsCmd.Exec exec, ResultCallback resultCallback) { @@ -38,6 +43,13 @@ public EventsCmd withResultCallback(ResultCallback resultCallback) { return this; } + @Override + public EventsCmd withFilters(Filters filters) { + checkNotNull(filters, "filters have not been specified"); + this.filters = filters; + return this; + } + @Override public String getSince() { return since; @@ -53,9 +65,15 @@ public ResultCallback getResultCallback() { return resultCallback; } + @Override + public Filters getFilters() { + return filters; + } + @Override public String toString() { return new StringBuilder("events").append(since != null ? " --since=" + since : "") - .append(until != null ? " --until=" + until : "").toString(); + .append(until != null ? " --until=" + until : "") + .append(filters != null ? " --filters=" + filters : "").toString(); } } diff --git a/src/main/java/com/github/dockerjava/core/command/FrameReader.java b/src/main/java/com/github/dockerjava/core/command/FrameReader.java index a6db922db..bb5a5d17a 100644 --- a/src/main/java/com/github/dockerjava/core/command/FrameReader.java +++ b/src/main/java/com/github/dockerjava/core/command/FrameReader.java @@ -46,7 +46,6 @@ public Frame readFrame() throws IOException { if (rawStreamDetected) { - int read = inputStream.read(rawBuffer); return new Frame(StreamType.RAW, Arrays.copyOf(rawBuffer, read)); @@ -68,7 +67,7 @@ public Frame readFrame() throws IOException { StreamType streamType = streamType(header[0]); - if(streamType.equals(StreamType.RAW)) { + if (streamType.equals(StreamType.RAW)) { rawStreamDetected = true; return new Frame(StreamType.RAW, Arrays.copyOf(header, HEADER_SIZE)); } diff --git a/src/main/java/com/github/dockerjava/core/command/ListContainersCmdImpl.java b/src/main/java/com/github/dockerjava/core/command/ListContainersCmdImpl.java index 13bb02cfb..b957a3bd6 100644 --- a/src/main/java/com/github/dockerjava/core/command/ListContainersCmdImpl.java +++ b/src/main/java/com/github/dockerjava/core/command/ListContainersCmdImpl.java @@ -1,12 +1,12 @@ package com.github.dockerjava.core.command; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.*; import java.util.List; import com.github.dockerjava.api.command.ListContainersCmd; import com.github.dockerjava.api.model.Container; +import com.github.dockerjava.api.model.Filters; /** * List containers @@ -32,6 +32,8 @@ public class ListContainersCmdImpl extends AbstrDockerCmd callbackNotifier = new GETCallbackNotifier(new JsonStreamProcessor( diff --git a/src/main/java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java b/src/main/java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java index 5bb905b56..5feb5bdac 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java +++ b/src/main/java/com/github/dockerjava/jaxrs/ListContainersCmdExec.java @@ -1,5 +1,7 @@ package com.github.dockerjava.jaxrs; +import static com.google.common.net.UrlEscapers.*; + import java.util.List; import javax.ws.rs.client.WebTarget; @@ -32,6 +34,11 @@ protected List execute(ListContainersCmd command) { webResource = webResource.queryParam("limit", String.valueOf(command.getLimit())); } + if (command.getFilters() != null) { + webResource = webResource.queryParam("filters", + urlPathSegmentEscaper().escape(command.getFilters().toString())); + } + LOGGER.trace("GET: {}", webResource); List containers = webResource.request().accept(MediaType.APPLICATION_JSON) .get(new GenericType>() { diff --git a/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java b/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java index 6cfc7a76e..a010a87ad 100644 --- a/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java +++ b/src/main/java/com/github/dockerjava/jaxrs/async/AbstractCallbackNotifier.java @@ -48,6 +48,11 @@ public Void call() throws Exception { resultCallback.onError(e.getCause()); } return null; + } catch (Exception e) { + if (resultCallback != null) { + resultCallback.onError(e); + } + return null; } try { diff --git a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java index e96e5bcc6..7faca0370 100644 --- a/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java +++ b/src/test/java/com/github/dockerjava/client/AbstractDockerClientTest.java @@ -181,7 +181,6 @@ public static void assertContainerHasVolumes(InspectContainerResponse inspectCon assertThat(volumes, contains(expectedVolumes)); } - public static class CollectFramesCallback extends ResultCallbackTemplate { public final List frames = new ArrayList(); diff --git a/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java index ba8c1dacb..180d835b6 100644 --- a/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/AuthCmdImplTest.java @@ -41,7 +41,7 @@ public void testAuth() throws Exception { } // Disabled because of 500/InternalServerException - @Test(enabled=false) + @Test(enabled = false) public void testAuthInvalid() throws Exception { try { diff --git a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java index 1b372d245..9876e43d5 100644 --- a/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/CreateContainerCmdImplTest.java @@ -13,6 +13,8 @@ import java.lang.reflect.Method; import java.security.SecureRandom; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; import static com.github.dockerjava.api.model.Capability.MKNOD; @@ -488,4 +490,24 @@ public void createContainerWithULimits() throws DockerException { } + @Test(groups = "ignoreInCircleCi") + public void createContainerWithLabels() throws DockerException { + + Map labels = new HashMap(); + labels.put("com.github.dockerjava.null", null); + labels.put("com.github.dockerjava.boolean", "true"); + + CreateContainerResponse container = dockerClient.createContainerCmd("busybox").withCmd("sleep", "9999") + .withLabels(labels).exec(); + + LOG.info("Created container {}", container.toString()); + + assertThat(container.getId(), not(isEmptyString())); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + + // null becomes empty string + labels.put("com.github.dockerjava.null", ""); + assertThat(inspectContainerResponse.getConfig().getLabels(), is(equalTo(labels))); + } } diff --git a/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java index eb490d7e9..7da6a100f 100644 --- a/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/EventsCmdImplTest.java @@ -18,6 +18,7 @@ import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.EventsCmd; import com.github.dockerjava.api.model.Event; +import com.github.dockerjava.api.model.EventFilters; import com.github.dockerjava.client.AbstractDockerClientTest; import com.github.dockerjava.core.async.ResultCallbackTemplate; @@ -94,6 +95,25 @@ public void testEventStreaming1() throws InterruptedException, IOException { assertTrue(zeroCount, "Received only: " + eventCallback.getEvents()); } + @Test + public void testEventStreamingWithFilter() throws InterruptedException, IOException { + // Don't include other tests events + TimeUnit.SECONDS.sleep(1); + + CountDownLatch countDownLatch = new CountDownLatch(1); + EventCallbackTest eventCallback = new EventCallbackTest(countDownLatch); + + EventsCmd eventsCmd = dockerClient.eventsCmd(eventCallback).withFilters(new EventFilters().withEvent("start")); + eventsCmd.exec(); + + generateEvents(); + + boolean zeroCount = countDownLatch.await(10, TimeUnit.SECONDS); + + eventCallback.close(); + assertTrue(zeroCount, "Received only: " + eventCallback.getEvents()); + } + @Test public void testEventStreaming2() throws InterruptedException, IOException { // Don't include other tests events diff --git a/src/test/java/com/github/dockerjava/core/command/ListContainersCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/ListContainersCmdImplTest.java index b074409bd..2f052f841 100644 --- a/src/test/java/com/github/dockerjava/core/command/ListContainersCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/ListContainersCmdImplTest.java @@ -13,6 +13,7 @@ import java.lang.reflect.Method; import java.util.List; +import java.util.Map; import org.hamcrest.Matcher; import org.testng.ITestResult; @@ -26,7 +27,9 @@ import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.model.Container; +import com.github.dockerjava.api.model.Filters; import com.github.dockerjava.client.AbstractDockerClientTest; +import com.google.common.collect.ImmutableMap; @Test(groups = "integration") public class ListContainersCmdImplTest extends AbstractDockerClientTest { @@ -51,7 +54,6 @@ public void afterMethod(ITestResult result) { super.afterMethod(result); } - @Test public void testListContainers() throws DockerException { String testImage = "busybox"; @@ -96,7 +98,74 @@ public void testListContainers() throws DockerException { Container container2 = filteredContainers.get(0); assertThat(container2.getCommand(), not(isEmptyString())); - assertThat(container2.getImage(), startsWith(testImage + ":")); + assertThat(container2.getImage(), startsWith(testImage)); + } + + @Test + public void testListContainersWithLabelsFilter() throws DockerException { + + String testImage = "busybox"; + + // need to block until image is pulled completely + asString(dockerClient.pullImageCmd(testImage).exec()); + + List containers = dockerClient.listContainersCmd().withShowAll(true).exec(); + assertThat(containers, notNullValue()); + LOG.info("Container List: {}", containers); + + int size = containers.size(); + + CreateContainerResponse container1 = dockerClient.createContainerCmd(testImage).withCmd("echo").exec(); + + assertThat(container1.getId(), not(isEmptyString())); + + InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(container1.getId()).exec(); + + assertThat(inspectContainerResponse.getConfig().getImage(), is(equalTo(testImage))); + + dockerClient.startContainerCmd(container1.getId()).exec(); + + LOG.info("container id: " + container1.getId()); + + List containers2 = dockerClient.listContainersCmd().withShowAll(true).exec(); + + for (Container container : containers2) { + LOG.info("listContainer: id=" + container.getId() + " image=" + container.getImage()); + } + + assertThat(size + 1, is(equalTo(containers2.size()))); + Matcher matcher = hasItem(hasField("id", startsWith(container1.getId()))); + assertThat(containers2, matcher); + + List filteredContainers = filter(hasField("id", startsWith(container1.getId())), containers2); + assertThat(filteredContainers.size(), is(equalTo(1))); + + for (Container container : filteredContainers) { + LOG.info("filteredContainer: " + container); + } + + Container container2 = filteredContainers.get(0); + assertThat(container2.getCommand(), not(isEmptyString())); + assertThat(container2.getImage(), startsWith(testImage)); + + Map labels = ImmutableMap.of("test", "docker-java"); + + // list with filter by label + dockerClient.createContainerCmd(testImage).withCmd("echo").withLabels(labels).exec(); + filteredContainers = dockerClient.listContainersCmd().withShowAll(true) + .withFilters(new Filters().withLabels(labels)).exec(); + assertThat(filteredContainers.size(), is(equalTo(1))); + Container container3 = filteredContainers.get(0); + assertThat(container3.getCommand(), not(isEmptyString())); + assertThat(container3.getImage(), startsWith(testImage)); + + filteredContainers = dockerClient.listContainersCmd().withShowAll(true) + .withFilters(new Filters().withLabels("test")).exec(); + assertThat(filteredContainers.size(), is(equalTo(1))); + container3 = filteredContainers.get(0); + assertThat(container3.getCommand(), not(isEmptyString())); + assertThat(container3.getImage(), startsWith(testImage)); + assertEquals(container3.getLabels(), labels); } }