blob: 449765ae9a991a990f25865e7a06db80c7c72988 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2020 Red Hat Inc. and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat - Initial Contribution
*******************************************************************************/
package org.eclipse.linuxtools.internal.docker.ui.commands;
import static org.eclipse.linuxtools.internal.docker.ui.commands.CommandUtils.getRunConsole;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.RuntimeProcess;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.linuxtools.docker.core.DockerContainerNotFoundException;
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.IDockerContainer;
import org.eclipse.linuxtools.docker.core.IDockerContainerConfig;
import org.eclipse.linuxtools.docker.core.IDockerHostConfig;
import org.eclipse.linuxtools.docker.core.IDockerImage;
import org.eclipse.linuxtools.docker.ui.Activator;
import org.eclipse.linuxtools.internal.docker.core.DockerConnection;
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.ImageRun;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.handlers.HandlerUtil;
public class RunImageCommandHandler extends AbstractHandler {
private static final String ERROR_CREATING_CONTAINER = "ContainerCreateError.msg"; //$NON-NLS-1$
private static final String ERROR_REMOVING_CONTAINER = "ContainerRemoveError.msg"; //$NON-NLS-1$
@Override
public Object execute(final ExecutionEvent event) {
final IWorkbenchPart activePart = HandlerUtil.getActivePart(event);
final IDockerImage selectedImage = CommandUtils
.getSelectedImage(activePart);
if (selectedImage == null) {
Activator.log(new DockerException(
DVMessages.getString("RunImageUnableToRetrieveError.msg"))); //$NON-NLS-1$
} else {
try {
final ImageRun wizard = new ImageRun(selectedImage);
final boolean runImage = CommandUtils.openWizard(wizard,
HandlerUtil.getActiveShell(event));
if (runImage) {
final IDockerContainerConfig containerConfig = wizard
.getDockerContainerConfig();
List<String> unusedPorts = new ArrayList<>();
final IDockerHostConfig hostConfig = wizard
.getDockerHostConfig(unusedPorts);
runImage(selectedImage, containerConfig, null,
hostConfig, unusedPorts, wizard.getDockerContainerName(),
wizard.removeWhenExits());
}
} catch (DockerException | CoreException e) {
Activator.log(e);
}
}
return null;
}
/**
* Run the given {@link IDockerImage} with the given settings
*
* @param image
* @param containerConfig
* @param hostConfig
* @param containerName
* @param removeWhenExits
*/
public static void runImage(final IDockerImage image,
final IDockerContainerConfig containerConfig,
final ILaunch launch,
final IDockerHostConfig hostConfig,
final List<String> unusedPorts,
final String containerName,
final boolean removeWhenExits) {
final IDockerConnection connection = image.getConnection();
if (containerConfig.tty()) {
// show the console view
Display.getDefault().asyncExec(() -> {
try {
PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getActivePage()
.showView(IConsoleConstants.ID_CONSOLE_VIEW);
} catch (Exception e) {
Activator.log(e);
}
});
}
// Create the container in a non-UI thread.
final Job runImageJob = new Job(
DVMessages.getString("RunImageCreateContainer.job")) { //$NON-NLS-1$
@Override
protected IStatus run(final IProgressMonitor monitor) {
monitor.beginTask(
DVMessages.getString("RunImageRunningTask.msg"), 2); //$NON-NLS-1$
String containerId = null;
RunConsole console = null;
try {
final SubMonitor createContainerMonitor = SubMonitor
.convert(monitor, 1);
// create the container
createContainerMonitor.beginTask(
DVMessages.getString(
"RunImageCreatingContainerTask.msg"), //$NON-NLS-1$
1);
containerId = ((DockerConnection) connection)
.createContainer(containerConfig, hostConfig, containerName);
final IDockerContainer container = ((DockerConnection) connection)
.getContainer(containerId);
createContainerMonitor.done();
// abort if operation was cancelled
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
// start the container
final SubMonitor startContainerMonitor = SubMonitor
.convert(monitor, 1);
startContainerMonitor.beginTask(DVMessages
.getString("RunImageStartingContainerTask.msg"), 1); //$NON-NLS-1$
console = getRunConsole(connection, container);
OutputStream outputStream = null;
if (console != null) {
// if we are auto-logging, show the console
console.showConsole();
outputStream = console.getOutputStream();
}
// Start the Container and create a process we can wrap with
// a RuntimeProcess and set into the ILaunch
ContainerCommandProcess commandProcess = new ContainerCommandProcess(
connection, container.image(), containerId,
outputStream, null,
true);
if (launch != null) {
new RuntimeProcess(launch, commandProcess,
container.name(), null);
}
startContainerMonitor.done();
// create a launch configuration from the container
LaunchConfigurationUtils.createRunImageLaunchConfiguration(image,
containerConfig,
hostConfig, unusedPorts, containerName,
removeWhenExits);
} catch (final DockerException | InterruptedException e) {
if (console != null) {
RunConsole.removeConsole(console);
}
Display.getDefault().syncExec(() -> MessageDialog.openError(
PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getShell(),
DVMessages.getFormattedString(
ERROR_CREATING_CONTAINER,
containerConfig.image()),
e.getMessage()));
} finally {
final String tmpContainerId = containerId;
if (removeWhenExits) {
final Job waitContainerJob = new Job(
CommandMessages.getString(
"RunImageCommandHandler.waitContainer.label")) { //$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
if (tmpContainerId != null) {
// Wait for the container to finish
((DockerConnection) connection)
.waitForContainer(tmpContainerId);
// Drain the logging thread before we remove the
// container
((DockerConnection) connection)
.stopLoggingThread(tmpContainerId);
while (((DockerConnection) connection)
.loggingStatus(
tmpContainerId) == EnumDockerLoggingStatus.LOGGING_ACTIVE) {
Thread.sleep(1000);
}
}
} catch (DockerContainerNotFoundException e) {
// container not created correctly
return Status.OK_STATUS;
} catch (DockerException | InterruptedException e) {
// ignore any errors in waiting for container or
// draining log
}
try {
// try and remove the container if it was created
if (tmpContainerId != null)
((DockerConnection) connection)
.removeContainer(tmpContainerId);
} catch (DockerException | InterruptedException e) {
final String id = tmpContainerId;
Display.getDefault()
.syncExec(() -> MessageDialog.openError(
PlatformUI.getWorkbench()
.getActiveWorkbenchWindow()
.getShell(),
DVMessages.getFormattedString(
ERROR_REMOVING_CONTAINER,
id),
e.getMessage()));
}
return Status.OK_STATUS;
}
};
// Do not display this job in the UI
waitContainerJob.setSystem(true);
waitContainerJob.schedule();
}
monitor.done();
}
return Status.OK_STATUS;
}
};
runImageJob.schedule();
}
}