diff options
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) { |