Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 47 additions & 6 deletions src/main/java/com/github/dockerjava/api/model/ExposedPort.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,38 @@
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.node.NullNode;

import com.github.dockerjava.api.model.Ports.Binding;

/**
* Represents a container port that Docker exposes to external clients.
* The port is defined by its {@link #getPort() port number} and a
* {@link #getScheme() scheme}, e.g. <code>tcp</code>.
* It can be published by Docker by {@link Ports#bind(ExposedPort, Binding) binding}
* it to a host port, represented by a {@link Binding}.
*/
@JsonDeserialize(using = ExposedPort.Deserializer.class)
@JsonSerialize(using = ExposedPort.Serializer.class)
public class ExposedPort {

private String scheme;
private final String scheme;

private int port;
private final int port;

/**
* Creates an {@link ExposedPort} for the given parameters.
*
* @param scheme the {@link #getScheme() scheme}, <code>tcp</code> or
* <code>udp</code>
* @param port the {@link #getPort() port number}
*/
public ExposedPort(String scheme, int port) {
this.scheme = scheme;
this.port = port;
}

/**
* @return the scheme (IP protocol), <code>tcp</code> or <code>udp</code>
*/
public String getScheme() {
return scheme;
}
Expand All @@ -40,27 +58,50 @@ public int getPort() {
return port;
}

/**
* Creates an {@link ExposedPort} for the TCP scheme.
* This is a shortcut for <code>new ExposedPort("tcp", port)</code>
*/
public static ExposedPort tcp(int port) {
return new ExposedPort("tcp", port);
}

/**
* Creates an {@link ExposedPort} for the UDP scheme.
* This is a shortcut for <code>new ExposedPort("udp", port)</code>
*/
public static ExposedPort udp(int port) {
return new ExposedPort("udp", port);
}

public static ExposedPort parse(String serialized) {
/**
* Parses a textual port specification (as used by the Docker CLI) to an
* {@link ExposedPort}.
*
* @param serialized the specification, e.g. <code>80/tcp</code>
* @return an {@link ExposedPort} matching the specification
* @throws IllegalArgumentException if the specification cannot be parsed
*/
public static ExposedPort parse(String serialized) throws IllegalArgumentException {
try {
String[] parts = serialized.split("/");
ExposedPort out = new ExposedPort(parts[1], Integer.valueOf(parts[0]));
return out;
} catch (Exception e) {
throw new RuntimeException("Error parsing ExposedPort '" + serialized + "'");
throw new IllegalArgumentException("Error parsing ExposedPort '" + serialized + "'");
}
}

/**
* Returns a string representation of this {@link ExposedPort} suitable
* for inclusion in a JSON message.
* The format is <code>port/scheme</code>, like the argument in {@link #parse(String)}.
*
* @return a string representation of this {@link ExposedPort}
*/
@Override
public String toString() {
return getPort() + "/" + getScheme();
return port + "/" + scheme;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ public void serialize(ExposedPorts exposedPorts, JsonGenerator jsonGen,

jsonGen.writeStartObject();
for (ExposedPort exposedPort : exposedPorts.getExposedPorts()) {
jsonGen.writeFieldName(exposedPort.getPort() + "/"
+ exposedPort.getScheme());
jsonGen.writeFieldName(exposedPort.toString());
jsonGen.writeStartObject();
jsonGen.writeEndObject();
}
Expand Down
30 changes: 28 additions & 2 deletions src/main/java/com/github/dockerjava/api/model/Ports.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,18 @@
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.node.NullNode;
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.
*
* @see HostConfig#getPortBindings()
* @see NetworkSettings#getPorts()
*/
@JsonDeserialize(using = Ports.Deserializer.class)
@JsonSerialize(using = Ports.Serializer.class)
public class Ports {
Expand All @@ -43,6 +53,10 @@ public String toString(){
return ports.toString();
}

/**
* @return the port bindings as a {@link Map} that contains one
* {@link Binding} per {@link ExposedPort}.
*/
public Map<ExposedPort, Binding> getBindings(){
return ports;
}
Expand All @@ -55,13 +69,25 @@ public static Binding Binding(int hostPort) {
}


/**
* The host part of a port binding.
* In a port binding a container port, expressed as an {@link ExposedPort},
* is published as a port of the Docker host.
*
* @see ExposedPort
*/
public static class Binding {


private final String hostIp;

private final int hostPort;

/**
* Creates the host part of a port binding.
*
* @see Ports#bind(ExposedPort, Binding)
* @see ExposedPort
*/
public Binding(String hostIp, int hostPort) {
this.hostIp = hostIp;
this.hostPort = hostPort;
Expand Down Expand Up @@ -125,7 +151,7 @@ public void serialize(Ports portBindings, JsonGenerator jsonGen,

jsonGen.writeStartObject();
for(Entry<ExposedPort, Binding> entry : portBindings.getBindings().entrySet()){
jsonGen.writeFieldName(entry.getKey().getPort() + "/" + entry.getKey().getScheme());
jsonGen.writeFieldName(entry.getKey().toString());
jsonGen.writeStartArray();
jsonGen.writeStartObject();
jsonGen.writeStringField("HostIp", entry.getValue().getHostIp());
Expand Down
32 changes: 32 additions & 0 deletions src/test/java/com/github/dockerjava/api/model/ExposedPortTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.github.dockerjava.api.model;

import static org.testng.Assert.assertEquals;

import org.testng.annotations.Test;

public class ExposedPortTest {

@Test
public void parse() {
ExposedPort exposedPort = ExposedPort.parse("80/tcp");
assertEquals(exposedPort.getPort(), 80);
}

@Test(expectedExceptions = IllegalArgumentException.class,
expectedExceptionsMessageRegExp = "Error parsing ExposedPort 'nonsense'")
public void parseInvalidInput() {
ExposedPort.parse("nonsense");
}

@Test(expectedExceptions = IllegalArgumentException.class,
expectedExceptionsMessageRegExp = "Error parsing ExposedPort 'null'")
public void parseNull() {
ExposedPort.parse(null);
}

@Test
public void stringify() {
assertEquals(ExposedPort.parse("80/tcp").toString(), "80/tcp");
}

}