Skip to content
Permalink
Browse files

[FIXED JENKINS-23704] Allow specify port binding when starting the co…

…ntainer
  • Loading branch information...
vjuranek committed Aug 1, 2014
1 parent 6472716 commit 37aab429b6eeff9e29185a5c37885df18a00c9c0
Showing with 44 additions and 21 deletions.
  1. +44 −21 src/main/java/org/jenkinsci/plugins/dockerbuildstep/cmd/StartCommand.java
@@ -16,7 +16,9 @@
import com.github.dockerjava.client.DockerClient;
import com.github.dockerjava.client.DockerException;
import com.github.dockerjava.client.model.ContainerInspectResponse;
import com.github.dockerjava.client.model.ExposedPort;
import com.github.dockerjava.client.model.Ports;
import com.github.dockerjava.client.model.Ports.Binding;

/**
* This command starts one or more Docker containers. It also exports some build environment variable like IP or started
@@ -43,11 +45,11 @@ public StartCommand(String containerIds, String portBindings, String waitPorts)
public String getContainerIds() {
return containerIds;
}

public String getPortBindings() {
return portBindings;
}

public String getWaitPorts() {
return waitPorts;
}
@@ -59,57 +61,78 @@ public void execute(@SuppressWarnings("rawtypes") AbstractBuild build, ConsoleLo
throw new IllegalArgumentException("At least one parameter is required");
}

//expand build and env. variable
// expand build and env. variable
String containerIdsRes = Resolver.buildVar(build, containerIds);
String portBindingsRes = Resolver.buildVar(build, portBindings);

List<String> ids = Arrays.asList(containerIdsRes.split(","));
Ports bindPorts = parsePortBindings(portBindingsRes);
DockerClient client = getClient();
//TODO check, if container exists and is stopped (probably catch exception)

// TODO check, if container exists and is stopped (probably catch exception)
for (String id : ids) {
id = id.trim();
client.execute(client.startContainerCmd(id));
client.execute(client.startContainerCmd(id).withPortBindings(bindPorts));
console.logInfo("started container id " + id);

ContainerInspectResponse inspectResp = client.execute(client.inspectContainerCmd(id));
EnvInvisibleAction envAction = new EnvInvisibleAction(inspectResp);
build.addAction(envAction);
}
//wait for ports
if(waitPorts != null && !waitPorts.isEmpty()) {

// wait for ports
if (waitPorts != null && !waitPorts.isEmpty()) {
waitForPorts(client, console);
}
}

private Ports parsePortBindings(String bindings) {
/**
* Assumes one port binding per line in format
* <ul>
* <li>dockerPort hostPort</li>
* <li>dockerPort/scheme hostPort</li>
* <li>dockerPort hostIP:hostPort</li>
* <li>dockerPort/scheme hostIP:hostPort</li>
* </ul>
*/
private Ports parsePortBindings(String bindings) throws IllegalArgumentException {
if (bindings == null || bindings.isEmpty())
return null;

Ports ports = new Ports();

String[] bindLines = bindings.split("\\r?\\n");
for (String bind : bindLines) {
String[] bindSplit = bind.trim().split(" ", 2);
if(bindSplit.length != 2)
throw new IllegalArgumentException("Port binding needs to be in format 'hostPort containerPort'");
ExposedPort ep = bindSplit[0].contains("/") ? ExposedPort.parse(bindSplit[0].trim()) : ExposedPort.tcp(new Integer(bindSplit[0].trim()));
String[] hostBind = bindSplit[1].trim().split(":", 2);
Binding b = hostBind.length > 1 ? new Binding(hostBind[0], new Integer(hostBind[1])) : new Binding(new Integer(hostBind[0]));
ports.bind(ep, b);
}
return ports;
}

private void waitForPorts(DockerClient client, ConsoleLogger console) throws DockerException {
Map<String, List<Integer>> containers = PortUtils.parsePorts(waitPorts);
for(String cId : containers.keySet()) {
for (String cId : containers.keySet()) {
ContainerInspectResponse inspectResp = client.execute(client.inspectContainerCmd(cId));
String ip = inspectResp.getNetworkSettings().getIpAddress();
List<Integer> ports = containers.get(cId);
for(Integer port : ports) {
for (Integer port : ports) {
console.logInfo("Waiting for port " + port + " on " + ip + " (conatiner ID " + cId + ")");
boolean portReady = PortUtils.waitForPort(ip, port);
if(portReady) {
if (portReady) {
console.logInfo(ip + ":" + port + " ready");
}
else {
//TODO fail the build, but make timeout configurable first
console.logWarn(ip + ":" + port + " still not available (conatiner ID " + cId + "), but build continues ...");
} else {
// TODO fail the build, but make timeout configurable first
console.logWarn(ip + ":" + port + " still not available (conatiner ID " + cId
+ "), but build continues ...");
}
}
}
}

@Extension
public static class StartCommandDescriptor extends DockerCommandDescriptor {
@Override

0 comments on commit 37aab42

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.