Support binding of port ranges by marcuslinke · Pull Request #575 · docker-java/docker-java
@@ -1,16 +1,5 @@
package com.github.dockerjava.api.model;
import static org.apache.commons.lang.StringUtils.isEmpty;
import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.builder.EqualsBuilder;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; Expand All @@ -23,6 +12,16 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.node.NullNode; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.builder.EqualsBuilder;
import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry;
import static org.apache.commons.lang.StringUtils.isEmpty;
/** * A container for port bindings, made available as a {@link Map} via its {@link #getBindings()} method. Expand Down Expand Up @@ -108,69 +107,85 @@ public Map<ExposedPort, Binding[]> getBindings() { // return bindings.toArray(new PortBinding[bindings.size()]); // }
/** * Creates a {@link Binding} for the given IP address and port number. */ public static Binding binding(String hostIp, Integer hostPort) { return new Binding(hostIp, hostPort); }
/** * Creates a {@link Binding} for the given port number, leaving the IP address undefined. */ public static Binding binding(Integer hostPort) { return new Binding(hostPort); }
/** * A {@link Binding} represents a socket on the Docker host that is used in a {@link PortBinding}. It is characterized by an * {@link #getHostIp() IP address} and a {@link #getHostPort() port number}. Both properties may be <code>null</code> in order to let * Docker assign them dynamically/using defaults. * {@link #getHostIp() IP address} and a {@link #getHostPortSpec() port spec}. Both properties may be <code>null</code> in order to * let Docker assign them dynamically/using defaults. * * @see Ports#bind(ExposedPort, Binding) * @see ExposedPort */ public static class Binding {
private final String hostIp;
private final Integer hostPort;
/** * Creates a {@link Binding} for the given {@link #getHostIp() IP address} and {@link #getHostPort() port number}. * Creates a {@link Binding} for the given {@link #getHostPortSpec() port spec}, leaving the {@link #getHostIp() IP address} * undefined. * * @see Ports#bind(ExposedPort, Binding) * @see ExposedPort */ public Binding(String hostIp, Integer hostPort) { this.hostIp = isEmpty(hostIp) ? null : hostIp; this.hostPort = hostPort; public static Binding bindPortSpec(String portSpec) { return new Binding(null, portSpec); }
/** * Creates a {@link Binding} for the given {@link #getHostPort() port number}, leaving the {@link #getHostIp() IP address} * Creates a {@link Binding} for the given {@link #getHostIp() IP address}, leaving the {@link #getHostPortSpec() port spec} * undefined. */ public static Binding bindIp(String hostIp) { return new Binding(hostIp, null); }
/** * Creates a {@link Binding} for the given {@link #getHostIp() IP address} and port number. */ public static Binding bindIpAndPort(String hostIp, int port) { return new Binding(hostIp, "" + port); }
/** * Creates a {@link Binding} for the given {@link #getHostIp() IP address} and port range. */ public static Binding bindIpAndPortRange(String hostIp, int lowPort, int highPort) { return new Binding(hostIp, lowPort + "-" + highPort); }
/** * Creates a {@link Binding} for the given port range, leaving the {@link #getHostIp() IP address} * undefined. * * @see Ports#bind(ExposedPort, Binding) * @see ExposedPort */ public Binding(Integer hostPort) { this(null, hostPort); public static Binding bindPortRange(int lowPort, int highPort) { return bindIpAndPortRange(null, lowPort, highPort); }
/** * Creates a {@link Binding} for the given {@link #getHostIp() IP address}, leaving the {@link #getHostPort() port number} * Creates a {@link Binding} for the given port leaving the {@link #getHostIp() IP address} * undefined. */ public Binding(String hostIp) { this(hostIp, null); public static Binding bindPort(int port) { return bindIpAndPort(null, port); }
/** * Creates a {@link Binding} with both {@link #getHostIp() IP address} and {@link #getHostPort() port number} undefined. * Creates an empty {@link Binding}. */ public Binding() { this(null, null); public static Binding empty() { return new Binding(null, null); }
private final String hostIp;
private final String hostPortSpec;
/** * Creates a {@link Binding} for the given {@link #getHostIp() host IP address} and {@link #getHostPortSpec() host port spec}. * * @see Ports#bind(ExposedPort, Binding) * @see ExposedPort */ public Binding(String hostIp, String hostPortSpec) { this.hostIp = isEmpty(hostIp) ? null : hostIp; this.hostPortSpec = hostPortSpec; }
/** Expand All @@ -182,16 +197,17 @@ public String getHostIp() { }
/** * @return the port number on the Docker host. May be <code>null</code>, in which case Docker will dynamically assign a port. * @return the port spec for the binding on the Docker host. May reference a single port ("1234"), a port range ("1234-2345") or * <code>null</code>, in which case Docker will dynamically assign a port. */ public Integer getHostPort() { return hostPort; public String getHostPortSpec() { return hostPortSpec; }
/** * Parses a textual host and port specification (as used by the Docker CLI) to a {@link Binding}. * <p> * Legal syntax: <code>IP|IP:port|port</code> * Legal syntax: <code>IP|IP:portSpec|portSpec</code> where <code>portSpec</code> is either a single port or a port range * * @param serialized * serialized the specification, e.g. <code>127.0.0.1:80</code> Expand All @@ -202,16 +218,16 @@ public Integer getHostPort() { public static Binding parse(String serialized) throws IllegalArgumentException { try { if (serialized.isEmpty()) { return new Binding(); return Binding.empty(); }
String[] parts = serialized.split(":"); switch (parts.length) { case 2: { return new Binding(parts[0], Integer.valueOf(parts[1])); return new Binding(parts[0], parts[1]); } case 1: { return parts[0].contains(".") ? new Binding(parts[0]) : new Binding(Integer.valueOf(parts[0])); return parts[0].contains(".") ? Binding.bindIp(parts[0]) : Binding.bindPortSpec(parts[0]); } default: { throw new IllegalArgumentException(); Expand All @@ -231,19 +247,19 @@ public static Binding parse(String serialized) throws IllegalArgumentException { @Override public String toString() { if (isEmpty(hostIp)) { return Integer.toString(hostPort); } else if (hostPort == null) { return hostPortSpec; } else if (hostPortSpec == null) { return hostIp; } else { return hostIp + ":" + hostPort; return hostIp + ":" + hostPortSpec; } }
@Override public boolean equals(Object obj) { if (obj instanceof Binding) { Binding other = (Binding) obj; return new EqualsBuilder().append(hostIp, other.getHostIp()).append(hostPort, other.getHostPort()) return new EqualsBuilder().append(hostIp, other.getHostIp()).append(hostPortSpec, other.getHostPortSpec()) .isEquals(); } else { return super.equals(obj); Expand All @@ -270,7 +286,7 @@ public Ports deserialize(JsonParser jsonParser, DeserializationContext deseriali JsonNode bindingNode = bindingsArray.get(i); if (!bindingNode.equals(NullNode.getInstance())) { String hostIp = bindingNode.get("HostIp").textValue(); int hostPort = bindingNode.get("HostPort").asInt(); String hostPort = bindingNode.get("HostPort").textValue(); out.bind(ExposedPort.parse(portNode.getKey()), new Binding(hostIp, hostPort)); } } Expand All @@ -294,8 +310,7 @@ public void serialize(Ports portBindings, JsonGenerator jsonGen, SerializerProvi for (Binding binding : entry.getValue()) { jsonGen.writeStartObject(); jsonGen.writeStringField("HostIp", binding.getHostIp() == null ? "" : binding.getHostIp()); jsonGen.writeStringField("HostPort", binding.getHostPort() == null ? "" : binding.getHostPort() .toString()); jsonGen.writeStringField("HostPort", binding.getHostPortSpec() == null ? "" : binding.getHostPortSpec()); jsonGen.writeEndObject(); } jsonGen.writeEndArray(); Expand Down
import static org.apache.commons.lang.StringUtils.isEmpty;
import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.builder.EqualsBuilder;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; Expand All @@ -23,6 +12,16 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.node.NullNode; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.builder.EqualsBuilder;
import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry;
import static org.apache.commons.lang.StringUtils.isEmpty;
/** * A container for port bindings, made available as a {@link Map} via its {@link #getBindings()} method. Expand Down Expand Up @@ -108,69 +107,85 @@ public Map<ExposedPort, Binding[]> getBindings() { // return bindings.toArray(new PortBinding[bindings.size()]); // }
/** * Creates a {@link Binding} for the given IP address and port number. */ public static Binding binding(String hostIp, Integer hostPort) { return new Binding(hostIp, hostPort); }
/** * Creates a {@link Binding} for the given port number, leaving the IP address undefined. */ public static Binding binding(Integer hostPort) { return new Binding(hostPort); }
/** * A {@link Binding} represents a socket on the Docker host that is used in a {@link PortBinding}. It is characterized by an * {@link #getHostIp() IP address} and a {@link #getHostPort() port number}. Both properties may be <code>null</code> in order to let * Docker assign them dynamically/using defaults. * {@link #getHostIp() IP address} and a {@link #getHostPortSpec() port spec}. Both properties may be <code>null</code> in order to * let Docker assign them dynamically/using defaults. * * @see Ports#bind(ExposedPort, Binding) * @see ExposedPort */ public static class Binding {
private final String hostIp;
private final Integer hostPort;
/** * Creates a {@link Binding} for the given {@link #getHostIp() IP address} and {@link #getHostPort() port number}. * Creates a {@link Binding} for the given {@link #getHostPortSpec() port spec}, leaving the {@link #getHostIp() IP address} * undefined. * * @see Ports#bind(ExposedPort, Binding) * @see ExposedPort */ public Binding(String hostIp, Integer hostPort) { this.hostIp = isEmpty(hostIp) ? null : hostIp; this.hostPort = hostPort; public static Binding bindPortSpec(String portSpec) { return new Binding(null, portSpec); }
/** * Creates a {@link Binding} for the given {@link #getHostPort() port number}, leaving the {@link #getHostIp() IP address} * Creates a {@link Binding} for the given {@link #getHostIp() IP address}, leaving the {@link #getHostPortSpec() port spec} * undefined. */ public static Binding bindIp(String hostIp) { return new Binding(hostIp, null); }
/** * Creates a {@link Binding} for the given {@link #getHostIp() IP address} and port number. */ public static Binding bindIpAndPort(String hostIp, int port) { return new Binding(hostIp, "" + port); }
/** * Creates a {@link Binding} for the given {@link #getHostIp() IP address} and port range. */ public static Binding bindIpAndPortRange(String hostIp, int lowPort, int highPort) { return new Binding(hostIp, lowPort + "-" + highPort); }
/** * Creates a {@link Binding} for the given port range, leaving the {@link #getHostIp() IP address} * undefined. * * @see Ports#bind(ExposedPort, Binding) * @see ExposedPort */ public Binding(Integer hostPort) { this(null, hostPort); public static Binding bindPortRange(int lowPort, int highPort) { return bindIpAndPortRange(null, lowPort, highPort); }
/** * Creates a {@link Binding} for the given {@link #getHostIp() IP address}, leaving the {@link #getHostPort() port number} * Creates a {@link Binding} for the given port leaving the {@link #getHostIp() IP address} * undefined. */ public Binding(String hostIp) { this(hostIp, null); public static Binding bindPort(int port) { return bindIpAndPort(null, port); }
/** * Creates a {@link Binding} with both {@link #getHostIp() IP address} and {@link #getHostPort() port number} undefined. * Creates an empty {@link Binding}. */ public Binding() { this(null, null); public static Binding empty() { return new Binding(null, null); }
private final String hostIp;
private final String hostPortSpec;
/** * Creates a {@link Binding} for the given {@link #getHostIp() host IP address} and {@link #getHostPortSpec() host port spec}. * * @see Ports#bind(ExposedPort, Binding) * @see ExposedPort */ public Binding(String hostIp, String hostPortSpec) { this.hostIp = isEmpty(hostIp) ? null : hostIp; this.hostPortSpec = hostPortSpec; }
/** Expand All @@ -182,16 +197,17 @@ public String getHostIp() { }
/** * @return the port number on the Docker host. May be <code>null</code>, in which case Docker will dynamically assign a port. * @return the port spec for the binding on the Docker host. May reference a single port ("1234"), a port range ("1234-2345") or * <code>null</code>, in which case Docker will dynamically assign a port. */ public Integer getHostPort() { return hostPort; public String getHostPortSpec() { return hostPortSpec; }
/** * Parses a textual host and port specification (as used by the Docker CLI) to a {@link Binding}. * <p> * Legal syntax: <code>IP|IP:port|port</code> * Legal syntax: <code>IP|IP:portSpec|portSpec</code> where <code>portSpec</code> is either a single port or a port range * * @param serialized * serialized the specification, e.g. <code>127.0.0.1:80</code> Expand All @@ -202,16 +218,16 @@ public Integer getHostPort() { public static Binding parse(String serialized) throws IllegalArgumentException { try { if (serialized.isEmpty()) { return new Binding(); return Binding.empty(); }
String[] parts = serialized.split(":"); switch (parts.length) { case 2: { return new Binding(parts[0], Integer.valueOf(parts[1])); return new Binding(parts[0], parts[1]); } case 1: { return parts[0].contains(".") ? new Binding(parts[0]) : new Binding(Integer.valueOf(parts[0])); return parts[0].contains(".") ? Binding.bindIp(parts[0]) : Binding.bindPortSpec(parts[0]); } default: { throw new IllegalArgumentException(); Expand All @@ -231,19 +247,19 @@ public static Binding parse(String serialized) throws IllegalArgumentException { @Override public String toString() { if (isEmpty(hostIp)) { return Integer.toString(hostPort); } else if (hostPort == null) { return hostPortSpec; } else if (hostPortSpec == null) { return hostIp; } else { return hostIp + ":" + hostPort; return hostIp + ":" + hostPortSpec; } }
@Override public boolean equals(Object obj) { if (obj instanceof Binding) { Binding other = (Binding) obj; return new EqualsBuilder().append(hostIp, other.getHostIp()).append(hostPort, other.getHostPort()) return new EqualsBuilder().append(hostIp, other.getHostIp()).append(hostPortSpec, other.getHostPortSpec()) .isEquals(); } else { return super.equals(obj); Expand All @@ -270,7 +286,7 @@ public Ports deserialize(JsonParser jsonParser, DeserializationContext deseriali JsonNode bindingNode = bindingsArray.get(i); if (!bindingNode.equals(NullNode.getInstance())) { String hostIp = bindingNode.get("HostIp").textValue(); int hostPort = bindingNode.get("HostPort").asInt(); String hostPort = bindingNode.get("HostPort").textValue(); out.bind(ExposedPort.parse(portNode.getKey()), new Binding(hostIp, hostPort)); } } Expand All @@ -294,8 +310,7 @@ public void serialize(Ports portBindings, JsonGenerator jsonGen, SerializerProvi for (Binding binding : entry.getValue()) { jsonGen.writeStartObject(); jsonGen.writeStringField("HostIp", binding.getHostIp() == null ? "" : binding.getHostIp()); jsonGen.writeStringField("HostPort", binding.getHostPort() == null ? "" : binding.getHostPort() .toString()); jsonGen.writeStringField("HostPort", binding.getHostPortSpec() == null ? "" : binding.getHostPortSpec()); jsonGen.writeEndObject(); } jsonGen.writeEndArray(); Expand Down