/*******************************************************************************
* Copyright (c) 2014, 2016, 2017 Red Hat.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat - Initial Contribution
*******************************************************************************/
package org.eclipse.linuxtools.internal.docker.ui.wizards;
import static org.eclipse.linuxtools.internal.docker.ui.launch.IRunDockerImageLaunchConfigurationConstants.MB;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.linuxtools.docker.core.DockerException;
import org.eclipse.linuxtools.docker.core.IDockerConnection;
import org.eclipse.linuxtools.docker.core.IDockerHostConfig;
import org.eclipse.linuxtools.docker.core.IDockerImage;
import org.eclipse.linuxtools.docker.core.IDockerPortBinding;
import org.eclipse.linuxtools.internal.docker.core.DockerContainerConfig;
import org.eclipse.linuxtools.internal.docker.core.DockerContainerConfig.Builder;
import org.eclipse.linuxtools.internal.docker.core.DockerHostConfig;
import org.eclipse.linuxtools.internal.docker.core.DockerPortBinding;
import org.eclipse.linuxtools.internal.docker.ui.launch.IRunDockerImageLaunchConfigurationConstants;
import org.eclipse.linuxtools.internal.docker.ui.launch.LaunchConfigurationUtils;
import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageRunSelectionModel.ContainerLinkModel;
import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageRunSelectionModel.ExposedPortModel;
/**
* Wizard to 'docker run' a given {@link IDockerImage}.
*
* @author xcoulon
*
*/
public class ImageRun extends Wizard {
private final ImageRunSelectionPage imageRunSelectionPage;
private final ImageRunResourceVolumesVariablesPage imageRunResourceVolumesPage;
private final ImageRunNetworkPage imageRunNetworkPage;
/**
* Constructor when an {@link IDockerConnection} has been selected to run an
* {@link IDockerImage}.
*
* @param connection
* the {@link IDockerConnection} pointing to a specific Docker
* daemon/host.
* @throws DockerException
*/
public ImageRun(final IDockerConnection connection) throws DockerException {
super();
setWindowTitle(WizardMessages.getString("ImageRun.title")); //$NON-NLS-1$
setNeedsProgressMonitor(true);
this.imageRunSelectionPage = new ImageRunSelectionPage(connection);
this.imageRunResourceVolumesPage = new ImageRunResourceVolumesVariablesPage(
connection);
this.imageRunNetworkPage = new ImageRunNetworkPage(connection);
}
/**
* Full constructor with a selected {@link IDockerImage} to run.
*
* @param selectedImage
* the {@link IDockerImage} to use to fill the wizard pages
* @throws DockerException
* @throws CoreException
*/
public ImageRun(final IDockerImage selectedImage)
throws DockerException, CoreException {
setWindowTitle(WizardMessages.getString("ImageRun.title")); //$NON-NLS-1$
setNeedsProgressMonitor(true);
// attempt to find the last "Image Run" launch configuration for this
// image
final ILaunchConfiguration lastLaunchConfiguration = LaunchConfigurationUtils
.getLaunchConfigurationByImageName(
LaunchConfigurationUtils.getLaunchConfigType(
IRunDockerImageLaunchConfigurationConstants.CONFIG_TYPE_ID),
selectedImage.repoTags().get(0));
this.imageRunSelectionPage = new ImageRunSelectionPage(selectedImage,
lastLaunchConfiguration);
this.imageRunResourceVolumesPage = new ImageRunResourceVolumesVariablesPage(
selectedImage, lastLaunchConfiguration);
this.imageRunNetworkPage = new ImageRunNetworkPage(selectedImage,
lastLaunchConfiguration);
}
@Override
public void addPages() {
addPage(imageRunSelectionPage);
addPage(imageRunResourceVolumesPage);
addPage(imageRunNetworkPage);
}
@Override
public IWizardPage getNextPage(final IWizardPage page) {
if (page.equals(imageRunSelectionPage)) {
imageRunResourceVolumesPage.getModel().setSelectedImage(
imageRunSelectionPage.getModel().getSelectedImage());
}
return super.getNextPage(page);
}
@Override
public boolean performFinish() {
return true;
}
public String getDockerContainerName() {
return this.imageRunSelectionPage.getModel().getContainerName();
}
public boolean removeWhenExits() {
return this.imageRunSelectionPage.getModel().isRemoveWhenExits();
}
public IDockerHostConfig getDockerHostConfig() {
final ImageRunSelectionModel selectionModel = this.imageRunSelectionPage
.getModel();
final ImageRunResourceVolumesVariablesModel resourcesModel = this.imageRunResourceVolumesPage
.getModel();
final ImageRunNetworkModel networkModel = this.imageRunNetworkPage
.getModel();
final DockerHostConfig.Builder hostConfigBuilder = new DockerHostConfig.Builder();
if (selectionModel.isPublishAllPorts()) {
hostConfigBuilder.publishAllPorts(true);
} else {
final Map<String, List<IDockerPortBinding>> portBindings = new HashMap<>();
for (Iterator<ExposedPortModel> iterator = selectionModel
.getExposedPorts().iterator(); iterator.hasNext();) {
final ExposedPortModel exposedPort = iterator.next();
// only selected Ports in the CheckboxTableViewer are exposed.
if (!selectionModel.getSelectedPorts().contains(exposedPort)) {
continue;
}
final DockerPortBinding portBinding = new DockerPortBinding(
exposedPort.getHostAddress(),
exposedPort.getHostPort());
portBindings.put(
exposedPort.getContainerPort()
+ exposedPort.getPortType(),
Arrays.<IDockerPortBinding> asList(portBinding));
}
hostConfigBuilder.portBindings(portBindings);
}
// container links
final List<String> links = new ArrayList<>();
for (Iterator<ContainerLinkModel> iterator = selectionModel.getLinks()
.iterator(); iterator.hasNext();) {
final ContainerLinkModel link = iterator.next();
links.add(link.getContainerName() + ':' + link.getContainerAlias());
}
hostConfigBuilder.links(links);
// data volumes
final List<String> volumesFrom = new ArrayList<>();
final List<String> binds = new ArrayList<>();
for (Iterator<DataVolumeModel> iterator = resourcesModel
.getDataVolumes().iterator(); iterator.hasNext();) {
final DataVolumeModel dataVolume = iterator.next();
// only data volumes selected in the CheckBoxTableViewer are
// included.
if (!resourcesModel.getSelectedDataVolumes().contains(dataVolume)) {
continue;
}
switch (dataVolume.getMountType()) {
case HOST_FILE_SYSTEM:
String bind = LaunchConfigurationUtils
.convertToUnixPath(dataVolume.getHostPathMount())
+ ':' + dataVolume.getContainerPath() + ":Z"; //$NON-NLS-1$ //$NON-NLS-2$
if (dataVolume.isReadOnly()) {
bind += ",ro"; //$NON-NLS-1$
}
binds.add(bind);
break;
case CONTAINER:
volumesFrom.add(dataVolume.getContainerMount());
break;
default:
break;
}
}
hostConfigBuilder.binds(binds);
hostConfigBuilder.volumesFrom(volumesFrom);
hostConfigBuilder.privileged(selectionModel.isPrivileged());
String networkMode = networkModel.getNetworkModeString();
// if network mode is not default, set it in host config
if (networkMode != null
&& !networkMode.equals(ImageRunNetworkModel.DEFAULT_MODE))
hostConfigBuilder.networkMode(networkMode);
// memory constraints (in bytes)
if (resourcesModel.isEnableResourceLimitations()) {
hostConfigBuilder.memory(resourcesModel.getMemoryLimit() * MB);
hostConfigBuilder.cpuShares(resourcesModel.getCpuShareWeight());
}
return hostConfigBuilder.build();
}
public DockerContainerConfig getDockerContainerConfig() {
final ImageRunSelectionModel selectionModel = this.imageRunSelectionPage
.getModel();
final ImageRunResourceVolumesVariablesModel resourcesModel = this.imageRunResourceVolumesPage
.getModel();
final Builder config = new DockerContainerConfig.Builder()
.cmd(selectionModel.getCommand())
.entryPoint(selectionModel.getEntrypoint())
.image(selectionModel.getSelectedImageName())
.tty(selectionModel.isAllocatePseudoTTY())
.openStdin(selectionModel.isInteractiveMode());
if (resourcesModel.isEnableResourceLimitations()) {
// memory limit must be converted from MB to bytes
config.memory(resourcesModel.getMemoryLimit() * MB);
config.cpuShares(resourcesModel.getCpuShareWeight());
}
// environment variables
final List<String> environmentVariables = new ArrayList<>();
for (Iterator<EnvironmentVariableModel> iterator = resourcesModel
.getEnvironmentVariables().iterator(); iterator.hasNext();) {
final EnvironmentVariableModel var = iterator.next();
environmentVariables.add(var.getName() + "=" + var.getValue()); //$NON-NLS-1$
}
config.env(environmentVariables);
// container labels
final Map<String, String> labelVariables = new HashMap<>();
for (Iterator<LabelVariableModel> iterator = resourcesModel
.getLabelVariables().iterator(); iterator.hasNext();) {
final LabelVariableModel var = iterator.next();
labelVariables.put(var.getName(), var.getValue()); // $NON-NLS-1$
}
config.labels(labelVariables);
if (!selectionModel.isPublishAllPorts()) {
final Set<String> exposedPorts = new HashSet<>();
for (Iterator<ExposedPortModel> iterator = selectionModel
.getExposedPorts().iterator(); iterator.hasNext();) {
final ExposedPortModel exposedPort = iterator.next();
// only selected Ports in the CheckboxTableViewer are exposed.
if (!selectionModel.getSelectedPorts().contains(exposedPort)) {
continue;
}
exposedPorts.add(exposedPort.getContainerPort()
+ exposedPort.getPortType());
}
config.exposedPorts(exposedPorts);
}
return config.build();
}
}