From d1f31cdfb0716c976eff6051f00fc8896cfc75c8 Mon Sep 17 00:00:00 2001 From: Harald Albers Date: Mon, 20 Oct 2014 20:49:49 +0200 Subject: [PATCH 1/2] Document current deserialization of Ports with a test --- .../dockerjava/api/model/PortsTest.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/test/java/com/github/dockerjava/api/model/PortsTest.java diff --git a/src/test/java/com/github/dockerjava/api/model/PortsTest.java b/src/test/java/com/github/dockerjava/api/model/PortsTest.java new file mode 100644 index 000000000..9cd5ef726 --- /dev/null +++ b/src/test/java/com/github/dockerjava/api/model/PortsTest.java @@ -0,0 +1,33 @@ +package com.github.dockerjava.api.model; + +import static org.testng.Assert.assertEquals; + +import java.util.Map; + +import org.testng.annotations.Test; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.dockerjava.api.model.Ports.Binding; + +public class PortsTest { + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void deserializingPortWithMultipleBindingsReturnsFirstBinding() throws Exception { + String json = "{\"80/tcp\":[{\"HostIp\":\"10.0.0.1\",\"HostPort\":\"80\"},{\"HostIp\":\"10.0.0.2\",\"HostPort\":\"80\"}]}"; + Ports ports = objectMapper.readValue(json, Ports.class); + Map bindings = ports.getBindings(); + assertEquals(bindings.size(), 1); + + Binding binding = bindings.get(ExposedPort.tcp(80)); + assertEquals(binding, new Binding("10.0.0.1", 80)); + } + + @Test + public void serializePort() throws Exception { + Ports ports = new Ports(ExposedPort.tcp(80), new Binding("10.0.0.1", 80)); + String expectedJson = "{\"80/tcp\":[{\"HostIp\":\"10.0.0.1\",\"HostPort\":\"80\"}]}"; + assertEquals(objectMapper.writeValueAsString(ports), expectedJson); + } + +} From 4571e99c6d9ceb1401d1ed7927723b8f840fd0e4 Mon Sep 17 00:00:00 2001 From: Harald Albers Date: Mon, 20 Oct 2014 21:55:37 +0200 Subject: [PATCH 2/2] Allow multiple port bindings per exposed port --- .../github/dockerjava/api/model/Ports.java | 45 +++++++----- .../dockerjava/api/model/PortsTest.java | 70 ++++++++++--------- .../command/StartContainerCmdImplTest.java | 8 ++- 3 files changed, 71 insertions(+), 52 deletions(-) diff --git a/src/main/java/com/github/dockerjava/api/model/Ports.java b/src/main/java/com/github/dockerjava/api/model/Ports.java index fe7904689..a14b31036 100644 --- a/src/main/java/com/github/dockerjava/api/model/Ports.java +++ b/src/main/java/com/github/dockerjava/api/model/Ports.java @@ -6,7 +6,9 @@ import java.util.Map; import java.util.Map.Entry; +import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; @@ -23,8 +25,6 @@ import com.github.dockerjava.api.command.InspectContainerResponse.HostConfig; import com.github.dockerjava.api.command.InspectContainerResponse.NetworkSettings; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * A container for port bindings, made available as a {@link Map} via its * {@link #getBindings()} method. @@ -36,7 +36,7 @@ @JsonSerialize(using = Ports.Serializer.class) public class Ports { - private final Map ports = new HashMap(); + private final Map ports = new HashMap(); public Ports() { } @@ -45,7 +45,12 @@ public Ports(ExposedPort exposedPort, Binding host) { } public void bind(ExposedPort exposedPort, Binding host) { - ports.put(exposedPort, host); + if (ports.containsKey(exposedPort)) { + Binding[] bindings = ports.get(exposedPort); + ports.put(exposedPort, (Binding[]) ArrayUtils.add(bindings, host)); + } else { + ports.put(exposedPort, new Binding[]{host}); + } } @Override @@ -54,10 +59,10 @@ public String toString(){ } /** - * @return the port bindings as a {@link Map} that contains one - * {@link Binding} per {@link ExposedPort}. + * @return the port bindings as a {@link Map} that contains one or more + * {@link Binding}s per {@link ExposedPort}. */ - public Map getBindings(){ + public Map getBindings(){ return ports; } @@ -132,11 +137,15 @@ public Ports deserialize(JsonParser jsonParser, DeserializationContext deseriali JsonNode node = oc.readTree(jsonParser); for (Iterator> it = node.fields(); it.hasNext();) { - Map.Entry field = it.next(); - if (!field.getValue().equals(NullNode.getInstance())) { - String hostIp = field.getValue().get(0).get("HostIp").textValue(); - int hostPort = field.getValue().get(0).get("HostPort").asInt(); - out.bind(ExposedPort.parse(field.getKey()), new Binding(hostIp, hostPort)); + Map.Entry portNode = it.next(); + JsonNode bindingsArray = portNode.getValue(); + for (int i = 0; i < bindingsArray.size(); i++) { + JsonNode bindingNode = bindingsArray.get(i); + if (!bindingNode.equals(NullNode.getInstance())) { + String hostIp = bindingNode.get("HostIp").textValue(); + int hostPort = bindingNode.get("HostPort").asInt(); + out.bind(ExposedPort.parse(portNode.getKey()), new Binding(hostIp, hostPort)); + } } } return out; @@ -150,13 +159,15 @@ public void serialize(Ports portBindings, JsonGenerator jsonGen, SerializerProvider serProvider) throws IOException, JsonProcessingException { jsonGen.writeStartObject(); - for(Entry entry : portBindings.getBindings().entrySet()){ + for(Entry entry : portBindings.getBindings().entrySet()){ jsonGen.writeFieldName(entry.getKey().toString()); jsonGen.writeStartArray(); - jsonGen.writeStartObject(); - jsonGen.writeStringField("HostIp", entry.getValue().getHostIp()); - jsonGen.writeStringField("HostPort", "" + entry.getValue().getHostPort()); - jsonGen.writeEndObject(); + for (Binding binding : entry.getValue()) { + jsonGen.writeStartObject(); + jsonGen.writeStringField("HostIp", binding.getHostIp()); + jsonGen.writeStringField("HostPort", "" + binding.getHostPort()); + jsonGen.writeEndObject(); + } jsonGen.writeEndArray(); } jsonGen.writeEndObject(); diff --git a/src/test/java/com/github/dockerjava/api/model/PortsTest.java b/src/test/java/com/github/dockerjava/api/model/PortsTest.java index 9cd5ef726..6a6c5e44e 100644 --- a/src/test/java/com/github/dockerjava/api/model/PortsTest.java +++ b/src/test/java/com/github/dockerjava/api/model/PortsTest.java @@ -1,33 +1,37 @@ -package com.github.dockerjava.api.model; - -import static org.testng.Assert.assertEquals; - -import java.util.Map; - -import org.testng.annotations.Test; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.dockerjava.api.model.Ports.Binding; - -public class PortsTest { - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - public void deserializingPortWithMultipleBindingsReturnsFirstBinding() throws Exception { - String json = "{\"80/tcp\":[{\"HostIp\":\"10.0.0.1\",\"HostPort\":\"80\"},{\"HostIp\":\"10.0.0.2\",\"HostPort\":\"80\"}]}"; - Ports ports = objectMapper.readValue(json, Ports.class); - Map bindings = ports.getBindings(); - assertEquals(bindings.size(), 1); - - Binding binding = bindings.get(ExposedPort.tcp(80)); - assertEquals(binding, new Binding("10.0.0.1", 80)); - } - - @Test - public void serializePort() throws Exception { - Ports ports = new Ports(ExposedPort.tcp(80), new Binding("10.0.0.1", 80)); - String expectedJson = "{\"80/tcp\":[{\"HostIp\":\"10.0.0.1\",\"HostPort\":\"80\"}]}"; - assertEquals(objectMapper.writeValueAsString(ports), expectedJson); - } - -} +package com.github.dockerjava.api.model; + +import static org.testng.Assert.assertEquals; + +import java.util.Map; + +import org.testng.annotations.Test; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.dockerjava.api.model.Ports.Binding; + +public class PortsTest { + private final ObjectMapper objectMapper = new ObjectMapper(); + private final String jsonWithDoubleBindingForOnePort = + "{\"80/tcp\":[{\"HostIp\":\"10.0.0.1\",\"HostPort\":\"80\"},{\"HostIp\":\"10.0.0.2\",\"HostPort\":\"80\"}]}"; + + @Test + public void deserializingPortWithMultipleBindings() throws Exception { + Ports ports = objectMapper.readValue(jsonWithDoubleBindingForOnePort, Ports.class); + Map map = ports.getBindings(); + assertEquals(map.size(), 1); + + Binding[] bindings = map.get(ExposedPort.tcp(80)); + assertEquals(bindings.length, 2); + assertEquals(bindings[0], new Binding("10.0.0.1", 80)); + assertEquals(bindings[1], new Binding("10.0.0.2", 80)); + } + + @Test + public void serializingPortWithMultipleBindings() throws Exception { + Ports ports = new Ports(); + ports.bind(ExposedPort.tcp(80), new Binding("10.0.0.1", 80)); + ports.bind(ExposedPort.tcp(80), new Binding("10.0.0.2", 80)); + assertEquals(objectMapper.writeValueAsString(ports), jsonWithDoubleBindingForOnePort); + } + +} diff --git a/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java b/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java index e5ceff826..469259eeb 100644 --- a/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java +++ b/src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java @@ -163,6 +163,7 @@ public void startContainerWithPortBindings() throws DockerException { Ports portBindings = new Ports(); portBindings.bind(tcp22, Ports.Binding(11022)); portBindings.bind(tcp23, Ports.Binding(11023)); + portBindings.bind(tcp23, Ports.Binding(11024)); dockerClient.startContainerCmd(container.getId()).withPortBindings(portBindings).exec(); @@ -172,12 +173,15 @@ public void startContainerWithPortBindings() throws DockerException { assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()), contains(tcp22, tcp23)); - assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp22), + assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp22)[0], is(equalTo(Ports.Binding(11022)))); - assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23), + assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[0], is(equalTo(Ports.Binding(11023)))); + assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[1], + is(equalTo(Ports.Binding(11024)))); + } @Test