use of org.eclipse.linuxtools.internal.docker.core.DockerPortBinding in project linuxtools by eclipse.
the class ContainerLauncher method launch.
/**
* Perform a launch of a command in a container and output stdout/stderr to
* console.
*
* @param id
* - id of caller to use to distinguish console owner
* @param listener
* - optional listener of the run console
* @param connectionUri
* - the specified connection to use
* @param image
* - the image to use
* @param cmdList
* - command to run as list of String
* @param workingDir
* - working directory or null
* @param additionalDirs
* - additional directories to mount or null
* @param origEnv
* - original environment if we are appending to our existing
* environment
* @param envMap
* - map of environment variable settings
* @param ports
* - ports to expose
* @param keep
* - keep container after running
* @param stdinSupport
* - true if stdin support is required, false otherwise
* @param privilegedMode
* - true if privileged mode is required, false otherwise
* @param labels
* - Map of labels for the container
* @param seccomp
* - seccomp profile
* @since 4.0
*/
public void launch(String id, IContainerLaunchListener listener, final String connectionUri, String image, List<String> cmdList, String workingDir, List<String> additionalDirs, Map<String, String> origEnv, Map<String, String> envMap, List<String> ports, boolean keep, boolean stdinSupport, boolean privilegedMode, Map<String, String> labels, String seccomp) {
// $NON-NLS-1$
final String LAUNCH_TITLE = "ContainerLaunch.title";
// $NON-NLS-1$
final String LAUNCH_EXITED_TITLE = "ContainerLaunchExited.title";
final List<String> env = new ArrayList<>();
env.addAll(toList(origEnv));
env.addAll(toList(envMap));
final Set<String> exposedPorts = new HashSet<>();
final Map<String, List<IDockerPortBinding>> portBindingsMap = new HashMap<>();
if (ports != null) {
for (String port : ports) {
port = port.trim();
if (port.length() > 0) {
// $NON-NLS-1$
String[] segments = port.split(":");
if (segments.length == 1) {
// containerPort
exposedPorts.add(segments[0]);
portBindingsMap.put(segments[0], Arrays.asList((IDockerPortBinding) new DockerPortBinding("", // $NON-NLS-1$ //$NON-NLS-2$
"")));
} else if (segments.length == 2) {
// hostPort:containerPort
exposedPorts.add(segments[1]);
portBindingsMap.put(segments[1], Arrays.asList((IDockerPortBinding) new DockerPortBinding("", // $NON-NLS-1$ //$NON-NLS-2$
segments[0])));
} else if (segments.length == 3) {
// either
// ip:hostPort:containerPort
// or ip::containerPort
exposedPorts.add(segments[1]);
if (segments[1].isEmpty()) {
portBindingsMap.put(segments[2], Arrays.asList((IDockerPortBinding) new DockerPortBinding("", // $NON-NLS-1$ //$NON-NLS-2$
segments[0])));
} else {
portBindingsMap.put(segments[2], Arrays.asList((IDockerPortBinding) new DockerPortBinding(segments[0], // $NON-NLS-1$ //$NON-NLS-2$
segments[1])));
}
}
}
}
}
// Note we only pass volumes to the config if we have a
// remote daemon. Local mounted volumes are passed
// via the HostConfig binds setting
DockerContainerConfig.Builder builder = new DockerContainerConfig.Builder().openStdin(stdinSupport).cmd(cmdList).image(image).workingDir(workingDir);
// 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);
// add any labels if specified
if (labels != null)
builder = builder.labels(labels);
if (!DockerConnectionManager.getInstance().hasConnections()) {
Display.getDefault().syncExec(() -> MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), DVMessages.getString(ERROR_LAUNCHING_CONTAINER), DVMessages.getString(ERROR_NO_CONNECTIONS)));
return;
}
// Try and use the specified connection that was used before,
// otherwise, open an error
final IDockerConnection connection = DockerConnectionManager.getInstance().getConnectionByUri(connectionUri);
if (connection == null) {
Display.getDefault().syncExec(() -> MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), DVMessages.getString(ERROR_LAUNCHING_CONTAINER), DVMessages.getFormattedString(ERROR_NO_CONNECTION_WITH_URI, connectionUri)));
return;
}
// if connection is not open, force it to be by fetching images
if (!connection.isOpen()) {
connection.getImages();
}
DockerHostConfig.Builder hostBuilder = new DockerHostConfig.Builder().privileged(privilegedMode);
// ptrace with gdbserver
if (seccomp != null) {
hostBuilder.securityOpt(seccomp);
}
final Map<String, String> remoteVolumes = new HashMap<>();
if (!((DockerConnection) connection).isLocal()) {
@SuppressWarnings("rawtypes") final Map<String, Map> volumes = new HashMap<>();
// the host data over before starting.
if (additionalDirs != null) {
for (String dir : additionalDirs) {
remoteVolumes.put(dir, dir);
volumes.put(dir, new HashMap<>());
}
}
if (workingDir != null) {
// $NON-NLS-1$
remoteVolumes.put(workingDir, workingDir);
volumes.put(workingDir, new HashMap<>());
}
builder = builder.volumes(volumes);
} else {
// Running daemon on local host.
// Add mounts for any directories we need to run the executable.
// When we add mount points, we need entries of the form:
// hostname:mountname:Z.
// In our case, we want all directories mounted as-is so the
// executable will run as the user expects.
final List<String> volumes = new ArrayList<>();
if (additionalDirs != null) {
for (String dir : additionalDirs) {
// $NON-NLS-1$ //$NON-NLS-2$
volumes.add(dir + ":" + dir + ":Z");
}
}
if (workingDir != null) {
// $NON-NLS-1$ //$NON-NLS-2$
volumes.add(workingDir + ":" + workingDir + ":Z");
}
hostBuilder = hostBuilder.binds(volumes);
}
final DockerContainerConfig config = builder.build();
// add any port bindings if specified
if (portBindingsMap.size() > 0)
hostBuilder = hostBuilder.portBindings(portBindingsMap);
final IDockerHostConfig hostConfig = hostBuilder.build();
final String imageName = image;
final boolean keepContainer = keep;
final String consoleId = id;
final IContainerLaunchListener containerListener = listener;
Thread t = new Thread(() -> {
// create the container
String containerId = null;
try {
containerId = ((DockerConnection) connection).createContainer(config, hostConfig, null);
if (!((DockerConnection) connection).isLocal()) {
// data over from the host.
if (!remoteVolumes.isEmpty()) {
CopyVolumesJob job = new CopyVolumesJob(remoteVolumes, connection, containerId);
job.schedule();
job.join();
if (job.getResult() != Status.OK_STATUS)
return;
}
}
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) {
out.addConsoleListener(new RunConsoleListenerBridge(containerListener));
}
((DockerConnection) connection).startContainer(containerId, null, null);
IDockerContainerInfo info = ((DockerConnection) connection).getContainerInfo(containerId);
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;
}
}
}
});
// 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();
});
// 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);
}
}
} catch (final DockerException e2) {
// error in creation, try and remove Container if possible
if (!keepContainer && containerId != null) {
try {
((DockerConnection) connection).removeContainer(containerId);
} catch (DockerException | InterruptedException e1) {
// ignore exception
}
}
Display.getDefault().syncExec(() -> MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), DVMessages.getFormattedString(ERROR_CREATING_CONTAINER, imageName), e2.getMessage()));
} catch (InterruptedException e3) {
// for now
// do nothing
}
((DockerConnection) connection).getContainers(true);
});
t.start();
}
use of org.eclipse.linuxtools.internal.docker.core.DockerPortBinding in project linuxtools by eclipse.
the class LaunchConfigurationUtilsTest method shouldDeserializeBindings.
@Test
public void shouldDeserializeBindings() {
// given
final List<String> publishedPorts = Arrays.asList("8080/tcp:1.2.3.4:8080", "8080/tcp::8080", "9090/tcp:1.2.3.4:9090", "9090/tcp::9090");
// when
final Map<String, List<IDockerPortBinding>> result = LaunchConfigurationUtils.deserializePortBindings(publishedPorts);
// then
assertThat(result).containsOnly(MapEntry.entry("8080/tcp", Arrays.asList(new DockerPortBinding("1.2.3.4", "8080"), new DockerPortBinding(null, "8080"))), MapEntry.entry("9090/tcp", Arrays.asList(new DockerPortBinding("1.2.3.4", "9090"), new DockerPortBinding(null, "9090"))));
}
use of org.eclipse.linuxtools.internal.docker.core.DockerPortBinding in project linuxtools by eclipse.
the class ImageRun method getDockerHostConfig.
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();
// included.
if (!resourcesModel.getSelectedDataVolumes().contains(dataVolume)) {
continue;
}
switch(dataVolume.getMountType()) {
case HOST_FILE_SYSTEM:
String bind = LaunchConfigurationUtils.convertToUnixPath(dataVolume.getHostPathMount()) + ':' + dataVolume.getContainerPath() + // $NON-NLS-1$ //$NON-NLS-2$
":Z";
if (dataVolume.isReadOnly()) {
// $NON-NLS-1$
bind += ",ro";
}
binds.add(bind);
break;
case CONTAINER:
volumesFrom.add(dataVolume.getContainerMount());
break;
default:
break;
}
}
hostConfigBuilder.binds(binds);
hostConfigBuilder.volumesFrom(volumesFrom);
hostConfigBuilder.privileged(selectionModel.isPrivileged());
// make /tmp and /run use tmpfs, and drop all capabilities
if (selectionModel.isBasicSecurity()) {
hostConfigBuilder.readonlyRootfs(true);
Map<String, String> tmpfsValues = new HashMap<>();
// $NON-NLS-1$ //$NON-NLS-2$
tmpfsValues.put("/run", "rw,exec");
// $NON-NLS-1$ //$NON-NLS-2$
tmpfsValues.put("/tmp", "rw,exec");
hostConfigBuilder.tmpfs(tmpfsValues);
List<String> capDropList = new ArrayList<>();
// $NON-NLS-1$
capDropList.add("all");
hostConfigBuilder.capDrop(capDropList);
}
if (selectionModel.isUnconfined()) {
List<String> seccomp = new ArrayList<>();
// $NON-NLS-1$
seccomp.add("seccomp:unconfined");
hostConfigBuilder.securityOpt(seccomp);
}
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();
}
Aggregations