Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Johnston2017-02-09 23:42:06 +0000
committerJeff Johnston2017-03-13 19:07:56 +0000
commited04e837c059cde769eb280b6bf8a00efa4efda6 (patch)
tree50b27ef16323f0a49536806af7ab888a787eb69b
parent0ba4f455eb8849b7f1802f8460002d4035aa7563 (diff)
downloadorg.eclipse.linuxtools-ed04e837c059cde769eb280b6bf8a00efa4efda6.tar.gz
org.eclipse.linuxtools-ed04e837c059cde769eb280b6bf8a00efa4efda6.tar.xz
org.eclipse.linuxtools-ed04e837c059cde769eb280b6bf8a00efa4efda6.zip
Bug 513591 - Add support for launching commands in a Docker Container
- add securityOptions specification to IDockerHostConfig and DockerHostConfig - add support for showing security options in the Container Inspect tab of the Properties view by modifying ContainerInspectContentProvider - fix DockerConnection createContainer to add in the security options from the DockerHostConfig - add attachLog method to DockerConnection - create an IDockerConnection3 interface which contains waitForContainer and attachLog methods - fix ContainerLauncher to try and set uid and gid of calling user so output files are accessible from Container - add new runCommand method to ContainerLauncher to run an arbitrary command - add new ContainerCommandProcess which extends Process Change-Id: I08a404436bbd4132b623fb18a0e46b988c54ced1
-rw-r--r--containers/org.eclipse.linuxtools.docker.core/META-INF/MANIFEST.MF2
-rw-r--r--containers/org.eclipse.linuxtools.docker.core/pom.xml2
-rw-r--r--containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerConnection.java36
-rw-r--r--containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerConnection3.java28
-rw-r--r--containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerHostConfig.java5
-rw-r--r--containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java20
-rw-r--r--containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerHostConfig.java19
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/META-INF/MANIFEST.MF6
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/pom.xml2
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/ContainerLauncher.java252
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/IErrorMessageHolder.java20
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/Messages.properties6
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/ContainerCommandProcess.java128
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/LaunchMessages.properties4
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/ContainerInspectContentProvider.java1
15 files changed, 519 insertions, 12 deletions
diff --git a/containers/org.eclipse.linuxtools.docker.core/META-INF/MANIFEST.MF b/containers/org.eclipse.linuxtools.docker.core/META-INF/MANIFEST.MF
index ee3a5031a3..327ce16e44 100644
--- a/containers/org.eclipse.linuxtools.docker.core/META-INF/MANIFEST.MF
+++ b/containers/org.eclipse.linuxtools.docker.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Docker Core Plugin
Bundle-SymbolicName: org.eclipse.linuxtools.docker.core;singleton:=true
-Bundle-Version: 2.1.0.qualifier
+Bundle-Version: 3.0.0.qualifier
Bundle-Activator: org.eclipse.linuxtools.docker.core.Activator
Bundle-Vendor: Eclipse Linux Tools
Require-Bundle: org.eclipse.core.runtime;bundle-version="3.12.0",
diff --git a/containers/org.eclipse.linuxtools.docker.core/pom.xml b/containers/org.eclipse.linuxtools.docker.core/pom.xml
index 9015235bf1..434cdb598f 100644
--- a/containers/org.eclipse.linuxtools.docker.core/pom.xml
+++ b/containers/org.eclipse.linuxtools.docker.core/pom.xml
@@ -7,7 +7,7 @@
<version>2.3.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.linuxtools.docker.core</artifactId>
- <version>2.1.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerConnection.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerConnection.java
index 2e4fb9c229..b9c5e814d2 100644
--- a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerConnection.java
+++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerConnection.java
@@ -419,4 +419,40 @@ public interface IDockerConnection {
*/
boolean setSettings(IDockerConnectionSettings settings);
+ /**
+ * Wait for a Container to finish.
+ *
+ * @param id
+ * the container to wait for
+ * @return {@link IDockerContainerExit class}
+ * @throws DockerException
+ * in case of underlying problem (server error)
+ * @throws InterruptedException
+ * if the thread was interrupted
+ * @since 3.0
+ */
+ public IDockerContainerExit waitForContainer(String id)
+ throws DockerException, InterruptedException;
+
+ /**
+ * Attach output streams to the Container log.
+ *
+ * @param id
+ * id of container
+ * @param out
+ * stdout stream to write to
+ * @param err
+ * stderr stream to write to
+ * @throws DockerException
+ * in case of underlying problem (server error)
+ * @throws InterruptedException
+ * if the thread was interrupted
+ * @throws IOException
+ * if an I/O exception occurs during attach
+ * @since 3.0
+ */
+ public void attachLog(final String id, final OutputStream out,
+ final OutputStream err)
+ throws DockerException, InterruptedException, IOException;
+
}
diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerConnection3.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerConnection3.java
new file mode 100644
index 0000000000..bb3a0a9018
--- /dev/null
+++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerConnection3.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 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.docker.core;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * @since 3.0
+ */
+public interface IDockerConnection3 {
+
+ public IDockerContainerExit waitForContainer(String id)
+ throws DockerException, InterruptedException;
+
+ public void attachLog(final String id, final OutputStream out,
+ final OutputStream err)
+ throws DockerException, InterruptedException, IOException;
+
+}
diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerHostConfig.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerHostConfig.java
index dfd89b1b93..45d1a12e22 100644
--- a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerHostConfig.java
+++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/IDockerHostConfig.java
@@ -35,6 +35,11 @@ public interface IDockerHostConfig {
List<String> volumesFrom();
+ /**
+ * @since 3.0
+ */
+ List<String> securityOpt();
+
String networkMode();
}
diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java
index ad74c5925d..bfa46c6de3 100644
--- a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java
+++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java
@@ -1447,6 +1447,9 @@ public class DockerConnection
if (hc.volumesFrom() != null) {
hbuilder.volumesFrom(hc.volumesFrom());
}
+ if (hc.securityOpt() != null) {
+ hbuilder.securityOpt(hc.securityOpt());
+ }
// FIXME: add the 'memory()' method in the IDockerHostConfig
// interface
if (((DockerHostConfig) hc).memory() != null) {
@@ -1925,6 +1928,23 @@ public class DockerConnection
}
}
+ @Override
+ public void attachLog(final String id, final OutputStream out,
+ final OutputStream err)
+ throws DockerException, InterruptedException, IOException {
+ DockerClient copyClient;
+ try {
+ copyClient = getClientCopy();
+ LogStream stream = copyClient.logs(id, LogsParam.follow(),
+ LogsParam.stdout(), LogsParam.stderr());
+ stream.attach(out, err);
+ stream.close();
+ } catch (com.spotify.docker.client.DockerException e) {
+ throw new DockerException(e.getMessage(), e.getCause());
+ }
+ }
+
+ @Override
public IDockerContainerExit waitForContainer(final String id)
throws DockerException, InterruptedException {
try {
diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerHostConfig.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerHostConfig.java
index 228154c3be..bfadabec90 100644
--- a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerHostConfig.java
+++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerHostConfig.java
@@ -37,6 +37,7 @@ public class DockerHostConfig implements IDockerHostConfig {
private final List<String> dns;
private final List<String> dnsSearch;
private final List<String> volumesFrom;
+ private final List<String> securityOpt;
private final String networkMode;
private final Long memory;
private final Long cpuShares;
@@ -71,6 +72,7 @@ public class DockerHostConfig implements IDockerHostConfig {
this.networkMode = hostConfig.networkMode();
this.memory = hostConfig.memory();
this.cpuShares = hostConfig.cpuShares();
+ this.securityOpt = hostConfig.securityOpt();
}
private DockerHostConfig(final Builder builder) {
@@ -89,6 +91,7 @@ public class DockerHostConfig implements IDockerHostConfig {
this.networkMode = builder.networkMode;
this.memory = builder.memory;
this.cpuShares = builder.cpuShares;
+ this.securityOpt = builder.securityOpt;
}
@@ -143,6 +146,11 @@ public class DockerHostConfig implements IDockerHostConfig {
}
@Override
+ public List<String> securityOpt() {
+ return securityOpt;
+ }
+
+ @Override
public String networkMode() {
return networkMode;
}
@@ -171,6 +179,7 @@ public class DockerHostConfig implements IDockerHostConfig {
private List<String> dns;
private List<String> dnsSearch;
private List<String> volumesFrom;
+ private List<String> securityOpt;
private String networkMode;
private Long memory;
private Long cpuShares;
@@ -260,6 +269,16 @@ public class DockerHostConfig implements IDockerHostConfig {
return this;
}
+ public Builder securityOpt(final List<String> securityOpt) {
+ this.securityOpt = new ArrayList<>(securityOpt);
+ return this;
+ }
+
+ public Builder securityOpt(final String... securityOpt) {
+ this.securityOpt = Arrays.asList(securityOpt);
+ return this;
+ }
+
public Builder networkMode(final String networkMode) {
this.networkMode = networkMode;
return this;
diff --git a/containers/org.eclipse.linuxtools.docker.ui/META-INF/MANIFEST.MF b/containers/org.eclipse.linuxtools.docker.ui/META-INF/MANIFEST.MF
index a042b2a923..3d765bc025 100644
--- a/containers/org.eclipse.linuxtools.docker.ui/META-INF/MANIFEST.MF
+++ b/containers/org.eclipse.linuxtools.docker.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Docker UI Plug-in
Bundle-SymbolicName: org.eclipse.linuxtools.docker.ui;singleton:=true
-Bundle-Version: 2.1.0.qualifier
+Bundle-Version: 3.0.0.qualifier
Bundle-Activator: org.eclipse.linuxtools.docker.ui.Activator
Bundle-Vendor: Eclipse Linux Tools
Require-Bundle: org.eclipse.ui,
@@ -30,7 +30,9 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.tm.terminal.view.ui;bundle-version="4.1.0",
org.eclipse.tm.terminal.view.core;bundle-version="4.0.0",
com.ibm.icu,
- org.apache.commons.compress;bundle-version="1.6.0"
+ org.apache.commons.compress;bundle-version="1.6.0",
+ org.eclipse.cdt.managedbuilder.core,
+ org.eclipse.cdt.core
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Bundle-Localization: plugin
diff --git a/containers/org.eclipse.linuxtools.docker.ui/pom.xml b/containers/org.eclipse.linuxtools.docker.ui/pom.xml
index 817b7d65e3..169be39b60 100644
--- a/containers/org.eclipse.linuxtools.docker.ui/pom.xml
+++ b/containers/org.eclipse.linuxtools.docker.ui/pom.xml
@@ -7,7 +7,7 @@
<version>2.3.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.linuxtools.docker.ui</artifactId>
- <version>2.1.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
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 cc3e8c5e06..6366a07615 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
@@ -12,6 +12,7 @@ package org.eclipse.linuxtools.docker.ui.launch;
import java.io.IOException;
import java.io.OutputStream;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -19,12 +20,15 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
@@ -35,6 +39,8 @@ import org.eclipse.linuxtools.docker.core.IDockerConnection;
import org.eclipse.linuxtools.docker.core.IDockerContainerExit;
import org.eclipse.linuxtools.docker.core.IDockerContainerInfo;
import org.eclipse.linuxtools.docker.core.IDockerHostConfig;
+import org.eclipse.linuxtools.docker.core.IDockerImage;
+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;
@@ -43,6 +49,7 @@ import org.eclipse.linuxtools.internal.docker.core.DockerHostConfig;
import org.eclipse.linuxtools.internal.docker.core.DockerPortBinding;
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.views.DVMessages;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
@@ -56,6 +63,8 @@ public class ContainerLauncher {
private static RunConsole console;
+ private static Map<IProject, ID> fidMap = new HashMap<>();
+
private class CopyVolumesJob extends Job {
private static final String COPY_VOLUMES_JOB_TITLE = "ContainerLaunch.copyVolumesJob.title"; //$NON-NLS-1$
@@ -345,7 +354,7 @@ public class ContainerLauncher {
}
DockerHostConfig.Builder hostBuilder = new DockerHostConfig.Builder()
- .privileged(privilegedMode);
+ .privileged(privilegedMode).securityOpt("seccomp:unconfined"); //$NON-NLS-1$
final Set<String> remoteVolumes = new TreeSet<>();
@@ -515,6 +524,233 @@ public class ContainerLauncher {
t.start();
}
+ private class ID {
+ private Integer uid;
+ private Integer gid;
+
+ public ID(Integer uid, Integer gid) {
+ this.uid = uid;
+ this.gid = gid;
+ }
+
+ public Integer getuid() {
+ return uid;
+ }
+
+ public Integer getgid() {
+ return gid;
+ }
+ }
+
+ /**
+ * @since 3.0
+ */
+ public Process runCommand(String connectionName, String imageName, IProject project,
+ IErrorMessageHolder errMsgHolder, String command,
+ String commandDir,
+ String workingDir,
+ List<String> additionalDirs, Map<String, String> origEnv,
+ Properties envMap, boolean supportStdin,
+ boolean privilegedMode, HashMap<String, String> labels,
+ boolean keepContainer) {
+
+ Integer uid = null;
+ Integer gid = null;
+ // For Unix, make sure that the user id is passed with the run
+ // so any output files are accessible by this end-user
+ String os = System.getProperty("os.name"); //$NON-NLS-1$
+ if (os.indexOf("nux") > 0) { //$NON-NLS-1$
+ // first try and see if we have already run a command on this
+ // project
+ ID ugid = fidMap.get(project);
+ if (ugid == null) {
+ try {
+ uid = (Integer) Files.getAttribute(
+ project.getLocation().toFile().toPath(),
+ "unix:uid"); //$NON-NLS-1$
+ gid = (Integer) Files.getAttribute(
+ project.getLocation().toFile().toPath(),
+ "unix:gid"); //$NON-NLS-1$
+ ugid = new ID(uid, gid);
+ // store the uid for possible later usage
+ fidMap.put(project, ugid);
+ } catch (IOException e) {
+ // do nothing...leave as null
+ } // $NON-NLS-1$
+ } else {
+ uid = ugid.getuid();
+ gid = ugid.getgid();
+ }
+ }
+
+ final List<String> env = new ArrayList<>();
+ env.addAll(toList(origEnv));
+ env.addAll(toList(envMap));
+
+ final List<String> cmdList = getCmdList(command);
+
+ final Map<String, List<IDockerPortBinding>> portBindingsMap = new HashMap<>();
+
+
+ IDockerConnection[] connections = DockerConnectionManager
+ .getInstance().getConnections();
+ if (connections == null || connections.length == 0) {
+ errMsgHolder.setErrorMessage(
+ Messages.getString("ContainerLaunch.noConnections.error")); //$NON-NLS-1$
+ return null;
+ }
+
+ IDockerConnection connection = null;
+ for (IDockerConnection c : connections) {
+ if (c.getUri().equals(connectionName)) {
+ connection = c;
+ break;
+ }
+ }
+
+ if (connection == null) {
+ errMsgHolder.setErrorMessage(Messages.getFormattedString(
+ "ContainerLaunch.connectionNotFound.error", //$NON-NLS-1$
+ connectionName));
+ return null;
+ }
+
+ List<IDockerImage> images = connection.getImages();
+ if (images.isEmpty()) {
+ errMsgHolder.setErrorMessage(
+ Messages.getString("ContainerLaunch.noImages.error")); //$NON-NLS-1$
+ return null;
+ }
+
+ IDockerImageInfo info = connection.getImageInfo(imageName);
+ if (info == null) {
+ errMsgHolder.setErrorMessage(Messages.getFormattedString(
+ "ContainerLaunch.imageNotFound.error", imageName)); //$NON-NLS-1$
+ return null;
+ }
+
+ DockerContainerConfig.Builder builder = new DockerContainerConfig.Builder()
+ .openStdin(supportStdin).cmd(cmdList).image(imageName)
+ .workingDir(workingDir);
+
+ // switch to user id for Linux so output is accessible
+ if (uid != null) {
+ builder = builder.user(uid.toString());
+ }
+
+ // TODO: add group id here when supported by DockerHostConfig.Builder
+
+ // add any labels if specified
+ if (labels != null)
+ builder = builder.labels(labels);
+
+ DockerHostConfig.Builder hostBuilder = new DockerHostConfig.Builder()
+ .privileged(privilegedMode);
+
+ // Note we only pass volumes to the config if we have a
+ // remote daemon. Local mounted volumes are passed
+ // via the HostConfig binds setting
+ final Set<String> remoteVolumes = new TreeSet<>();
+ if (!((DockerConnection) connection).isLocal()) {
+ // if using remote daemon, we have to
+ // handle volume mounting differently.
+ // Instead we mount empty volumes and copy
+ // the host data over before starting.
+ if (additionalDirs != null) {
+ for (String dir : additionalDirs) {
+ IPath p = new Path(dir).removeTrailingSeparator();
+ remoteVolumes.add(p.toPortableString());
+ }
+ }
+ if (workingDir != null) {
+ IPath p = new Path(workingDir).removeTrailingSeparator();
+ remoteVolumes.add(p.toPortableString());
+ }
+ if (commandDir != null) {
+ IPath p = new Path(commandDir).removeTrailingSeparator();
+ remoteVolumes.add(p.toPortableString());
+ }
+ builder = builder.volumes(remoteVolumes);
+ } 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 Set<String> volumes = new TreeSet<>();
+ if (additionalDirs != null) {
+ for (String dir : additionalDirs) {
+ IPath p = new Path(dir).removeTrailingSeparator();
+ volumes.add(p.toPortableString() + ":" //$NON-NLS-1$
+ + p.toPortableString() + ":Z"); //$NON-NLS-1$
+ }
+ }
+ if (workingDir != null) {
+ IPath p = new Path(workingDir).removeTrailingSeparator();
+ volumes.add(p.toPortableString() + ":" + p.toPortableString() //$NON-NLS-1$
+ + ":Z"); //$NON-NLS-1$
+ }
+ if (commandDir != null) {
+ IPath p = new Path(commandDir).removeTrailingSeparator();
+ volumes.add(p.toPortableString() + ":" + p.toPortableString() //$NON-NLS-1$
+ + ":Z"); //$NON-NLS-1$
+ }
+ List<String> volumeList = new ArrayList<>(volumes);
+ hostBuilder = hostBuilder.binds(volumeList);
+ }
+
+ final DockerContainerConfig config = builder.build();
+
+ // add any port bindings if specified
+ if (portBindingsMap.size() > 0)
+ hostBuilder = hostBuilder.portBindings(portBindingsMap);
+
+ final IDockerHostConfig hostConfig = hostBuilder.build();
+
+ // create the container
+ String containerId = null;
+ try {
+ containerId = ((DockerConnection) connection)
+ .createContainer(config, hostConfig, null);
+ } catch (DockerException | InterruptedException e) {
+ errMsgHolder.setErrorMessage(e.getMessage());
+ return null;
+ }
+
+ final String id = containerId;
+ final IDockerConnection conn = connection;
+ Thread t = new Thread(() -> {
+ if (!((DockerConnection) conn).isLocal()) {
+ // if daemon is remote, we need to copy
+ // data over from the host.
+ if (!remoteVolumes.isEmpty()) {
+ CopyVolumesJob job = new CopyVolumesJob(remoteVolumes,
+ conn, id);
+ job.schedule();
+ try {
+ job.join();
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ if (job.getResult() != Status.OK_STATUS)
+ return;
+ }
+ }
+ try {
+ ((DockerConnection) conn).startContainer(id,
+ null);
+ } catch (DockerException | InterruptedException e) {
+ // ignore
+ }
+ });
+
+ t.start();
+
+ return new ContainerCommandProcess(connection, imageName, containerId,
+ keepContainer);
+ }
+
/**
* Clean up the container used for launching
*
@@ -628,12 +864,16 @@ public class ContainerLauncher {
* the entries to manipulate
* @return the concatenated key/values for each given variable entry
*/
- private List<String> toList(final Map<String, String> variables) {
+ private List<String> toList(
+ @SuppressWarnings("rawtypes") final Map variables) {
final List<String> result = new ArrayList<>();
if (variables != null) {
- for (Entry<String, String> entry : variables.entrySet()) {
- final String key = entry.getKey();
- final String value = entry.getValue();
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ Set<Map.Entry> entries = variables.entrySet();
+ for (@SuppressWarnings("rawtypes")
+ Map.Entry entry : entries) {
+ final String key = (String) entry.getKey();
+ final String value = (String) entry.getValue();
final String envEntry = key + "=" + value; //$NON-NLS-1$
result.add(envEntry);
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/IErrorMessageHolder.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/IErrorMessageHolder.java
new file mode 100644
index 0000000000..be6ed9502a
--- /dev/null
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/IErrorMessageHolder.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Red Hat Inc. and others.
+ * 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.docker.ui.launch;
+
+/**
+ * @since 3.0
+ */
+public interface IErrorMessageHolder {
+
+ public void setErrorMessage(String error);
+
+}
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/Messages.properties b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/Messages.properties
index 66f2c31cec..1c630cd0c6 100644
--- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/Messages.properties
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/Messages.properties
@@ -14,4 +14,8 @@ ContainerLaunchExited.title=Exited [{0}]: {1} running in image: {2}
ContainerLaunch.copyVolumesJob.title=Copying Volumes
ContainerLaunch.copyVolumesJob.desc=Copying volumes from host to <{0}>
ContainerLaunch.copyVolumesJob.task=Copying [{0}]
-ContainerLaunch.copyVolumesJob.error=Error copying volume [{0}] to <{1}> \ No newline at end of file
+ContainerLaunch.copyVolumesJob.error=Error copying volume [{0}] to <{1}>
+ContainerLaunch.noConnections.error=No connections available to launch a container
+ContainerLaunch.connectionNotFound.error=No connection with specified uri: <{0}> was found
+ContainerLaunch.noImages.error=No images are available from connection
+ContainerLaunch.imageNotFound.error=Specified image: <{0}> not found for connection \ No newline at end of file
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/ContainerCommandProcess.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/ContainerCommandProcess.java
new file mode 100644
index 0000000000..2f2a6b5351
--- /dev/null
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/ContainerCommandProcess.java
@@ -0,0 +1,128 @@
+package org.eclipse.linuxtools.internal.docker.ui.launch;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+import org.eclipse.linuxtools.docker.core.DockerException;
+import org.eclipse.linuxtools.docker.core.IDockerConnection;
+import org.eclipse.linuxtools.docker.core.IDockerContainerExit;
+import org.eclipse.linuxtools.docker.core.IDockerContainerInfo;
+import org.eclipse.linuxtools.docker.core.IDockerContainerState;
+
+public class ContainerCommandProcess extends Process {
+
+ private String containerId;
+ private IDockerConnection connection;
+ private String imageName;
+ private PipedInputStream stdout;
+ private PipedInputStream stderr;
+ private boolean keepContainer;
+ private Thread thread;
+
+ public ContainerCommandProcess(IDockerConnection connection,
+ String imageName, String containerId, boolean keepContainer) {
+ this.connection = connection;
+ this.imageName = imageName;
+ this.containerId = containerId;
+ this.stdout = new PipedInputStream();
+ this.stderr = new PipedInputStream();
+ this.keepContainer = keepContainer;
+ // Lambda Runnable
+ Runnable logContainer = () -> {
+ try (PipedOutputStream pipedStdout = new PipedOutputStream(stdout);
+ PipedOutputStream pipedStderr = new PipedOutputStream(
+ stderr)) {
+ connection.attachLog(containerId, pipedStdout, pipedStderr);
+ } catch (DockerException | InterruptedException | IOException e) {
+ // do nothing but close output streams
+ }
+ };
+
+ // start the thread
+ this.thread = new Thread(logContainer);
+ this.thread.start();
+ // Runnable watchContainer = () -> {
+ // try {
+ // IDockerContainerExit exit = connection
+ // .waitForContainer(containerId);
+ // } catch (DockerException | InterruptedException e) {
+ // // do nothing
+ // }
+ //
+ // try {
+ // System.out.println("watchcontainer finished");
+ // this.stdout.close();
+ // this.stderr.close();
+ // this.thread.interrupt();
+ // } catch (IOException e) {
+ // Activator.log(e);
+ // }
+ // };
+ // // kick off a thread to stop logging
+ // new Thread(watchContainer).start();
+ }
+
+ @Override
+ public void destroy() {
+ try {
+ this.stdout.close();
+ this.stderr.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ thread.interrupt();
+ }
+
+ @Override
+ public int exitValue() {
+ IDockerContainerInfo info = connection
+ .getContainerInfo(containerId);
+ if (info != null) {
+ IDockerContainerState state = info.state();
+ if (state != null) {
+ if (state.paused() || state.restarting() || state.running()) {
+ throw new IllegalThreadStateException(
+ LaunchMessages.getFormattedString(
+ "ContainerNotFinished.msg", containerId));
+ }
+ return state.exitCode();
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public InputStream getErrorStream() {
+ return stderr;
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ return stdout;
+ }
+
+ @Override
+ public OutputStream getOutputStream() {
+ return new ByteArrayOutputStream();
+ }
+
+ @Override
+ public int waitFor() throws InterruptedException {
+ try {
+ IDockerContainerExit exit = connection
+ .waitForContainer(containerId);
+ return exit.statusCode();
+ } catch (DockerException e) {
+ return -1;
+ }
+ }
+
+ public String getImage() {
+ return imageName;
+ }
+
+}
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/LaunchMessages.properties b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/LaunchMessages.properties
index 3a6824d7f5..f4f88797b2 100644
--- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/LaunchMessages.properties
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/LaunchMessages.properties
@@ -81,3 +81,7 @@ DockerComposeUpShortcutChooseLaunch.msg=Select the launch configuration to run '
LaunchShortcut.error=Error
LaunchShortcut.error.msg=The selection is not a valid resource
+
+ContainerNotFinished.msg=Container {0} not finished
+
+
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/ContainerInspectContentProvider.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/ContainerInspectContentProvider.java
index 0c3cb6aff1..6caef55ff6 100644
--- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/ContainerInspectContentProvider.java
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/ContainerInspectContentProvider.java
@@ -96,6 +96,7 @@ public class ContainerInspectContentProvider implements ITreeContentProvider {
new Object[]{"PortBindings", LabelProviderUtils.reduce(hostConfig.portBindings())}, //$NON-NLS-1$
new Object[]{"Privileged", hostConfig.privileged()}, //$NON-NLS-1$
new Object[]{"PublishAllPorts", hostConfig.publishAllPorts()}, //$NON-NLS-1$
+ new Object[] { "SecurityOpt", hostConfig.securityOpt() }, //$NON-NLS-1$
new Object[]{"VolumesFrom", LabelProviderUtils.reduce(hostConfig.volumesFrom())}, //$NON-NLS-1$
};
} else if(propertyValue instanceof IDockerContainerConfig) {

Back to the top