X Tutup
Skip to content

Commit b2d3db0

Browse files
committed
Merge pull request #82 from albers/multiple-port-bindings
Allow multiple port bindings per ExposedPort
2 parents 2fcc174 + 4571e99 commit b2d3db0

File tree

3 files changed

+71
-19
lines changed

3 files changed

+71
-19
lines changed

src/main/java/com/github/dockerjava/api/model/Ports.java

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import java.util.Map;
77
import java.util.Map.Entry;
88

9+
import org.apache.commons.lang.ArrayUtils;
910
import org.apache.commons.lang.builder.EqualsBuilder;
11+
import org.apache.commons.lang.builder.ToStringBuilder;
1012

1113
import com.fasterxml.jackson.core.JsonGenerator;
1214
import com.fasterxml.jackson.core.JsonParser;
@@ -23,8 +25,6 @@
2325
import com.github.dockerjava.api.command.InspectContainerResponse.HostConfig;
2426
import com.github.dockerjava.api.command.InspectContainerResponse.NetworkSettings;
2527

26-
import org.apache.commons.lang.builder.ToStringBuilder;
27-
2828
/**
2929
* A container for port bindings, made available as a {@link Map} via its
3030
* {@link #getBindings()} method.
@@ -36,7 +36,7 @@
3636
@JsonSerialize(using = Ports.Serializer.class)
3737
public class Ports {
3838

39-
private final Map<ExposedPort, Binding> ports = new HashMap<ExposedPort, Binding>();
39+
private final Map<ExposedPort, Binding[]> ports = new HashMap<ExposedPort, Binding[]>();
4040

4141
public Ports() { }
4242

@@ -45,7 +45,12 @@ public Ports(ExposedPort exposedPort, Binding host) {
4545
}
4646

4747
public void bind(ExposedPort exposedPort, Binding host) {
48-
ports.put(exposedPort, host);
48+
if (ports.containsKey(exposedPort)) {
49+
Binding[] bindings = ports.get(exposedPort);
50+
ports.put(exposedPort, (Binding[]) ArrayUtils.add(bindings, host));
51+
} else {
52+
ports.put(exposedPort, new Binding[]{host});
53+
}
4954
}
5055

5156
@Override
@@ -54,10 +59,10 @@ public String toString(){
5459
}
5560

5661
/**
57-
* @return the port bindings as a {@link Map} that contains one
58-
* {@link Binding} per {@link ExposedPort}.
62+
* @return the port bindings as a {@link Map} that contains one or more
63+
* {@link Binding}s per {@link ExposedPort}.
5964
*/
60-
public Map<ExposedPort, Binding> getBindings(){
65+
public Map<ExposedPort, Binding[]> getBindings(){
6166
return ports;
6267
}
6368

@@ -132,11 +137,15 @@ public Ports deserialize(JsonParser jsonParser, DeserializationContext deseriali
132137
JsonNode node = oc.readTree(jsonParser);
133138
for (Iterator<Map.Entry<String, JsonNode>> it = node.fields(); it.hasNext();) {
134139

135-
Map.Entry<String, JsonNode> field = it.next();
136-
if (!field.getValue().equals(NullNode.getInstance())) {
137-
String hostIp = field.getValue().get(0).get("HostIp").textValue();
138-
int hostPort = field.getValue().get(0).get("HostPort").asInt();
139-
out.bind(ExposedPort.parse(field.getKey()), new Binding(hostIp, hostPort));
140+
Map.Entry<String, JsonNode> portNode = it.next();
141+
JsonNode bindingsArray = portNode.getValue();
142+
for (int i = 0; i < bindingsArray.size(); i++) {
143+
JsonNode bindingNode = bindingsArray.get(i);
144+
if (!bindingNode.equals(NullNode.getInstance())) {
145+
String hostIp = bindingNode.get("HostIp").textValue();
146+
int hostPort = bindingNode.get("HostPort").asInt();
147+
out.bind(ExposedPort.parse(portNode.getKey()), new Binding(hostIp, hostPort));
148+
}
140149
}
141150
}
142151
return out;
@@ -150,13 +159,15 @@ public void serialize(Ports portBindings, JsonGenerator jsonGen,
150159
SerializerProvider serProvider) throws IOException, JsonProcessingException {
151160

152161
jsonGen.writeStartObject();
153-
for(Entry<ExposedPort, Binding> entry : portBindings.getBindings().entrySet()){
162+
for(Entry<ExposedPort, Binding[]> entry : portBindings.getBindings().entrySet()){
154163
jsonGen.writeFieldName(entry.getKey().toString());
155164
jsonGen.writeStartArray();
156-
jsonGen.writeStartObject();
157-
jsonGen.writeStringField("HostIp", entry.getValue().getHostIp());
158-
jsonGen.writeStringField("HostPort", "" + entry.getValue().getHostPort());
159-
jsonGen.writeEndObject();
165+
for (Binding binding : entry.getValue()) {
166+
jsonGen.writeStartObject();
167+
jsonGen.writeStringField("HostIp", binding.getHostIp());
168+
jsonGen.writeStringField("HostPort", "" + binding.getHostPort());
169+
jsonGen.writeEndObject();
170+
}
160171
jsonGen.writeEndArray();
161172
}
162173
jsonGen.writeEndObject();
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.github.dockerjava.api.model;
2+
3+
import static org.testng.Assert.assertEquals;
4+
5+
import java.util.Map;
6+
7+
import org.testng.annotations.Test;
8+
9+
import com.fasterxml.jackson.databind.ObjectMapper;
10+
import com.github.dockerjava.api.model.Ports.Binding;
11+
12+
public class PortsTest {
13+
private final ObjectMapper objectMapper = new ObjectMapper();
14+
private final String jsonWithDoubleBindingForOnePort =
15+
"{\"80/tcp\":[{\"HostIp\":\"10.0.0.1\",\"HostPort\":\"80\"},{\"HostIp\":\"10.0.0.2\",\"HostPort\":\"80\"}]}";
16+
17+
@Test
18+
public void deserializingPortWithMultipleBindings() throws Exception {
19+
Ports ports = objectMapper.readValue(jsonWithDoubleBindingForOnePort, Ports.class);
20+
Map<ExposedPort, Binding[]> map = ports.getBindings();
21+
assertEquals(map.size(), 1);
22+
23+
Binding[] bindings = map.get(ExposedPort.tcp(80));
24+
assertEquals(bindings.length, 2);
25+
assertEquals(bindings[0], new Binding("10.0.0.1", 80));
26+
assertEquals(bindings[1], new Binding("10.0.0.2", 80));
27+
}
28+
29+
@Test
30+
public void serializingPortWithMultipleBindings() throws Exception {
31+
Ports ports = new Ports();
32+
ports.bind(ExposedPort.tcp(80), new Binding("10.0.0.1", 80));
33+
ports.bind(ExposedPort.tcp(80), new Binding("10.0.0.2", 80));
34+
assertEquals(objectMapper.writeValueAsString(ports), jsonWithDoubleBindingForOnePort);
35+
}
36+
37+
}

src/test/java/com/github/dockerjava/core/command/StartContainerCmdImplTest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ public void startContainerWithPortBindings() throws DockerException {
163163
Ports portBindings = new Ports();
164164
portBindings.bind(tcp22, Ports.Binding(11022));
165165
portBindings.bind(tcp23, Ports.Binding(11023));
166+
portBindings.bind(tcp23, Ports.Binding(11024));
166167

167168
dockerClient.startContainerCmd(container.getId()).withPortBindings(portBindings).exec();
168169

@@ -172,12 +173,15 @@ public void startContainerWithPortBindings() throws DockerException {
172173
assertThat(Arrays.asList(inspectContainerResponse.getConfig().getExposedPorts()),
173174
contains(tcp22, tcp23));
174175

175-
assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp22),
176+
assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp22)[0],
176177
is(equalTo(Ports.Binding(11022))));
177178

178-
assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23),
179+
assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[0],
179180
is(equalTo(Ports.Binding(11023))));
180181

182+
assertThat(inspectContainerResponse.getHostConfig().getPortBindings().getBindings().get(tcp23)[1],
183+
is(equalTo(Ports.Binding(11024))));
184+
181185
}
182186

183187
@Test

0 commit comments

Comments
 (0)
X Tutup