diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java index 308e6c7ab..7e4990a7c 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerApp.java @@ -291,7 +291,7 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing, if (client==null) { console.write("Cannot start container... Docker client is disconnected!", LogType.STDERROR); } else { - Network network = target.ensureNetwork(); + Network network = target.ensureNetwork(console); console.write("Running container with '"+image+"'", LogType.STDOUT); JmxSupport jmx = new JmxSupport(); String jmxUrl = jmx.getJmxUrl(); @@ -305,7 +305,6 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing, .put(APP_NAME, getName()) .put(BUILD_ID, desiredBuildId) .put(SYSTEM_PROPS, sysprops); - ImmutableSet.Builder exposedPorts = ImmutableSet.builder(); ImmutableList.Builder portBindings = ImmutableList.builder(); @@ -371,6 +370,17 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing, String networkAlias = getName(); cb.withAliases(networkAlias); cb.withLabels(labels.build()); + + //See: https://www.pivotaltracker.com/story/show/175202648 + FakeDockerRunCommand fakeCmd = new FakeDockerRunCommand() + .withImage(image) + .withLabels(cb.getLabels()) + .withNetwork(network) + .withNetworkAliases(networkAlias) + .withPortBindings(cb.getHostConfig().getPortBindings()) + .withEnv(cb.getEnv()); + console.logCommand(fakeCmd.toString()); + CreateContainerResponse c = cb.exec(); console.write("Container created: "+c.getId(), LogType.STDOUT); console.write("Starting container: "+c.getId(), LogType.STDOUT); @@ -382,6 +392,7 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing, //appContext.showConsole(c.id()); client.startContainerCmd(c.getId()).exec(); + console.write("Streaming container output ...", LogType.STDOUT); containerLogConnection.setValue(DockerContainer.connectLog(target, c.getId(), console, true)); } } diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerRunTarget.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerRunTarget.java index 451b6a386..5f9145e6c 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerRunTarget.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/DockerRunTarget.java @@ -27,9 +27,11 @@ import java.util.UUID; import org.eclipse.core.resources.IProject; import org.springframework.ide.eclipse.boot.core.BootPropertyTester; import org.springframework.ide.eclipse.boot.dash.api.App; +import org.springframework.ide.eclipse.boot.dash.api.AppConsole; import org.springframework.ide.eclipse.boot.dash.api.DebuggableTarget; import org.springframework.ide.eclipse.boot.dash.api.ProjectDeploymentTarget; import org.springframework.ide.eclipse.boot.dash.cloudfoundry.RemoteBootDashModel; +import org.springframework.ide.eclipse.boot.dash.console.LogType; import org.springframework.ide.eclipse.boot.dash.devtools.DevtoolsUtil; import org.springframework.ide.eclipse.boot.dash.di.SimpleDIContext; import org.springframework.ide.eclipse.boot.dash.docker.ui.DefaultDockerUserInteractions; @@ -182,14 +184,16 @@ implements RemoteRunTarget, ProjectDeploymentT return true; } - public synchronized Network ensureNetwork() { + public synchronized Network ensureNetwork(AppConsole console) { DockerClient client = this.client.getValue(); if (client!=null) { Network network = getNetwork(client, DOCKER_NETWORK_NAME); if (network!=null) { return network; } - client.createNetworkCmd().withName(DOCKER_NETWORK_NAME).withDriver("bridge").exec(); + console.logCommand("docker network create -d bridge "+DOCKER_NETWORK_NAME); + CreateNetworkResponse r = client.createNetworkCmd().withName(DOCKER_NETWORK_NAME).withDriver("bridge").exec(); + console.logCommandResult(r.getId()); return getNetwork(client, DOCKER_NETWORK_NAME); } return null; diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/FakeDockerRunCommand.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/FakeDockerRunCommand.java new file mode 100644 index 000000000..a33fdaee5 --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.docker/src/org/springframework/ide/eclipse/boot/dash/docker/runtarget/FakeDockerRunCommand.java @@ -0,0 +1,119 @@ +package org.springframework.ide.eclipse.boot.dash.docker.runtarget; + +import java.util.Map; +import java.util.Map.Entry; + +import com.github.dockerjava.api.model.ExposedPort; +import com.github.dockerjava.api.model.Network; +import com.github.dockerjava.api.model.Ports; +import com.github.dockerjava.api.model.Ports.Binding; + +public class FakeDockerRunCommand { + + private String image; + private Map labels; + private String[] networkAliases; + private String network; + private Ports portBindings; + private String[] env; + + public FakeDockerRunCommand withImage(String image) { + this.image = image; + return this; + } + + public FakeDockerRunCommand withLabels(Map labels) { + this.labels = labels; + return this; + } + + @Override + public String toString() { + StringBuilder cmd = new StringBuilder("docker run"); + addOptions(cmd); + addArgs(cmd, image); + return cmd.toString(); + } + + private void addOptions(StringBuilder cmd) { + addLabels(cmd); + addNetwork(cmd); + addAliases(cmd); + addPortBindings(cmd); + addEnv(cmd); + } + + private void addEnv(StringBuilder cmd) { + if (env!=null && env.length>0) { + for (String b : env) { + addArgs(cmd, "--env", b); + } + } + } + + private void addPortBindings(StringBuilder cmd) { + if (portBindings!=null) { + Map bindings = portBindings.getBindings(); + if (!bindings.isEmpty()) { + for (Entry entry : bindings.entrySet()) { + ExposedPort exposed = entry.getKey(); + for (Binding bindTo : entry.getValue()) { + addArgs(cmd, "-p", + bindTo.getHostIp()+":"+bindTo.getHostPortSpec()+":"+exposed.getPort()+"/"+exposed.getProtocol() + ); + } + System.out.println(entry); + } + } + } + } + + private void addNetwork(StringBuilder cmd) { + if (network!=null) { + addArgs(cmd, "--network", network); + } + } + + public void addAliases(StringBuilder cmd) { + if (networkAliases!=null && networkAliases.length>0) { + for (String alias : networkAliases) { + addArgs(cmd, "--network-alias", alias); + } + } + } + + private void addLabels(StringBuilder cmd) { + if (labels!=null && !labels.isEmpty()) { + for (Entry entry : labels.entrySet()) { + addArgs(cmd, "--label", entry.getKey()+"="+entry.getValue()); + } + } + } + + private void addArgs(StringBuilder cmd, String... arg) { + cmd.append(" \\\n "); + cmd.append(CommandUtil.escape(arg)); + } + + public FakeDockerRunCommand withNetworkAliases(String... networkAliases) { + this.networkAliases = networkAliases; + return this; + } + + public FakeDockerRunCommand withNetwork(Network network) { + this.network = network.getName(); + return this; + } + + public FakeDockerRunCommand withPortBindings(Ports portBindings) { + this.portBindings = portBindings; + return this; + } + + public FakeDockerRunCommand withEnv(String... env) { + this.env = env; + return this; + } + + +} diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/.settings/org.springframework.ide.eclipse.prefs b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/.settings/org.springframework.ide.eclipse.prefs new file mode 100644 index 000000000..a12794d68 --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash.test/.settings/org.springframework.ide.eclipse.prefs @@ -0,0 +1,2 @@ +boot.validation.initialized=true +eclipse.preferences.version=1 diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/api/AppConsole.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/api/AppConsole.java index 46b0a50d9..ff868be79 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/api/AppConsole.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/api/AppConsole.java @@ -56,4 +56,23 @@ public interface AppConsole { void show(); + default void logCommand(String string) { + try { + String[] pieces = string.split("\\n"); + for (int i = 0; i < pieces.length; i++) { + write((i==0?"$ ":"> ")+pieces[i], LogType.STDOUT); + } + } catch (Exception e) { + Log.log(e); + } + } + + default void logCommandResult(String string) { + try { + write(string, LogType.STDOUT); + } catch (Exception e) { + Log.log(e); + } + } + }