Skip to content

Commit 2226e2f

Browse files
committed
Use port binding parser from docker-java
See docker-java/docker-java#87
1 parent a1e8511 commit 2226e2f

4 files changed

Lines changed: 69 additions & 87 deletions

File tree

src/main/java/org/jenkinsci/plugins/dockerbuildstep/cmd/StartCommand.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import com.github.dockerjava.api.DockerException;
2222
import com.github.dockerjava.api.command.InspectContainerResponse;
2323
import com.github.dockerjava.api.model.Bind;
24-
import com.github.dockerjava.api.model.Ports;
24+
import com.github.dockerjava.api.model.PortBinding;
2525

2626
/**
2727
* This command starts one or more Docker containers.
@@ -89,7 +89,7 @@ public void execute(@SuppressWarnings("rawtypes") AbstractBuild build, ConsoleLo
8989
String bindMountsRes = Resolver.buildVar(build, bindMounts);
9090

9191
List<String> ids = Arrays.asList(containerIdsRes.split(","));
92-
Ports portBindings = PortBindingParser.parse(portBindingsRes);
92+
PortBinding[] portBindings = PortBindingParser.parse2(portBindingsRes);
9393
Bind[] binds = BindParser.parse(bindMountsRes);
9494
DockerClient client = getClient();
9595

@@ -145,7 +145,7 @@ public String getDisplayName() {
145145

146146
public FormValidation doTestPortBindings(@QueryParameter String portBindings) {
147147
try {
148-
PortBindingParser.parse(portBindings);
148+
PortBindingParser.parse2(portBindings);
149149
} catch (IllegalArgumentException e) {
150150
return FormValidation.error(e.getMessage());
151151
}

src/main/java/org/jenkinsci/plugins/dockerbuildstep/util/PortBindingParser.java

Lines changed: 17 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,16 @@
22

33
import static org.apache.commons.lang.StringUtils.isEmpty;
44

5-
import java.util.Map;
6-
import java.util.regex.Matcher;
7-
import java.util.regex.Pattern;
8-
9-
import com.github.dockerjava.api.model.ExposedPort;
10-
import com.github.dockerjava.api.model.InternetProtocol;
11-
import com.github.dockerjava.api.model.Ports;
12-
import com.github.dockerjava.api.model.Ports.Binding;
5+
import com.github.dockerjava.api.model.PortBinding;
136

147
/**
158
* Parser for port mapping definitions that define how exposed container ports
169
* are mapped to host ports of the Docker server.
17-
* The result is represented as a {@link Ports} object exposing the individual
18-
* bindings via a {@link Map}.
1910
*/
2011
public class PortBindingParser {
2112

2213
/**
23-
* Parses a textual port binding definition to a {@link Ports} object that
24-
* contains the actual parsing results in a {@link Map} accessible via
25-
* {@link Ports#getBindings()}.
14+
* Parses a textual port binding definition to an array of {@link PortBinding}s.
2615
*
2716
* Assumes one port binding per line in format
2817
* <ul>
@@ -35,42 +24,25 @@ public class PortBindingParser {
3524
*
3625
* @throws IllegalArgumentException if any error occurs during parsing
3726
*/
38-
public static Ports parse(String bindings) throws IllegalArgumentException {
39-
Ports ports = new Ports();
40-
if (isEmpty(bindings))
41-
return ports;
42-
43-
String[] bindLines = bindings.split("\\r?\\n");
44-
for (String bind : bindLines) {
45-
Ports binding = parseOneBinding(bind);
46-
ports.getBindings().putAll(binding.getBindings());
27+
public static PortBinding[] parse2(String definition) throws IllegalArgumentException {
28+
if (isEmpty(definition)) return new PortBinding[0];
29+
30+
String[] lines = definition.split("\\r?\\n");
31+
PortBinding[] result = new PortBinding[lines.length];
32+
33+
for (int i = 0; i < lines.length; i++) {
34+
result[i] = parseOnePortBinding(lines[i]);
4735
}
48-
return ports;
36+
37+
return result;
4938
}
5039

51-
private static Ports parseOneBinding(String definition) throws IllegalArgumentException {
52-
Pattern pattern = Pattern.compile("((?<hIp>\\d+\\.\\d+\\.\\d+\\.\\d+):)?(?<hPort>\\d+)?[ :](?<cPort>\\d+)(/(?<protocol>tcp|udp))?");
53-
Matcher matcher = pattern.matcher(definition);
54-
if (matcher.matches()) {
55-
return new Ports(
56-
createExposedPort(matcher.group("cPort"), matcher.group("protocol")),
57-
createBinding(matcher.group("hIp"), matcher.group("hPort")));
58-
} else {
40+
private static PortBinding parseOnePortBinding(String definition) throws IllegalArgumentException {
41+
try {
42+
return PortBinding.parse(definition.replace(' ', ':'));
43+
} catch (Exception e) {
5944
throw new IllegalArgumentException("Port binding needs to be in format '[hostIP:]hostPort containerPort[/protocol]'");
6045
}
6146
}
62-
63-
private static Binding createBinding(String hIp, String hPort) {
64-
if (hPort == null) hPort = "0";
65-
return hIp == null
66-
? new Binding(Integer.parseInt(hPort))
67-
: new Binding(hIp, Integer.parseInt(hPort));
68-
}
69-
70-
private static ExposedPort createExposedPort(String cPort, String protocol) {
71-
return protocol == null
72-
? ExposedPort.tcp(Integer.parseInt(cPort))
73-
: new ExposedPort(Integer.parseInt(cPort), InternetProtocol.parse(protocol));
74-
}
75-
47+
7648
}

src/test/java/org/jenkinsci/plugins/dockerbuildstep/util/BindParserTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ public void twoBindings_DosStyle() {
9191
private void assertCreatesBinds(String input, Expected... expected) {
9292
Bind[] parsed = BindParser.parse(input);
9393
assertEquals("wrong number of Binds created", expected.length, parsed.length);
94+
9495
for (int i = 0; i < parsed.length; i++) {
9596
assertEquals("Bind #" + i, expected[i].hostPath, parsed[i].getPath());
9697
assertEquals("Bind #" + i, expected[i].containerPath, parsed[i].getVolume().getPath());

src/test/java/org/jenkinsci/plugins/dockerbuildstep/util/PortBindingParserTest.java

Lines changed: 48 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,83 +2,94 @@
22

33
import static org.junit.Assert.*;
44

5-
import java.util.Map;
6-
75
import org.junit.Test;
86

97
import com.github.dockerjava.api.model.ExposedPort;
8+
import com.github.dockerjava.api.model.PortBinding;
109
import com.github.dockerjava.api.model.Ports;
11-
import com.github.dockerjava.api.model.Ports.Binding;
1210

1311
/**
1412
* Defines legal syntax for entering port bindings.
1513
*/
1614
public class PortBindingParserTest {
17-
15+
16+
private static final ExposedPort TCP_8080 = ExposedPort.tcp(8080);
17+
1818
@Test
19-
public void completeDefinition_blank() {
20-
assertCreatesBinding("127.0.0.1:80 8080/tcp", Ports.Binding("127.0.0.1", 80), ExposedPort.tcp(8080));
19+
public void fullDefinition_blank() {
20+
assertCreatesBindings("127.0.0.1:80 8080/tcp",
21+
new PortBinding(Ports.Binding("127.0.0.1", 80), TCP_8080));
2122
}
2223

2324
@Test
2425
public void noProtocol_blank() {
25-
assertCreatesBinding("127.0.0.1:80 8080", Ports.Binding("127.0.0.1", 80), ExposedPort.tcp(8080));
26+
assertCreatesBindings("127.0.0.1:80 8080",
27+
new PortBinding(Ports.Binding("127.0.0.1", 80), TCP_8080));
2628
}
2729

2830
@Test
29-
public void noHost_blank() {
30-
assertCreatesBinding("80 8080/tcp", Ports.Binding(80), ExposedPort.tcp(8080));
31+
public void noHostIp_blank() {
32+
assertCreatesBindings("80 8080/tcp",
33+
new PortBinding(Ports.Binding(80), TCP_8080));
3134
}
3235

3336
@Test
34-
public void minimalDefiniton_blank() {
35-
assertCreatesBinding("80 8080", Ports.Binding(80), ExposedPort.tcp(8080));
37+
public void portsOnly_blank() {
38+
assertCreatesBindings("80 8080",
39+
new PortBinding(Ports.Binding(80), TCP_8080));
3640
}
3741

3842
@Test
39-
public void completeDefinition_colon() {
40-
assertCreatesBinding("127.0.0.1:80:8080/tcp", Ports.Binding("127.0.0.1", 80), ExposedPort.tcp(8080));
43+
public void fullDefinition_colon() {
44+
assertCreatesBindings("127.0.0.1:80:8080/tcp",
45+
new PortBinding(Ports.Binding("127.0.0.1", 80), TCP_8080));
4146
}
4247

4348
@Test
4449
public void noProtocol_colon() {
45-
assertCreatesBinding("127.0.0.1:80:8080", Ports.Binding("127.0.0.1", 80), ExposedPort.tcp(8080));
50+
assertCreatesBindings("127.0.0.1:80:8080",
51+
new PortBinding(Ports.Binding("127.0.0.1", 80), TCP_8080));
4652
}
4753

4854
@Test
49-
public void noHost_colon() {
50-
assertCreatesBinding("80:8080/tcp", Ports.Binding(80), ExposedPort.tcp(8080));
55+
public void noHostIp_colon() {
56+
assertCreatesBindings("80:8080/tcp",
57+
new PortBinding(Ports.Binding(80), TCP_8080));
5158
}
5259

5360
@Test
54-
public void minimalDefiniton_colon() {
55-
assertCreatesBinding("80:8080", Ports.Binding(80), ExposedPort.tcp(8080));
61+
public void portsOnly_colon() {
62+
assertCreatesBindings("80:8080",
63+
new PortBinding(Ports.Binding(80), TCP_8080));
5664
}
5765

5866
@Test(expected = IllegalArgumentException.class)
5967
public void syntaxError() {
60-
PortBindingParser.parse("nonsense");
68+
PortBindingParser.parse2("nonsense");
6169
}
6270

6371
@Test
6472
public void parseEmptyString() {
65-
Map<ExposedPort, Binding[]> bindings = PortBindingParser.parse("").getBindings();
66-
assertTrue("no binding", bindings.isEmpty());
73+
PortBinding[] bindings = PortBindingParser.parse2("");
74+
assertEquals(0, bindings.length);
6775
}
6876

6977
@Test
7078
public void exposedUdpPort() {
71-
assertCreatesBinding("80 8080/udp", Ports.Binding(80), ExposedPort.udp(8080));
79+
assertCreatesBindings("80 8080/udp",
80+
new PortBinding(Ports.Binding(80), ExposedPort.udp(8080)));
7281
}
7382

7483
@Test
75-
public void dynamicPort() {
76-
assertCreatesBinding("127.0.0.1: 8080", Ports.Binding("127.0.0.1", 0), ExposedPort.tcp(8080));
84+
public void dynamicHostPort_blank() {
85+
assertCreatesBindings("127.0.0.1: 8080",
86+
new PortBinding(Ports.Binding("127.0.0.1", null), TCP_8080));
7787
}
7888

7989
@Test
80-
public void dynamicPort_colon() {
81-
assertCreatesBinding("127.0.0.1::8080", Ports.Binding("127.0.0.1", 0), ExposedPort.tcp(8080));
90+
public void dynamicHostPort_colon() {
91+
assertCreatesBindings("127.0.0.1::8080",
92+
new PortBinding(Ports.Binding("127.0.0.1", null), TCP_8080));
8293
}
8394

8495
@Test
@@ -92,21 +103,19 @@ public void twoBindings_DosStyle() {
92103
}
93104

94105
private void twoBindings(String input) {
95-
Ports ports = PortBindingParser.parse(input);
96-
assertEquals(2, ports.getBindings().size());
97-
assertContainsBinding(ports, ExposedPort.tcp(8080), Ports.Binding(80));
98-
assertContainsBinding(ports, ExposedPort.tcp(8081), Ports.Binding(81));
106+
assertCreatesBindings(input,
107+
new PortBinding(Ports.Binding(80), ExposedPort.tcp(8080)),
108+
new PortBinding(Ports.Binding(81), ExposedPort.tcp(8081)));
99109
}
100110

101-
private static void assertCreatesBinding(String input, Binding binding, ExposedPort exposedPort) {
102-
Ports ports = PortBindingParser.parse(input);
103-
assertContainsBinding(ports, exposedPort, binding);
104-
}
111+
private static void assertCreatesBindings(String input, PortBinding... expected) {
112+
PortBinding[] parsed = PortBindingParser.parse2(input);
113+
assertEquals("wrong number of PortBindings created", expected.length, parsed.length);
105114

106-
private static void assertContainsBinding(Ports ports, ExposedPort exposedPort, Binding expectedBinding) {
107-
Binding[] bindings = ports.getBindings().get(exposedPort);
108-
assertNotNull("no binding was created for " + exposedPort, bindings);
109-
assertEquals(expectedBinding, bindings[0]);
115+
for (int i = 0; i < parsed.length; i++) {
116+
assertEquals("PortBinding #" + i, expected[i].getBinding(), parsed[i].getBinding());
117+
assertEquals("PortBinding #" + i, expected[i].getExposedPort(), parsed[i].getExposedPort());
118+
}
110119
}
111-
120+
112121
}

0 commit comments

Comments
 (0)