diff options
Diffstat (limited to 'containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/ContainerLauncher.java')
-rw-r--r-- | containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/ContainerLauncher.java | 251 |
1 files changed, 186 insertions, 65 deletions
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/ContainerLauncher.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/ContainerLauncher.java index c5ea7e0fff..cc745da3fe 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/ContainerLauncher.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/ContainerLauncher.java @@ -48,7 +48,6 @@ import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.linuxtools.docker.core.DockerConnectionManager; import org.eclipse.linuxtools.docker.core.DockerException; -import org.eclipse.linuxtools.docker.core.EnumDockerLoggingStatus; import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.docker.core.IDockerContainerConfig; import org.eclipse.linuxtools.docker.core.IDockerContainerExit; @@ -59,16 +58,22 @@ import org.eclipse.linuxtools.docker.core.IDockerImageInfo; import org.eclipse.linuxtools.docker.core.IDockerPortBinding; import org.eclipse.linuxtools.docker.ui.Activator; import org.eclipse.linuxtools.internal.docker.core.DockerConnection; +import org.eclipse.linuxtools.internal.docker.core.DockerConsoleOutputStream; import org.eclipse.linuxtools.internal.docker.core.DockerContainerConfig; import org.eclipse.linuxtools.internal.docker.core.DockerHostConfig; import org.eclipse.linuxtools.internal.docker.core.DockerPortBinding; +import org.eclipse.linuxtools.internal.docker.core.IConsoleListener; import org.eclipse.linuxtools.internal.docker.ui.consoles.ConsoleOutputStream; import org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole; import org.eclipse.linuxtools.internal.docker.ui.launch.ContainerCommandProcess; import org.eclipse.linuxtools.internal.docker.ui.launch.LaunchConfigurationUtils; import org.eclipse.linuxtools.internal.docker.ui.views.DVMessages; import org.eclipse.linuxtools.internal.docker.ui.wizards.DataVolumeModel; +import org.eclipse.swt.custom.CTabFolder; +import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; public class ContainerLauncher { @@ -545,6 +550,25 @@ public class ContainerLauncher { } + // The following class allows us to use internal IConsoleListeners in + // docker.core + // but still use the public IRunConsoleListeners API here without requiring + // a minor release. + private class RunConsoleListenerBridge implements IConsoleListener { + + private IRunConsoleListener listener; + + public RunConsoleListenerBridge(IRunConsoleListener listener) { + this.listener = listener; + } + + @Override + public void newOutput(String output) { + listener.newOutput(output); + } + + } + /** * Perform a launch of a command in a container and output stdout/stderr to * console. @@ -652,6 +676,17 @@ public class ContainerLauncher { .cmd(cmdList) .image(image) .workingDir(workingDir); + + // Ugly hack...we want CDT gdbserver to run in the terminal so we look + // for its + // ContainerListener class and set tty=true in that case...this avoids a + // minor release and we can later add a new launch method with the tty + // option + if (listener != null && listener.getClass().getName().equals( + "org.eclipse.cdt.internal.docker.launcher.ContainerLaunchConfigurationDelegate$StartGdbServerJob")) { + builder = builder.tty(true); + } + // add any exposed ports as needed if (exposedPorts.size() > 0) builder = builder.exposedPorts(exposedPorts); @@ -776,77 +811,163 @@ public class ContainerLauncher { return; } } - OutputStream stream = null; - RunConsole oldConsole = getConsole(); - final RunConsole rc = RunConsole.findConsole(containerId, - consoleId); - setConsole(rc); - rc.clearConsole(); - if (oldConsole != null) - RunConsole.removeConsole(oldConsole); - Display.getDefault() - .syncExec(() -> rc.setTitle(Messages.getFormattedString( - LAUNCH_TITLE, new String[] { cmdList.get(0), - imageName }))); - // if (!rc.isAttached()) { - rc.attachToConsole(connection, containerId); - // } - if (rc != null) { - stream = rc.getOutputStream(); + if (config.tty()) { + // We need tty support to handle issue with Docker daemon + // not always outputting in time (e.g. we might get an + // output line after the process has exited which can be + // too late to show or it might get displayed in a wrong + // order in relation to other output. We also want the + // output to ultimately show up in the Console View. + OutputStream stream = null; + RunConsole oldConsole = getConsole(); + final RunConsole rc = RunConsole.findConsole(containerId, + consoleId); + setConsole(rc); + rc.clearConsole(); + if (oldConsole != null) + RunConsole.removeConsole(oldConsole); + Display.getDefault().syncExec(() -> rc.setTitle(Messages + .getFormattedString(LAUNCH_TITLE, new String[] { + cmdList.get(0), imageName }))); + if (rc != null) { + stream = rc.getOutputStream(); + } + + // We want terminal support, but we want to output to the + // RunConsole. + // To do this, we create a DockerConsoleOutputStream which + // we + // hook into the TM Terminal via stdout and stderr output + // listeners. + // These listeners will output to the + // DockerConsoleOutputStream which + // will in turn output to the RunConsole. See + // DockerConnection.openTerminal(). + DockerConsoleOutputStream out = new DockerConsoleOutputStream( + stream); + RunConsole.attachToTerminal(connection, containerId, out); if (containerListener != null) { - ((ConsoleOutputStream) stream) - .addConsoleListener(containerListener); + out.addConsoleListener(new RunConsoleListenerBridge( + containerListener)); } - } - // Create a unique logging thread id which has container id - // and console id - String loggingId = containerId + "." + consoleId; - ((DockerConnection) connection).startContainer(containerId, - loggingId, stream); - if (rc != null) - rc.showConsole(); - if (containerListener != null) { + ((DockerConnection) connection).startContainer(containerId, + null, null); IDockerContainerInfo info = ((DockerConnection) connection) .getContainerInfo(containerId); - containerListener.containerInfo(info); - } + if (containerListener != null) { + containerListener.containerInfo(info); + } + // Wait for the container to finish + final IDockerContainerExit status = ((DockerConnection) connection) + .waitForContainer(containerId); + Display.getDefault().syncExec(() -> { + rc.setTitle( + Messages.getFormattedString(LAUNCH_EXITED_TITLE, + new String[] { + status.statusCode().toString(), + cmdList.get(0), imageName })); + rc.showConsole(); + // We used a TM Terminal to receive the output of the + // session and + // then sent the output to the RunConsole. Remove the + // terminal + // tab that got created now that we are finished and all + // data is shown + // in Console View. + IWorkbenchPage page = PlatformUI.getWorkbench() + .getActiveWorkbenchWindow().getActivePage(); + IViewPart terminalView = page.findView( + "org.eclipse.tm.terminal.view.ui.TerminalsView"); + CTabFolder ctabfolder = terminalView + .getAdapter(CTabFolder.class); + if (ctabfolder != null) { + CTabItem[] items = ctabfolder.getItems(); + for (CTabItem item : items) { + if (item.getText().endsWith(info.name())) { + item.dispose(); + break; + } + } + } + }); + // Let any container listener know that the container is + // finished + if (containerListener != null) + containerListener.done(); + + if (!keepContainer) { + ((DockerConnection) connection) + .removeContainer(containerId); + } + } else { + OutputStream stream = null; + RunConsole oldConsole = getConsole(); + final RunConsole rc = RunConsole.findConsole(containerId, + consoleId); + setConsole(rc); + rc.clearConsole(); + if (oldConsole != null) + RunConsole.removeConsole(oldConsole); + Display.getDefault().syncExec(() -> rc.setTitle(Messages + .getFormattedString(LAUNCH_TITLE, new String[] { + cmdList.get(0), imageName }))); + // if (!rc.isAttached()) { + rc.attachToConsole(connection, containerId); + // } + if (rc != null) { + stream = rc.getOutputStream(); + if (containerListener != null) { + ((ConsoleOutputStream) stream) + .addConsoleListener(containerListener); + } + } + // Create a unique logging thread id which has container id + // and console id + String loggingId = containerId + "." + consoleId; + ((DockerConnection) connection).startContainer(containerId, + loggingId, stream); + if (rc != null) + rc.showConsole(); + if (containerListener != null) { + IDockerContainerInfo info = ((DockerConnection) connection) + .getContainerInfo(containerId); + containerListener.containerInfo(info); + } - // Wait for the container to finish - final IDockerContainerExit status = ((DockerConnection) connection) - .waitForContainer(containerId); - Display.getDefault().syncExec(() -> { - rc.setTitle( - Messages.getFormattedString(LAUNCH_EXITED_TITLE, - new String[] { - status.statusCode().toString(), - cmdList.get(0), imageName })); - rc.showConsole(); - }); - - // Let any container listener know that the container is - // finished - if (containerListener != null) - containerListener.done(); - - if (!keepContainer) { - // Drain the logging thread before we remove the - // container (we need to use the logging id) - ((DockerConnection) connection) - .stopLoggingThread(loggingId); - while (((DockerConnection) connection).loggingStatus( - loggingId) == EnumDockerLoggingStatus.LOGGING_ACTIVE) { + // Wait for the container to finish + final IDockerContainerExit status = ((DockerConnection) connection) + .waitForContainer(containerId); + Display.getDefault().syncExec(() -> { + rc.setTitle( + Messages.getFormattedString(LAUNCH_EXITED_TITLE, + new String[] { + status.statusCode().toString(), + cmdList.get(0), imageName })); + rc.showConsole(); + }); + + // Let any container listener know that the container is + // finished + if (containerListener != null) + containerListener.done(); + + if (!keepContainer) { + // Drain the logging thread before we remove the + // container (we need to use the logging id) Thread.sleep(1000); + ((DockerConnection) connection) + .stopLoggingThread(loggingId); + // Look for any Display Log console that the user may + // have opened which would be + // separate and make sure it is removed as well + RunConsole rc2 = RunConsole + .findConsole(((DockerConnection) connection) + .getContainer(containerId)); + if (rc2 != null) + RunConsole.removeConsole(rc2); + ((DockerConnection) connection) + .removeContainer(containerId); } - // Look for any Display Log console that the user may - // have opened which would be - // separate and make sure it is removed as well - RunConsole rc2 = RunConsole - .findConsole(((DockerConnection) connection) - .getContainer(containerId)); - if (rc2 != null) - RunConsole.removeConsole(rc2); - ((DockerConnection) connection) - .removeContainer(containerId); } } catch (final DockerException e2) { |