diff options
101 files changed, 3866 insertions, 732 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 c811e69632..6dfea14c6f 100644 --- a/containers/org.eclipse.linuxtools.docker.core/META-INF/MANIFEST.MF +++ b/containers/org.eclipse.linuxtools.docker.core/META-INF/MANIFEST.MF @@ -18,7 +18,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="3.12.0", org.glassfish.jersey.core.jersey-client;bundle-version="2.14.0", org.glassfish.jersey.media.jersey-media-json-jackson;bundle-version="2.14.0", org.glassfish.jersey.core.jersey-common;bundle-version="2.14.0", - org.eclipse.tm.terminal.view.core;bundle-version="4.0.0" + org.eclipse.tm.terminal.view.core;bundle-version="4.0.0", + org.eclipse.debug.core;bundle-version="3.10.100" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.linuxtools.docker.core, diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/Activator.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/Activator.java index fe71cc209c..548c8df9bc 100644 --- a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/Activator.java +++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/Activator.java @@ -49,7 +49,15 @@ public class Activator extends Plugin { } public static void log(IStatus status) { - Activator.getDefault().getLog().log(status); + if (Activator.getDefault() != null + && Activator.getDefault().getLog() != null) { + Activator.getDefault().getLog().log(status); + } + } + + public static void logWarningMessage(final String message) { + log(new Status(IStatus.WARNING, PLUGIN_ID, IStatus.WARNING, message, + null)); } public static void logErrorMessage(final String message) { diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/DockerConnectionManager.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/DockerConnectionManager.java index 8ea9742cee..40d23b3092 100644 --- a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/DockerConnectionManager.java +++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/DockerConnectionManager.java @@ -10,9 +10,9 @@ *******************************************************************************/ package org.eclipse.linuxtools.docker.core; -import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import org.eclipse.core.runtime.ListenerList; import org.eclipse.linuxtools.docker.core.IDockerConnectionSettings.BindingType; @@ -91,19 +91,81 @@ public class DockerConnectionManager { this.connectionStorageManager.saveConnections(this.connections); } - public IDockerConnection[] getConnections() { + /** + * @return an unmodifiable and non-null array of {@link IDockerConnection} + */ + public IDockerConnection[] getConnections() { + if (this.connections == null) { + return new IDockerConnection[0]; + } return connections.toArray(new IDockerConnection[connections.size()]); } /** + * @return an unmodifiable and non-null list of {@link IDockerConnection} + */ + public List<IDockerConnection> getAllConnections() { + if (this.connections == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(this.connections); + } + + /** + * @return the first {@link IDockerConnection} or <code>null</code> if none + * exists yet. + */ + public IDockerConnection getFirstConnection() { + if (!hasConnections()) { + return null; + } + return this.connections.get(0); + } + + /** + * @return <code>true</code> if there is at least one + * {@link IDockerConnection} in this + * {@link DockerConnectionManager}, <code>false</code> otherwise. + */ + public boolean hasConnections() { + return connections != null && !connections.isEmpty(); + } + + /** + * Finds the {@link IDockerConnection} from the given {@code connectionName} + * + * @param connectionName + * the name of the connection to find + * @return the {@link IDockerConnection} or <code>null</code> if none + * matched. + */ + public IDockerConnection getConnectionByName(final String connectionName) { + return this.connections.stream().filter( + connection -> connection.getName().equals(connectionName)) + .findFirst().orElse(null); + } + + /** + * Finds the {@link IDockerConnection} from the given {@code connectionUri} + * + * @param connectionUri + * the URI of the connection to find + * @return the {@link IDockerConnection} or <code>null</code> if none + * matched. + */ + public IDockerConnection getConnectionByUri(String connectionUri) { + return DockerConnectionManager.getInstance().getAllConnections() + .stream() + .filter(c -> c.getUri().equals(connectionUri)).findFirst() + .orElse(null); + } + + /** * @return an immutable {@link List} of the {@link IDockerConnection} names */ public List<String> getConnectionNames() { - final List<String> connectionNames = new ArrayList<>(); - for (IDockerConnection connection : this.connections) { - connectionNames.add(connection.getName()); - } - return Collections.unmodifiableList(connectionNames); + return Collections.unmodifiableList(getAllConnections().stream() + .map(c -> c.getName()).collect(Collectors.toList())); } public IDockerConnection findConnection(final String name) { diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/Messages.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/Messages.java index 0528c4ac12..75cc1d6b32 100644 --- a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/Messages.java +++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/Messages.java @@ -39,6 +39,7 @@ public class Messages extends NLS { public static String Docker_Connection_Timeout; public static String Docker_Machine_Process_Error; public static String Docker_Machine_Process_Exception; + public static String Docker_Compose_Command_Not_Found; static { // Initialize resource bundle. diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/Messages.properties b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/Messages.properties index f5a6c7b47c..b71ebec43b 100644 --- a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/Messages.properties +++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/docker/core/Messages.properties @@ -32,4 +32,5 @@ Registry_Version_Mismatch=Target Docker registry located at {0} does not support Docker_Machine_Command_Not_Found=The '''docker-machine''' command could not be located in {0} Docker_Connection_Timeout=Closing the connection after a timeout exception Docker_Machine_Process_Error=Failed to execute command ''{0}'' (exit code={1}): {2} -Docker_Machine_Process_Exception=Failed to execute command ''{0}''
\ No newline at end of file +Docker_Machine_Process_Exception=Failed to execute command ''{0}'' +Docker_Compose_Command_Not_Found=The '''docker-compose''' command could not be located in {0} diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerCompose.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerCompose.java new file mode 100644 index 0000000000..739897e200 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerCompose.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2016 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.core; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.linuxtools.docker.core.DockerException; +import org.eclipse.linuxtools.docker.core.IDockerConnection; + +/** + * A utility class to run the {@code docker-compose} command line. + */ +public class DockerCompose { + + private static DockerCompose instance = new DockerCompose(); + + private ProcessLauncher processLauncher = new ProcessLauncher(); + + public static DockerCompose getInstance() { + return instance; + } + + private DockerCompose() { + + } + + /** + * Replace the default {@link ProcessLauncher} with another instance. Used + * to testing by injecting a mock instance here. + * + * @param processLauncher + * the new {@link ProcessLauncher}. + */ + public void setProcessLauncher(ProcessLauncher processLauncher) { + this.processLauncher = processLauncher; + } + + /** + * Checks that the given {@code dockerMachineInstallDir} contains the + * {@code docker-compose} command + * + * @param dockerComposeInstallDir + * the directory to check + * @return <code>true</code> if the system-specific command was found, + * <code>false</code> otherwise. + */ + public boolean checkPathToDockerCompose( + final String dockerComposeInstallDir) { + return this.processLauncher.checkPathToCommand(dockerComposeInstallDir, + getDockerComposeCommandName()); + } + + /** + * Runs the {@code docker-compose up} command from the specified + * {@code baseDir} + * + * @param dockerComposeInstallDir + * the directory in which the {@code docker-compose} command is + * located + * @param baseDir + * the base directory in which the {@code docker-compose} command + * should be ran. This directory should contain a + * {@code docker-compose.yml} file. + * @throws DockerException + * if something wrong happened + */ + public Process up(final IDockerConnection connection, + final String dockerComposeInstallDir, final String baseDir) + throws DockerException { + return this.processLauncher.processBuilder(dockerComposeInstallDir, + getDockerComposeCommandName(), + getArguments(connection, "up")) //$NON-NLS-1$ + .workingDir(baseDir).start(); + } + + public Process stop(final IDockerConnection connection, + final String dockerComposeInstallDir, final String baseDir) + throws DockerException { + return this.processLauncher + .processBuilder(dockerComposeInstallDir, + getDockerComposeCommandName(), + getArguments(connection, "stop")) //$NON-NLS-1$ + .workingDir(baseDir).start(); + } + + private static String[] getArguments(final IDockerConnection connection, + final String commandName) { + switch (connection.getSettings().getType()) { + case UNIX_SOCKET_CONNECTION: + return new String[] { commandName }; + case TCP_CONNECTION: + final TCPConnectionSettings connectionSettings = (TCPConnectionSettings) connection + .getSettings(); + // include the flags to connect to the host + final List<String> args = new ArrayList<>(); + args.add("-H"); + args.add(connectionSettings.getHost()); + if (connectionSettings.isTlsVerify() + && connectionSettings.getPathToCertificates() != null) { + args.add("--tlsverify"); //$NON-NLS-1$ + args.add("--tlscacert"); //$NON-NLS-1$ + args.add(getFilePath(connectionSettings.getPathToCertificates(), + "ca.pem")); //$NON-NLS-1$ + args.add("--tlscert"); //$NON-NLS-1$ + args.add(getFilePath(connectionSettings.getPathToCertificates(), + "cert.pem")); //$NON-NLS-1$ + args.add("--tlskey"); //$NON-NLS-1$ + args.add(getFilePath(connectionSettings.getPathToCertificates(), + "key.pem")); //$NON-NLS-1$ + + } + args.add(commandName); + + return args.toArray(new String[0]); + } + return null; + } + + private static String getFilePath(final String pathToCertificates, + final String certificateFileName) { + if (pathToCertificates.endsWith(File.separator)) { + return pathToCertificates + certificateFileName; + } + return pathToCertificates + File.separator + certificateFileName; + } + + public static String getDockerComposeCommandName() { + if (SystemUtils.isWindows()) { + return "docker-compose.exe"; //$NON-NLS-1$ + } + return "docker-compose"; //$NON-NLS-1$ + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerMachine.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerMachine.java index 359f4f8fba..0f077dc192 100644 --- a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerMachine.java +++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerMachine.java @@ -10,23 +10,7 @@ *******************************************************************************/ package org.eclipse.linuxtools.internal.docker.core; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.linuxtools.docker.core.Activator; -import org.eclipse.linuxtools.docker.core.Messages; -import org.eclipse.osgi.util.NLS; +import org.eclipse.linuxtools.docker.core.DockerException; /** * Utility class to discover Docker machines using the 'docker-machine' command @@ -34,15 +18,33 @@ import org.eclipse.osgi.util.NLS; */ public class DockerMachine { - private static Object lock = new Object(); + /** + * Checks that the given {@code dockerMachineInstallDir} contains the + * {@code docker-machine} command + * + * @param dockerMachineInstallDir + * the directory to check + * @return <code>true</code> if the system-specific command was found, + * <code>false</code> otherwise. + */ + public static boolean checkPathToDockerMachine( + final String dockerMachineInstallDir) { + return ProcessUtils.checkPathToCommand(dockerMachineInstallDir, + getDockerMachineExecutableName()); + } /** * @param pathToDockerMachine * the path to 'docker-machine' stored in the preferences * @return the names of the existing Docker Machines + * @throws DockerException + * if something went wrong */ - public static String[] getNames(final String pathToDockerMachine) { - return execute(pathToDockerMachine, new String[] { "ls", "-q" }); //$NON-NLS-1$ //$NON-NLS-2$ + public static String[] getNames(final String pathToDockerMachine) + throws DockerException { + return ProcessUtils.processBuilder(pathToDockerMachine, + getDockerMachineExecutableName(), new String[] { "ls", "-q" }) //$NON-NLS-1$ //$NON-NLS-2$ + .start(); } /** @@ -54,13 +56,17 @@ public class DockerMachine { * the installation directory for the underlying VM driver used * by Docker Machine * @return the host URI to use to connect to it + * @throws DockerException + * if something went wrong */ public static String getHost(final String name, final String dockerMachineInstallDir, - final String vmDriverInstallDir) { - final String[] res = execute(dockerMachineInstallDir, - new String[] { "url", name }, //$NON-NLS-1$ - vmDriverInstallDir); + final String vmDriverInstallDir) throws DockerException { + final String[] res = ProcessUtils + .processBuilder(dockerMachineInstallDir, + getDockerMachineExecutableName(), + new String[] { "url", name }) //$NON-NLS-1$ + .extraPath(vmDriverInstallDir).start(); return res.length == 1 ? res[0] : null; } @@ -73,12 +79,16 @@ public class DockerMachine { * the installation directory for the underlying VM driver used * by Docker Machine * @return the path to the directory containing the certificates + * @throws DockerException + * if something went wrong */ public static String getCertPath(final String name, - final String pathToDockerMachine, final String vmDriverInstallDir) { - final String[] envVariables = execute(pathToDockerMachine, - new String[] { "env", name }, //$NON-NLS-1$ - vmDriverInstallDir); + final String pathToDockerMachine, final String vmDriverInstallDir) + throws DockerException { + final String[] envVariables = ProcessUtils.processBuilder(pathToDockerMachine, + getDockerMachineExecutableName(), + new String[] { "env", name }) //$NON-NLS-1$ + .extraPath(vmDriverInstallDir).start(); for (String envVariable : envVariables) { if (envVariable.contains("DOCKER_CERT_PATH")) { //$NON-NLS-1$ // DOCKER_CERT_PATH="/path/to/cert-folder" @@ -89,108 +99,6 @@ public class DockerMachine { } /** - * Executes the command given in parameter - * - * @param args - * command arguments - * @return the lines read in the {@link Process}' {@link InputStream} or an - * empty array if the {@code docker-machine} command could not be - * found in the {@code PATH}. - */ - private static String[] execute(final String dockerMachineInstallDir, - final String[] args, final String... extraPaths) { - synchronized (lock) { - // check that the 'docker-machine' can be found in the given - // 'dockerMachineInstallDir' - final boolean dockerMachineCommandExists = checkPathToDockerMachine( - dockerMachineInstallDir); - if (!dockerMachineCommandExists) { - // log a warning and exit - Activator.log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, - NLS.bind(Messages.Docker_Machine_Command_Not_Found, - dockerMachineInstallDir))); - return new String[0]; - } - final String[] command = new String[args.length + 1]; - command[0] = Paths.get(dockerMachineInstallDir, - getDockerMachineExecutableName()).toString(); - System.arraycopy(args, 0, command, 1, args.length); - try { - final ProcessBuilder processBuilder = new ProcessBuilder( - command); - final Map<String, String> environment = processBuilder - .environment(); - final StringBuilder path = new StringBuilder(); - for (String extraPath : extraPaths) { - path.append(File.pathSeparator).append(extraPath); - } - final String newEnvPath = environment.get("PATH") //$NON-NLS-1$ - + path.toString(); - environment.put("PATH", newEnvPath); //$NON-NLS-1$ - - final Process p = processBuilder.start(); - p.waitFor(); - if (p.exitValue() == 0) { - final List<String> result = new ArrayList<>(); - try (final InputStream inputStream = p.getInputStream(); - final BufferedReader buff = new BufferedReader( - new InputStreamReader(inputStream))) { - String line; - while ((line = buff.readLine()) != null) { - result.add(line); - } - } - return result.toArray(new String[0]); - } else { - final StringBuffer errorMessage = new StringBuffer(); - try (final InputStream errorStream = p.getErrorStream(); - final BufferedReader buff = new BufferedReader( - new InputStreamReader(errorStream))) { - String line; - while ((line = buff.readLine()) != null) { - errorMessage.append(line).append('\n'); // $NON-NLS-1$ - } - } - Activator.log(new Status(IStatus.WARNING, - Activator.PLUGIN_ID, - NLS.bind(Messages.Docker_Machine_Process_Error, - new Object[] { - Stream.of(command).collect( - Collectors.joining(" ")), - p.exitValue(), - errorMessage.toString() }))); - } - } catch (IOException | InterruptedException e) { - Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, - NLS.bind(Messages.Docker_Machine_Process_Exception, - Stream.of(command) - .collect(Collectors.joining(" ")), - e))); - } - return new String[0]; - } - } - - /** - * Checks that the 'docker-machine' command exists in the given {@code path} - * - * @param path - * to path to use to look for the 'docker-machine' command - * @return <code>true</code> if the command was found, <code>false</code> - * otherwise. - */ - public static boolean checkPathToDockerMachine(final String path) { - for (String pathFragment : path.split(File.pathSeparator)) { - final File pathToDockerMachine = new File(pathFragment, - getDockerMachineExecutableName()); - if (pathToDockerMachine.exists()) { - return true; - } - } - return false; - } - - /** * @return the name of the Docker Machine executable, depending on the * current operating system. */ diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessLauncher.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessLauncher.java new file mode 100644 index 0000000000..3dafcd9c86 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessLauncher.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2016 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.core; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.linuxtools.docker.core.DockerException; + +/** + * A utility class to run Java {@link Process} such as {@code docker-machine} or + * {@code docker-compose}. + */ +public class ProcessLauncher { + + public static final String COMMAND_LINE = "org.eclipse.linuxtools.docker.compose.commandLine"; + + /** + * Checks that the given {@code cmdName} exists in the given {@code path} + * + * @param path + * the system {@code PATH} to use to look for the command + * @param cmdName + * the name of the command in the given {@code cmdDir} + * @return <code>true</code> if the command was found, <code>false</code> + * otherwise. + */ + public boolean checkPathToCommand(final String path, final String cmdName) { + return Stream.of(path.split(File.pathSeparator)) + .map(pathFragment -> new File(pathFragment, cmdName)) + .anyMatch(fullPath -> fullPath.exists()); + } + + /** + * Entry method to run a command. + * + * @param baseCmdDir + * the base directory containing the command to run + * @param cmdName + * the name of the command to run + * @throws DockerException + * if the {@code baseCmdDir} did not contain the specific + * {@code cmdName} + */ + public FluentProcessBuilder processBuilder(final String baseCmdDir, + final String cmdName, final String[] args) throws DockerException { + return new FluentProcessBuilder(baseCmdDir, cmdName, args); + } + + public static class FluentProcessBuilder { + + /** the {@link ProcessBuilder} to use to run the command. */ + private final ProcessBuilder processBuilder; + + /** + * Constructor. + * + * @param baseCmdDir + * the base directory containing the command to run + * @param cmdName + * the name of the command to run + * @throws DockerException + * if the {@code baseCmdDir} did not contain the specific + * {@code cmdName} + */ + private FluentProcessBuilder(final String baseCmdDir, + final String cmdName, final String[] args) + throws DockerException { + // check that the 'cmdName' can be found in the given + // 'baseCmdDir' + final boolean commandExists = new ProcessLauncher() + .checkPathToCommand(baseCmdDir, cmdName); + if (!commandExists) { + throw new DockerException( + ProcessMessages.getFormattedString("Command_Not_Found", //$NON-NLS-1$ + baseCmdDir, cmdName)); + } + final String[] command = new String[args.length + 1]; + command[0] = Paths.get(baseCmdDir, cmdName).toString(); + System.arraycopy(args, 0, command, 1, args.length); + this.processBuilder = new ProcessBuilder(command); + } + + public FluentProcessBuilder extraPath(final String... extraPaths) { + final Map<String, String> environment = processBuilder + .environment(); + final StringBuilder path = new StringBuilder(); + for (String extraPath : extraPaths) { + path.append(File.pathSeparator).append(extraPath); + } + final String newEnvPath = environment.get("PATH") //$NON-NLS-1$ + + path.toString(); + environment.put("PATH", newEnvPath); //$NON-NLS-1$ + return this; + } + + public FluentProcessBuilder workingDir(final String workingDir) { + this.processBuilder.directory(new File(workingDir)); + return this; + } + + public FluentProcessBuilder redirectErrorStream( + boolean redirectErrorStream) { + this.processBuilder.redirectErrorStream(redirectErrorStream); + return this; + } + + public String getCommand() { + return this.processBuilder.command().stream() + .collect(Collectors.joining(" ")); + } + + public Process start() throws DockerException { + try { + return this.processBuilder.start(); + } catch (IOException e) { + throw new DockerException(ProcessMessages + .getFormattedString("Process_Start_Exception", //$NON-NLS-1$ + processBuilder.command().stream() + .collect(Collectors.joining(" ")), + e.getMessage()), + e); + } + } + } + +}
\ No newline at end of file diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessLogConsumer.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessLogConsumer.java new file mode 100644 index 0000000000..e77945ef9f --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessLogConsumer.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2016 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.core; + +import java.util.function.Consumer; + +/** + * A Log consumer that has a {@code ready} flag to delay processing. + */ +public class ProcessLogConsumer { + + private final Consumer<String> consumer; + + private boolean ready = false; + + public ProcessLogConsumer(final Consumer<String> consumer) { + this.consumer = consumer; + } + + public boolean isReady() { + return this.ready; + } + + public void setReady(boolean ready) { + this.ready = ready; + } + + public void process(final String log) { + consumer.accept(log); + } +} diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessMessages.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessMessages.java new file mode 100644 index 0000000000..d5847e40a5 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessMessages.java @@ -0,0 +1,31 @@ +package org.eclipse.linuxtools.internal.docker.core; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class ProcessMessages { + + private static final String BUNDLE_NAME = ProcessMessages.class.getName(); + + public static String getString(String key) { + try { + return ResourceBundle.getBundle(BUNDLE_NAME).getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } catch (NullPointerException e) { + return '#' + key + '#'; + } + } + + public static String getFormattedString(final String key, + final Object arg) { + return MessageFormat.format(getString(key), new Object[] { arg }); + } + + public static String getFormattedString(final String key, + final Object... args) { + return MessageFormat.format(getString(key), args); + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessMessages.properties b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessMessages.properties new file mode 100644 index 0000000000..2470031b3e --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessMessages.properties @@ -0,0 +1,14 @@ +################################################################################# +# Copyright (c) 2016 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 +################################################################################# +Command_Not_Found=The ''{1}'' command could not be located in ''{0}'' +Process_Error=Failed to execute command ''{0}'' (exit code={1}): {2} +Process_Start_Exception=Failed to execute command ''{0}'': {1} +Process_Monitor_Exception=Failed to monitor process diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessUtils.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessUtils.java new file mode 100644 index 0000000000..7d9cad7d43 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/ProcessUtils.java @@ -0,0 +1,225 @@ +/******************************************************************************* + * Copyright (c) 2016 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.core; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.linuxtools.docker.core.Activator; +import org.eclipse.linuxtools.docker.core.DockerException; + +/** + * A utility class to run Java {@link Process}es such as {@code docker-machine} + * or {@code docker-compose}. + */ +@Deprecated +public class ProcessUtils { + + /** + * Checks that the given {@code cmdName} exists in the given {@code path} + * + * @param path + * the system {@code PATH} to use to look for the command + * @param cmdName + * the name of the command in the given {@code cmdDir} + * @return <code>true</code> if the command was found, <code>false</code> + * otherwise. + */ + public static boolean checkPathToCommand(final String path, + final String cmdName) { + return Stream.of(path.split(File.pathSeparator)) + .map(pathFragment -> new File(pathFragment, cmdName)) + .anyMatch(fullPath -> fullPath.exists()); + } + + /** + * Entry method to run a command. + * + * @param baseCmdDir + * the base directory containing the command to run + * @param cmdName + * the name of the command to run + * @throws DockerException + * if the {@code baseCmdDir} did not contain the specific + * {@code cmdName} + */ + public static FluentProcessBuilder processBuilder(final String baseCmdDir, + final String cmdName, final String... args) throws DockerException { + return new FluentProcessBuilder(baseCmdDir, cmdName, args); + } + + public static class FluentProcessBuilder { + + /** the {@link ProcessBuilder} to use to run the command. */ + private final ProcessBuilder processBuilder; + + /** + * Constructor. + * + * @param baseCmdDir + * the base directory containing the command to run + * @param cmdName + * the name of the command to run + * @throws DockerException + * if the {@code baseCmdDir} did not contain the specific + * {@code cmdName} + */ + private FluentProcessBuilder(final String baseCmdDir, + final String cmdName, final String[] args) + throws DockerException { + // check that the 'cmdName' can be found in the given + // 'baseCmdDir' + final boolean commandExists = checkPathToCommand(baseCmdDir, + cmdName); + if (!commandExists) { + throw new DockerException( + ProcessMessages.getFormattedString("Command_Not_Found", //$NON-NLS-1$ + baseCmdDir, cmdName)); + } + final String[] command = new String[args.length + 1]; + command[0] = Paths.get(baseCmdDir, cmdName).toString(); + System.arraycopy(args, 0, command, 1, args.length); + this.processBuilder = new ProcessBuilder(command); + } + + public FluentProcessBuilder extraPath(final String... extraPaths) { + final Map<String, String> environment = processBuilder + .environment(); + final StringBuilder path = new StringBuilder(); + for (String extraPath : extraPaths) { + path.append(File.pathSeparator).append(extraPath); + } + final String newEnvPath = environment.get("PATH") //$NON-NLS-1$ + + path.toString(); + environment.put("PATH", newEnvPath); //$NON-NLS-1$ + return this; + } + + public FluentProcessBuilder workingDir(final String workingDir) { + this.processBuilder.directory(new File(workingDir)); + return this; + } + + public AsyncProcessRunner outputListener( + final Consumer<String> outputConsumer) { + return new AsyncProcessRunner(this.processBuilder, outputConsumer); + } + + public String[] start() { + try { + final Process p = processBuilder.start(); + p.waitFor(); + if (p.exitValue() == 0) { + final List<String> result = new ArrayList<>(); + try (final InputStream inputStream = p.getInputStream(); + final BufferedReader buff = new BufferedReader( + new InputStreamReader(inputStream))) { + String line; + while ((line = buff.readLine()) != null) { + result.add(line); + } + } + return result.toArray(new String[0]); + } else { + final StringBuffer errorMessage = new StringBuffer(); + try (final InputStream errorStream = p.getErrorStream(); + final BufferedReader buff = new BufferedReader( + new InputStreamReader(errorStream))) { + String line; + while ((line = buff.readLine()) != null) { + errorMessage.append(line).append('\n'); // $NON-NLS-1$ + } + } + Activator.log(new Status(IStatus.WARNING, + Activator.PLUGIN_ID, + ProcessMessages.getFormattedString("Process_Error", //$NON-NLS-1$ + this.processBuilder.command().stream() + .collect(Collectors.joining(" ")), + p.exitValue(), errorMessage.toString()))); + } + } catch (IOException | InterruptedException e) { + Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + ProcessMessages.getFormattedString("Process_Exception", //$NON-NLS-1$ + this.processBuilder.command().stream() + .collect(Collectors.joining(" ")), + e.getMessage()), + e)); + } + return new String[0]; + } + } + + /** + * Process executor + */ + public static class AsyncProcessRunner { + + private final ProcessBuilder processBuilder; + + private final Consumer<String> outputConsumer; + + public AsyncProcessRunner(final ProcessBuilder processBuilder, + final Consumer<String> outputConsumer) { + this.processBuilder = processBuilder; + this.outputConsumer = outputConsumer; + } + + /** + * Executes the {@link Process} and sends output lines from the standard + * {@code outputStream} and the {@code errorStream} to the + * {@code outputConsumer} provided in the constructor. + * + * @return the {@link Process} + * @throws DockerException + * if something wrong happened when the process was executed + */ + public Process start() throws DockerException { + try { + // we need to redirect the error stream into the standard output + // stream + processBuilder.redirectErrorStream(true); + final Process process = processBuilder.start(); + try (final InputStream inputStream = process.getInputStream(); + final BufferedReader buff = new BufferedReader( + new InputStreamReader(inputStream))) { + String line; + while ((line = buff.readLine()) != null) { + this.outputConsumer.accept(line + '\n'); // $NON-NLS-1$ + } + } + + return process; + } catch (IOException e) { + throw new DockerException( + ProcessMessages.getFormattedString("Process_Exception", //$NON-NLS-1$ + this.processBuilder.command().stream() + .collect(Collectors.joining(" ")), + e.getMessage()), + e); + } + } + + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/META-INF/MANIFEST.MF b/containers/org.eclipse.linuxtools.docker.ui.tests/META-INF/MANIFEST.MF index 92a3536bd8..0a239858fc 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/META-INF/MANIFEST.MF +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/META-INF/MANIFEST.MF @@ -29,6 +29,7 @@ Require-Bundle: org.eclipse.linuxtools.docker.ui;bundle-version="1.0.0", org.slf4j.api;bundle-version="1.7.2", org.glassfish.jersey.bundles.repackaged.jersey-guava;bundle-version="2.14.0", org.eclipse.ui.ide, - org.eclipse.debug.ui + org.eclipse.debug.ui, + org.eclipse.ui.console;bundle-version="3.6.100" Bundle-ClassPath: . Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/projects/foo/docker-compose.yml b/containers/org.eclipse.linuxtools.docker.ui.tests/projects/foo/docker-compose.yml new file mode 100644 index 0000000000..ae16bf420f --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/projects/foo/docker-compose.yml @@ -0,0 +1,4 @@ +version: '2' +services: + redis: + image: redis diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtilsSWTBotTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtilsSWTBotTest.java index c3b578d5e4..b744035f0b 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtilsSWTBotTest.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtilsSWTBotTest.java @@ -36,7 +36,7 @@ import org.junit.Test; import com.spotify.docker.client.DockerClient; /** - * + * */ public class CommandUtilsSWTBotTest { @@ -45,11 +45,12 @@ public class CommandUtilsSWTBotTest { private DockerExplorerView dockerExplorerView; @ClassRule - public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule(); - + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.DOCKER_PERSPECTIVE_ID); + @Rule public ClearConnectionManagerRule clearConnectionManager = new ClearConnectionManagerRule(); - + @Before public void lookupDockerExplorerView() { SWTUtils.asyncExec(() -> { @@ -61,7 +62,7 @@ public class CommandUtilsSWTBotTest { Assert.fail("Failed to open Docker Explorer view: " + e.getMessage()); } }); - dockerExplorerViewBot = bot.viewById("org.eclipse.linuxtools.docker.ui.dockerExplorerView"); + dockerExplorerViewBot = SWTUtils.getSWTBotView(bot, "org.eclipse.linuxtools.docker.ui.dockerExplorerView"); dockerExplorerView = (DockerExplorerView) (dockerExplorerViewBot.getViewReference().getView(true)); bot.views().stream() .filter(v -> v.getReference().getId().equals("org.eclipse.linuxtools.docker.ui.dockerContainersView") @@ -114,7 +115,7 @@ public class CommandUtilsSWTBotTest { // then current connection should be found Assertions.assertThat(CommandUtils.getCurrentConnection(dockerExplorerView)).isEqualTo(dockerConnection); } - + @Test public void shouldRetrieveConnectionFromSelectedContainerLink() { // given @@ -131,7 +132,7 @@ public class CommandUtilsSWTBotTest { // then current connection should be found Assertions.assertThat(CommandUtils.getCurrentConnection(dockerExplorerView)).isEqualTo(dockerConnection); } - + @Test public void shouldRetrieveConnectionFromSelectedContainerVolumesCategory() { // given @@ -181,7 +182,7 @@ public class CommandUtilsSWTBotTest { // then current connection should be found Assertions.assertThat(CommandUtils.getCurrentConnection(dockerExplorerView)).isEqualTo(dockerConnection); } - + @Test public void shouldRetrieveConnectionFromSelectedContainerPort() { // given @@ -198,7 +199,7 @@ public class CommandUtilsSWTBotTest { // then current connection should be found Assertions.assertThat(CommandUtils.getCurrentConnection(dockerExplorerView)).isEqualTo(dockerConnection); } - + @Test public void shouldRetrieveConnectionFromSelectedImagesCategory() { // given @@ -212,7 +213,7 @@ public class CommandUtilsSWTBotTest { // then current connection should be found Assertions.assertThat(CommandUtils.getCurrentConnection(dockerExplorerView)).isEqualTo(dockerConnection); } - + @Test public void shouldRetrieveConnectionFromSelectedImage() { // given diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/consoles/StyledConsoleLogsTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/consoles/StyledConsoleLogsTest.java new file mode 100644 index 0000000000..6f9b1e06c5 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/consoles/StyledConsoleLogsTest.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2016 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.consoles; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.linuxtools.internal.docker.ui.consoles.StyledTextBuilder.ESC; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.viewers.StyledString; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.SWTUtils; +import org.eclipse.swt.custom.StyledText; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +/** + * Testing that the colored output are properly generated into + * {@link StyledText}. + */ +@RunWith(Parameterized.class) +public class StyledConsoleLogsTest { + + private static class ParametersBuilder { + + private final List<Object[]> parameters = new ArrayList<>(); + + ParametersBuilder add(final String lineText, final StyledString expectation) { + parameters.add(new Object[] { lineText, expectation }); + return this; + } + + Object[][] build() { + return parameters.toArray(new Object[0][0]); + } + } + + @Parameters() // don't use name = "{0}" to display the unit test name, as it + // breaks the build on Hudson because of an invalid XML + // character + public static Object[][] getData() { + final ParametersBuilder parametersBuilder = new ParametersBuilder(); + parametersBuilder.add(ESC + "[33mcontainerid|" + ESC + "[0mstandard_content", + new StyledString().append("containerid|", StylerBuilder.styler(33)).append("standard_content", + StylerBuilder.defaultStyler())); + parametersBuilder.add("prefix_content" + ESC + "[33mcontainerid|" + ESC + "[0mstandard_content", + new StyledString().append("prefix_content", StylerBuilder.defaultStyler()) + .append("containerid|", StylerBuilder.styler(33)) + .append("standard_content", StylerBuilder.defaultStyler())); + parametersBuilder.add(ESC + "[33merror_content", + new StyledString().append("error_content", StylerBuilder.styler(33))); + parametersBuilder.add(ESC + "[33mcontainerid|" + ESC + "[0mstandard_content1" + ESC + "[34mcolorized_content" + + ESC + "[0mstandard_content2", + new StyledString().append("containerid|", StylerBuilder.styler(33)) + .append("standard_content1", StylerBuilder.defaultStyler()) + .append("colorized_content", StylerBuilder.styler(34)) + .append("standard_content2", StylerBuilder.defaultStyler())); + parametersBuilder.add( + ESC + "[33mcontainerid|" + ESC + "[0mstandard_content1" + ESC + "[34mcolorized_content" + ESC + + "[0mstandard_content2" + ESC + "[35mcolorized_content2", + new StyledString().append("containerid|", StylerBuilder.styler(33)) + .append("standard_content1", StylerBuilder.defaultStyler()) + .append("colorized_content", StylerBuilder.styler(34)) + .append("standard_content2", StylerBuilder.defaultStyler()) + .append("colorized_content2", StylerBuilder.styler(35))); + parametersBuilder.add(ESC + "[0m" + ESC + "[33merror_content", + new StyledString().append("", StylerBuilder.defaultStyler()).append("error_content", + StylerBuilder.styler(33))); + parametersBuilder.add(ESC + "[0m", new StyledString().append("", StylerBuilder.defaultStyler())); + return parametersBuilder.build(); + } + + @Parameter(0) + public String lineText; + + @Parameter(1) + public StyledString expectedStyledString; + + @Test + public void shouldGenerateStyledString() { + // given + // when + final StyledString result = StyledTextBuilder.parse(lineText); + // then + assertThat(SWTUtils.syncExec(() -> result.getStyleRanges())) + .isEqualTo(SWTUtils.syncExec(() -> expectedStyledString.getStyleRanges())); + assertThat(result.getString()).isEqualTo(expectedStyledString.getString()); + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/consoles/package-info.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/consoles/package-info.java new file mode 100644 index 0000000000..47bff1ec63 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/consoles/package-info.java @@ -0,0 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2016 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.consoles;
\ No newline at end of file diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/launch/BuildDockerImageShortcutSWTBotTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/launch/BuildDockerImageShortcutSWTBotTest.java index a866880a58..010bf7a965 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/launch/BuildDockerImageShortcutSWTBotTest.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/launch/BuildDockerImageShortcutSWTBotTest.java @@ -20,7 +20,6 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.linuxtools.docker.core.DockerConnectionManager; import org.eclipse.linuxtools.internal.docker.core.DockerConnection; -import org.eclipse.linuxtools.internal.docker.ui.commands.CommandMessages; import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerClientFactory; import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerConnectionFactory; import org.eclipse.linuxtools.internal.docker.ui.testutils.ProjectInitializationRule; @@ -29,14 +28,13 @@ import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ClearConnectionMa import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ClearLaunchConfigurationsRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWelcomePageRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.DockerConnectionManagerUtils; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ProjectExplorerViewRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.SWTUtils; import org.eclipse.linuxtools.internal.docker.ui.wizards.WizardMessages; import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; -import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu; import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; -import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; @@ -65,27 +63,25 @@ public class BuildDockerImageShortcutSWTBotTest { public ClearLaunchConfigurationsRule clearLaunchConfig = new ClearLaunchConfigurationsRule( IBuildDockerImageLaunchConfigurationConstants.CONFIG_TYPE_ID); - private SWTWorkbenchBot bot = new SWTWorkbenchBot(); - private SWTBotView projectExplorerBotView; + @Rule + public ProjectExplorerViewRule projectExplorerViewRule = new ProjectExplorerViewRule(); - @Before - public void setup() { - this.projectExplorerBotView = bot.viewById("org.eclipse.ui.navigator.ProjectExplorer"); - this.projectExplorerBotView.setFocus(); - } + private SWTWorkbenchBot bot = new SWTWorkbenchBot(); /** * @return the {@link SWTBotMenu} for the "Run as > Docker Image Build" * shortcut */ private SWTBotMenu getRunAsdockerImageBuildContextMenu(final String projectName, final String dockerFileName) { - final SWTBotTreeItem fooProjectTreeItem = SWTUtils.getTreeItem(this.projectExplorerBotView, projectName); + final SWTBotTreeItem fooProjectTreeItem = SWTUtils + .getTreeItem(this.projectExplorerViewRule.getProjectExplorerBotView(), projectName); assertThat(fooProjectTreeItem).isNotNull(); SWTUtils.syncExec(() -> fooProjectTreeItem.expand()); final SWTBotTreeItem dockerfileTreeItem = SWTUtils.getTreeItem(fooProjectTreeItem, dockerFileName); assertThat(dockerfileTreeItem).isNotNull(); SWTUtils.select(dockerfileTreeItem); - final SWTBotMenu runAsDockerImageBuildMenu = SWTUtils.getContextMenu(this.projectExplorerBotView.bot().tree(), + final SWTBotMenu runAsDockerImageBuildMenu = SWTUtils.getContextMenu( + this.projectExplorerViewRule.getProjectExplorerBotView().bot().tree(), "Run As", "1 Docker Image Build"); return runAsDockerImageBuildMenu; } @@ -98,7 +94,8 @@ public class BuildDockerImageShortcutSWTBotTest { // when SWTUtils.asyncExec(() -> getRunAsdockerImageBuildContextMenu("foo", "Dockerfile").click()); // then expect an error dialog because no Docker connection exists - assertThat(bot.shell(CommandMessages.getString("BuildImageCommandHandler.no.connections.msg"))).isNotNull(); + assertThat(bot.shell(LaunchMessages.getString("BuildDockerImageShortcut.no.connections.msg"))) + .isNotNull(); // closing the wizard SWTUtils.syncExec(() -> { bot.button("No").click(); diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeSWTBotTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeSWTBotTest.java new file mode 100644 index 0000000000..9a0dc78ab2 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeSWTBotTest.java @@ -0,0 +1,304 @@ +/******************************************************************************* + * Copyright (c) 2016 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.launch; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.linuxtools.docker.core.DockerConnectionManager; +import org.eclipse.linuxtools.docker.core.DockerException; +import org.eclipse.linuxtools.internal.docker.core.DockerCompose; +import org.eclipse.linuxtools.internal.docker.core.DockerConnection; +import org.eclipse.linuxtools.internal.docker.core.ProcessLauncher; +import org.eclipse.linuxtools.internal.docker.ui.consoles.ConsoleMessages; +import org.eclipse.linuxtools.internal.docker.ui.testutils.CustomMatchers; +import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerClientFactory; +import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerConnectionFactory; +import org.eclipse.linuxtools.internal.docker.ui.testutils.ProjectInitializationRule; +import org.eclipse.linuxtools.internal.docker.ui.testutils.RunWithProject; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ButtonAssertion; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ClearConnectionManagerRule; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ClearLaunchConfigurationsRule; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseShellRule; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWelcomePageRule; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ComboAssertion; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ConsoleViewRule; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.DockerConnectionManagerUtils; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ProjectExplorerViewRule; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.SWTUtils; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.TextAssertion; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ToolbarButtonAssertion; +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarButton; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Matchers; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import com.spotify.docker.client.DockerClient; + +/** + * Testing the {@link DockerCompose} utility class using SWTBot. + */ +public class DockerComposeSWTBotTest { + + @ClassRule + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.DOCKER_PERSPECTIVE_ID); + + @Rule + public ClearConnectionManagerRule clearConnectionManager = new ClearConnectionManagerRule(); + + @Rule + public ProjectInitializationRule projectInit = new ProjectInitializationRule(); + + @Rule + public ClearLaunchConfigurationsRule clearLaunchConfig = new ClearLaunchConfigurationsRule( + IDockerComposeLaunchConfigurationConstants.CONFIG_TYPE_ID); + + @Rule + public CloseShellRule closeShell = new CloseShellRule(IDialogConstants.CLOSE_LABEL); + + @Rule + public ConsoleViewRule consoleViewRule = new ConsoleViewRule(); + + @Rule + public ProjectExplorerViewRule projectExplorerViewRule = new ProjectExplorerViewRule(); + + private SWTWorkbenchBot bot = new SWTWorkbenchBot(); + + private CountDownLatch latch; + + @Before + public void setupMockedProcessLauncher() throws DockerException, InterruptedException { + // configure the 'docker-compose up' mocks with a CountDownLatch to + // simulate a long-running process + final ProcessLauncher mockProcessLauncher = Mockito.mock(ProcessLauncher.class, Mockito.RETURNS_DEEP_STUBS); + DockerCompose.getInstance().setProcessLauncher(mockProcessLauncher); + setupDockerComposeUpMockProcess(mockProcessLauncher); + // configure the 'docker-compose stop' mocks which release the + // CountDownLatch to halt the long-running process + setupDockerComposeStopMockProcess(mockProcessLauncher); + + } + + private void setupDockerComposeUpMockProcess(final ProcessLauncher mockProcessLauncher) + throws DockerException, InterruptedException { + final Process mockDockerComposeUpProcess = Mockito.mock(Process.class); + Mockito.when(mockDockerComposeUpProcess.getInputStream()) + .thenReturn(new ByteArrayInputStream("up!\n".getBytes())); + Mockito.when(mockDockerComposeUpProcess.getErrorStream()).thenReturn(new ByteArrayInputStream("".getBytes())); + Mockito.when(mockDockerComposeUpProcess.getOutputStream()).thenReturn(new ByteArrayOutputStream()); + Mockito.when(mockProcessLauncher.processBuilder(Matchers.anyString(), + Matchers.eq(DockerCompose.getDockerComposeCommandName()), CustomMatchers.arrayContains("up")) + .workingDir(Matchers.anyString()).start()).thenReturn(mockDockerComposeUpProcess); + latch = new CountDownLatch(1); + Mockito.when(mockDockerComposeUpProcess.waitFor()).then(new Answer<Object>() { + + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + latch.await(5, TimeUnit.SECONDS); + return 0; + } + }); + } + + private void setupDockerComposeStopMockProcess(final ProcessLauncher mockProcessLauncher) + throws DockerException, InterruptedException { + final Process mockDockerComposeStopProcess = Mockito.mock(Process.class); + Mockito.when(mockDockerComposeStopProcess.getInputStream()) + .thenReturn(new ByteArrayInputStream("stop\n".getBytes())); + Mockito.when(mockDockerComposeStopProcess.getErrorStream()).thenReturn(new ByteArrayInputStream("".getBytes())); + Mockito.when(mockDockerComposeStopProcess.getOutputStream()).thenReturn(new ByteArrayOutputStream()); + + Mockito.when(mockProcessLauncher.processBuilder(Matchers.anyString(), + Matchers.eq(DockerCompose.getDockerComposeCommandName()), CustomMatchers.arrayContains("stop")) + .workingDir(Matchers.anyString()).start()).thenReturn(mockDockerComposeStopProcess); + Mockito.when(mockDockerComposeStopProcess.waitFor()).then(new Answer<Object>() { + + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + latch.countDown(); + return 0; + } + }); + } + + /** + * @return the {@link SWTBotMenu} for the "Run as > Docker Image Build" + * shortcut + */ + private SWTBotMenu getRunAsDockerComposeContextMenu(final String projectName, final String dockerComposeFileName) { + final SWTBotView projectExplorerBotView = this.projectExplorerViewRule.getProjectExplorerBotView(); + // make sure the project explorer view is visible, in case it was hidden + // by another view. + projectExplorerBotView.setFocus(); + final SWTBotTreeItem fooProjectTreeItem = SWTUtils.getTreeItem(projectExplorerBotView, projectName); + assertThat(fooProjectTreeItem).isNotNull(); + SWTUtils.syncExec(() -> fooProjectTreeItem.expand()); + final SWTBotTreeItem dockerfileTreeItem = SWTUtils.getTreeItem(fooProjectTreeItem, dockerComposeFileName); + assertThat(dockerfileTreeItem).isNotNull(); + SWTUtils.select(dockerfileTreeItem); + final SWTBotMenu runAsDockerComposeMenu = SWTUtils.getContextMenu( + projectExplorerBotView.bot().tree(), + "Run As", "1 Docker Compose"); + return runAsDockerComposeMenu; + } + + @Test + @RunWithProject("foo") + public void shouldDisableCommandOnFirstCallWhenMissingConnection() { + // given no connection + ClearConnectionManagerRule.removeAllConnections(DockerConnectionManager.getInstance()); + // when + SWTUtils.asyncExec(() -> getRunAsDockerComposeContextMenu("foo", "docker-compose.yml").click()); + // then expect an error dialog because no Docker connection exists + assertThat(bot.shell(LaunchMessages.getString("DockerComposeUpShortcut.no.connections.msg"))).isNotNull(); + // closing the wizard + SWTUtils.syncExec(() -> { + bot.button("No").click(); + }); + } + + @Test + @RunWithProject("foo") + public void shouldStartDockerComposeFromScratch() throws CoreException, InterruptedException { + // given + final DockerClient client = MockDockerClientFactory.build(); + final DockerConnection dockerConnection = MockDockerConnectionFactory.from("Test", client) + .withDefaultTCPConnectionSettings(); + DockerConnectionManagerUtils.configureConnectionManager(dockerConnection); + // when + SWTUtils.asyncExec(() -> getRunAsDockerComposeContextMenu("foo", "docker-compose.yml").click()); + // then confirm the connection + bot.button("OK").click(); + // wait for the job to run + SWTUtils.waitForJobsToComplete(); + // then expect the console to be displayed + assertThat(SWTUtils.isConsoleViewVisible(this.bot)).isTrue(); + // expect the 'stop' button to be enabled + final SWTBotToolbarButton consoleToolbarStopButton = SWTUtils.getConsoleToolbarButtonWithTooltipText(bot, + ConsoleMessages.getString("DockerComposeStopAction.tooltip")); + ToolbarButtonAssertion.assertThat(consoleToolbarStopButton).isEnabled(); + // verify that the launch configuration was saved + final ILaunchConfiguration launchConfiguration = LaunchConfigurationUtils.getLaunchConfigurationByName( + IDockerComposeLaunchConfigurationConstants.CONFIG_TYPE_ID, "Docker Compose [foo]"); + assertThat(launchConfiguration).isNotNull(); + // verify the latch + assertThat(latch.getCount()).isEqualTo(1); + } + + @Test + @RunWithProject("foo") + public void shouldStartDockerComposeWithExistingLaunchConfiguration() throws CoreException { + // given + final DockerClient client = MockDockerClientFactory.build(); + final DockerConnection dockerConnection = MockDockerConnectionFactory.from("Test", client) + .withDefaultTCPConnectionSettings(); + DockerConnectionManagerUtils.configureConnectionManager(dockerConnection); + final IFile dockerComposeScript = projectInit.getProject().getFile("docker-compose.yml"); + LaunchConfigurationUtils.createDockerComposeUpLaunchConfiguration(dockerConnection, dockerComposeScript); + // when + SWTUtils.asyncExec(() -> getRunAsDockerComposeContextMenu("foo", "docker-compose.yml").click()); + // then confirm the connection + final SWTBotToolbarButton consoleToolbarStopButton = SWTUtils.getConsoleToolbarButtonWithTooltipText(bot, + ConsoleMessages.getString("DockerComposeStopAction.tooltip")); + ToolbarButtonAssertion.assertThat(consoleToolbarStopButton).isEnabled(); + } + + @Test + @RunWithProject("foo") + public void shouldStopDockerCompose() throws CoreException, InterruptedException { + // given + shouldStartDockerComposeFromScratch(); + // when + final SWTBotToolbarButton consoleToolbarStopButton = SWTUtils.getConsoleToolbarButtonWithTooltipText(bot, + ConsoleMessages.getString("DockerComposeStopAction.tooltip")); + ToolbarButtonAssertion.assertThat(consoleToolbarStopButton).isEnabled(); + consoleToolbarStopButton.click(); + // then + // verify the latch is down + assertThat(latch.getCount()).isEqualTo(0); + // verify the stop button is disabled + ToolbarButtonAssertion.assertThat(consoleToolbarStopButton).isNotEnabled(); + } + + @Test + @RunWithProject("foo") + public void shouldRestartDockerCompose() throws CoreException, InterruptedException, DockerException { + // given + final DockerClient client = MockDockerClientFactory.build(); + final DockerConnection dockerConnection = MockDockerConnectionFactory.from("Test", client) + .withDefaultTCPConnectionSettings(); + DockerConnectionManagerUtils.configureConnectionManager(dockerConnection); + // when starting without launch config + SWTUtils.asyncExec(() -> getRunAsDockerComposeContextMenu("foo", "docker-compose.yml").click()); + bot.button("OK").click(); + // wait for the job to run + SWTUtils.waitForJobsToComplete(); + // when stopping + final SWTBotToolbarButton consoleToolbarStopButton = SWTUtils.getConsoleToolbarButtonWithTooltipText(bot, + ConsoleMessages.getString("DockerComposeStopAction.tooltip")); + ToolbarButtonAssertion.assertThat(consoleToolbarStopButton).isEnabled(); + consoleToolbarStopButton.click(); + // redo the setup to get a new mock process + setupMockedProcessLauncher(); + // when restarting + SWTUtils.asyncExec(() -> getRunAsDockerComposeContextMenu("foo", "docker-compose.yml").click()); + // wait for the job to run + SWTUtils.waitForJobsToComplete(); + // then + ToolbarButtonAssertion.assertThat(consoleToolbarStopButton).isEnabled(); + } + + @Test + @RunWithProject("foo") + @Ignore // ignored for now because the "Run" menu from the toolbar remains + // visible (on macOS) and this + // has side-effects on the other tests that fail because the widgets are not + // found. + public void shouldValidateLaunchConfiguration() throws CoreException { + // given + final DockerClient client = MockDockerClientFactory.build(); + final DockerConnection dockerConnection = MockDockerConnectionFactory.from("Test", client) + .withDefaultTCPConnectionSettings(); + DockerConnectionManagerUtils.configureConnectionManager(dockerConnection); + final IFile dockerComposeScript = projectInit.getProject().getFile("docker-compose.yml"); + LaunchConfigurationUtils.createDockerComposeUpLaunchConfiguration(dockerConnection, dockerComposeScript); + // when + bot.toolbarDropDownButtonWithTooltip("Run").menuItem("Run Configurations...").click(); + final SWTBotTreeItem dockerComposeTreeItem = SWTUtils.expand(bot.tree(), "Docker Compose"); + SWTUtils.select(dockerComposeTreeItem, "Docker Compose [foo]"); + // verify that the config is set and the form can be closed with the + // "OK" button + ComboAssertion.assertThat(bot.comboBox(0)).isEnabled().itemSelected("Test"); + TextAssertion.assertThat(bot.text(2)).isEnabled().textEquals("/foo"); + ButtonAssertion.assertThat(bot.button("Run")).isEnabled(); + + } +} diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/CustomMatchers.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/CustomMatchers.java new file mode 100644 index 0000000000..2a0d37b78d --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/CustomMatchers.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2016 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.testutils; + +import java.util.stream.Stream; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.mockito.Matchers; + +/** + * Custom {@link Matcher} + */ +public class CustomMatchers { + + public static String[] arrayContains(final String expectation) { + return Matchers.argThat(new BaseMatcher<String[]>() { + + @Override + public boolean matches(Object items) { + return Stream.of((String[]) items).anyMatch(item -> item.equals(expectation)); + } + + @Override + public void describeTo(Description description) { + + } + + }); + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/ProjectInitializationRule.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/ProjectInitializationRule.java index 7fd366d434..b0f9a43039 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/ProjectInitializationRule.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/ProjectInitializationRule.java @@ -45,6 +45,12 @@ public class ProjectInitializationRule extends ExternalResource { private Description description; + private IProject project = null; + + public IProject getProject() { + return this.project; + } + @Override public Statement apply(final Statement base, final Description description) { this.description = description; @@ -58,7 +64,7 @@ public class ProjectInitializationRule extends ExternalResource { } final String projectName = getProjectName(); final IWorkspace junitWorkspace = ResourcesPlugin.getWorkspace(); - getTargetWorkspaceProject(getSampleProjectPath(projectName), junitWorkspace); + this.project = getTargetWorkspaceProject(getSampleProjectPath(projectName), junitWorkspace); } /** @@ -79,7 +85,7 @@ public class ProjectInitializationRule extends ExternalResource { if (runWithProjectTypeAnnotation != null) { return runWithProjectTypeAnnotation.value(); } - fail("No @RunWithProject found while running test " + className + "." + methodName); + fail("No '@RunWithProject' annotation found while running test " + className + "." + methodName); return null; } @@ -98,7 +104,7 @@ public class ProjectInitializationRule extends ExternalResource { /** * Creates or opens the project in the target/JUnit workspace. - * + * * @param projectSourcePath * the absolute path to the project * @param targetWorkspace @@ -150,7 +156,7 @@ public class ProjectInitializationRule extends ExternalResource { */ static void createProject(final IProjectDescription description, final String projectName, final IWorkspace workspace, final IProject project) - throws InvocationTargetException, OperationCanceledException, CoreException, InterruptedException { + throws InvocationTargetException, OperationCanceledException, CoreException, InterruptedException { // import from file system // import project from location copying files - use default project @@ -174,7 +180,7 @@ public class ProjectInitializationRule extends ExternalResource { /** * Builds the given project - * + * * @param project * @throws CoreException * @throws OperationCanceledException diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/AbstractSWTBotAssertion.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/AbstractSWTBotAssertion.java index 23b02f0bbe..c71468bc3d 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/AbstractSWTBotAssertion.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/AbstractSWTBotAssertion.java @@ -21,7 +21,7 @@ import org.eclipse.swtbot.swt.finder.widgets.AbstractSWTBot; */ public abstract class AbstractSWTBotAssertion<Assertion extends AbstractSWTBotAssertion<Assertion, SWTWidget>, SWTWidget extends AbstractSWTBot<?>> extends AbstractAssert<Assertion, SWTWidget> { - + protected AbstractSWTBotAssertion(final SWTWidget actual, final Class<Assertion> clazz) { super(actual, clazz); } @@ -30,7 +30,8 @@ public abstract class AbstractSWTBotAssertion<Assertion extends AbstractSWTBotAs public Assertion isEnabled() { notNullValue(); if(!actual.isEnabled()) { - failWithMessage("Expected checkbox with text '%s' to be enabled but it was not", actual.getText()); + failWithMessage("Expected widget with text '%s (%s)' to be enabled but it was not", actual.getText(), + actual.getToolTipText()); } return (Assertion) this; } @@ -39,7 +40,7 @@ public abstract class AbstractSWTBotAssertion<Assertion extends AbstractSWTBotAs public Assertion isNotEnabled() { notNullValue(); if(actual.isEnabled()) { - failWithMessage("Expected checkbox with text '%s' to be disabled but it was not", actual.getText()); + failWithMessage("Expected widget with text '%s (%s)' to be disabled but it was not", actual.getText()); } return (Assertion) this; } diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ClearConnectionManagerRule.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ClearConnectionManagerRule.java index 65f5820144..2124b75eaa 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ClearConnectionManagerRule.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ClearConnectionManagerRule.java @@ -11,9 +11,11 @@ package org.eclipse.linuxtools.internal.docker.ui.testutils.swt; -import java.util.stream.Stream; +import java.util.ArrayList; +import java.util.List; import org.eclipse.linuxtools.docker.core.DockerConnectionManager; +import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.internal.docker.core.DefaultDockerConnectionSettingsFinder; import org.junit.rules.ExternalResource; @@ -35,7 +37,8 @@ public class ClearConnectionManagerRule extends ExternalResource { * @param dockerConnectionManager */ public static void removeAllConnections(final DockerConnectionManager dockerConnectionManager) { - Stream.of(dockerConnectionManager.getConnections()).forEach(c -> dockerConnectionManager.removeConnection(c)); + final List<IDockerConnection> allConnections = new ArrayList<>(dockerConnectionManager.getAllConnections()); + allConnections.forEach(c -> dockerConnectionManager.removeConnection(c)); } }
\ No newline at end of file diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ClearLaunchConfigurationsRule.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ClearLaunchConfigurationsRule.java index 32843734de..078b0d87e9 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ClearLaunchConfigurationsRule.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ClearLaunchConfigurationsRule.java @@ -32,7 +32,7 @@ public class ClearLaunchConfigurationsRule extends ExternalResource { /** * Constructor - * + * * @param launchConfigTypeId * the id of the {@link ILaunchConfiguration} type to remove. */ diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/CloseWizardRule.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/CloseShellRule.java index 8846a78477..8c1522ac28 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/CloseWizardRule.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/CloseShellRule.java @@ -11,7 +11,6 @@ package org.eclipse.linuxtools.internal.docker.ui.testutils.swt; -import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.linuxtools.docker.core.DockerConnectionManager; import org.eclipse.linuxtools.internal.docker.core.DefaultDockerConnectionSettingsFinder; import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; @@ -24,15 +23,22 @@ import org.junit.rules.ExternalResource; /** * Closes the wizard(s) after each test, if the "Cancel" button is available */ -public class CloseWizardRule extends ExternalResource { +public class CloseShellRule extends ExternalResource { + + private final String buttonLabel; + + public CloseShellRule(final String buttonLabel) { + this.buttonLabel = buttonLabel; + } @Override protected void after() { final SWTWorkbenchBot bot = new SWTWorkbenchBot(); try { - while (isInDialog(bot) && getCancelButton(bot) != null) { - getCancelButton(bot).click(); + while (isInDialog(bot) && getButton(bot, this.buttonLabel) != null) { + getButton(bot, this.buttonLabel).click(); } + DockerConnectionManager.getInstance() .setConnectionSettingsFinder(new DefaultDockerConnectionSettingsFinder()); } catch (WidgetNotFoundException e) { @@ -42,12 +48,13 @@ public class CloseWizardRule extends ExternalResource { private static boolean isInDialog(final SWTWorkbenchBot bot) { final SWTBotShell activeShell = bot.activeShell(); - final String text = SWTUtils.syncExec(() -> PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().getText()); + final String text = SWTUtils + .syncExec(() -> PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().getText()); final String shellText = activeShell.getText(); return text != null && !text.equals(shellText); } - private static SWTBotButton getCancelButton(final SWTWorkbenchBot bot) { - return bot.button(IDialogConstants.CANCEL_LABEL); + private static SWTBotButton getButton(final SWTWorkbenchBot bot, final String buttonLabel) { + return bot.button(buttonLabel); } } diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/CloseWelcomePageRule.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/CloseWelcomePageRule.java index 2c08de7172..98c83ac24f 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/CloseWelcomePageRule.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/CloseWelcomePageRule.java @@ -12,8 +12,9 @@ package org.eclipse.linuxtools.internal.docker.ui.testutils.swt; import org.eclipse.swt.widgets.Display; -import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.ui.IWorkbench; import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.WorkbenchException; import org.junit.rules.ExternalResource; /** @@ -21,33 +22,36 @@ import org.junit.rules.ExternalResource; */ public class CloseWelcomePageRule extends ExternalResource { + public static final String DOCKER_PERSPECTIVE_ID = "org.eclipse.linuxtools.docker.ui.perspective"; + + public static final String JAVA_PERSPECTIVE_ID = "org.eclipse.jdt.ui.JavaPerspective"; + /** the Id of the perspective to open. */ private final String defaultPerspectiveId; - - /** - * Default constructor when the "Docker tooling" perspective is going to be opened once the welcome page was closed. - */ - public CloseWelcomePageRule() { - this.defaultPerspectiveId = "org.eclipse.linuxtools.docker.ui.perspective"; - } - + /** - * Custom constructor with the id of the perspective to open once the welcome page was closed. - * @param perspectiveId the id of the perspective to open. + * Custom constructor with the id of the perspective to open once the + * welcome page was closed. + * + * @param perspectiveId + * the id of the perspective to open. */ public CloseWelcomePageRule(final String perspectiveId) { this.defaultPerspectiveId = perspectiveId; } - + @Override protected void before() { Display.getDefault().syncExec(() -> { - if (PlatformUI.getWorkbench().getIntroManager().getIntro() != null) { - PlatformUI.getWorkbench().getIntroManager() - .closeIntro(PlatformUI.getWorkbench().getIntroManager().getIntro()); - } + final IWorkbench workbench = PlatformUI.getWorkbench(); + if (workbench.getIntroManager().getIntro() != null) { + workbench.getIntroManager().closeIntro(workbench.getIntroManager().getIntro()); + } + try { + workbench.showPerspective(defaultPerspectiveId, workbench.getActiveWorkbenchWindow()); + } catch (WorkbenchException e) { + e.printStackTrace(); + } }); - final SWTWorkbenchBot bot = new SWTWorkbenchBot(); - bot.perspectiveById(defaultPerspectiveId).activate(); } } diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ConsoleViewRule.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ConsoleViewRule.java new file mode 100644 index 0000000000..2f877122a5 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ConsoleViewRule.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2016 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.testutils.swt; + +import org.eclipse.swt.widgets.Display; +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; +import org.eclipse.ui.console.IConsoleConstants; +import org.junit.rules.ExternalResource; + +/** + * An {@link ExternalResource} to close the Console view. + */ +public class ConsoleViewRule extends ExternalResource { + + @Override + protected void before() { + Display.getDefault().syncExec(() -> { + final SWTBotView consoleView = SWTUtils.getSWTBotView(new SWTWorkbenchBot(), + IConsoleConstants.ID_CONSOLE_VIEW); + if (consoleView != null) { + consoleView.close(); + } + }); + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/DockerConnectionManagerUtils.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/DockerConnectionManagerUtils.java index dd55f32718..62bdafedb9 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/DockerConnectionManagerUtils.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/DockerConnectionManagerUtils.java @@ -11,9 +11,6 @@ package org.eclipse.linuxtools.internal.docker.ui.testutils.swt; -import java.util.Optional; -import java.util.concurrent.TimeUnit; - import org.eclipse.linuxtools.docker.core.DockerConnectionManager; import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.docker.core.IDockerConnectionStorageManager; @@ -21,11 +18,9 @@ import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerConnectionS import org.eclipse.linuxtools.internal.docker.ui.views.DockerContainersView; import org.eclipse.linuxtools.internal.docker.ui.views.DockerExplorerView; import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; -import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; -import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; /** - * + * */ public class DockerConnectionManagerUtils { @@ -33,28 +28,33 @@ public class DockerConnectionManagerUtils { * Configures the {@link DockerConnectionManager} with the given array of * {@link IDockerConnection} (can be mocked) and refreshes the associated * {@link DockerExplorerView}. - * - * @param connections the connection to configure in the {@link DockerConnectionManager} via a mocked {@link IDockerConnectionStorageManager} + * + * @param connections + * the connection to configure in the + * {@link DockerConnectionManager} via a mocked + * {@link IDockerConnectionStorageManager} */ - public static void configureConnectionManager( - final IDockerConnection... connections) { - final IDockerConnectionStorageManager connectionStorageManager = MockDockerConnectionStorageManagerFactory.providing(connections); + public static void configureConnectionManager(final IDockerConnection... connections) { + final IDockerConnectionStorageManager connectionStorageManager = MockDockerConnectionStorageManagerFactory + .providing(connections); configureConnectionManager(connectionStorageManager); } - + /** * Configures the {@link DockerConnectionManager} with the given array of * {@link IDockerConnection} (can be mocked) and refreshes the associated * {@link DockerExplorerView}. - * - * @param connectionStorageManager the {@link IDockerConnectionStorageManager} to use (can be mocked) + * + * @param connectionStorageManager + * the {@link IDockerConnectionStorageManager} to use (can be + * mocked) */ public static void configureConnectionManager(final IDockerConnectionStorageManager connectionStorageManager) { - DockerConnectionManager.getInstance() - .setConnectionStorageManager(connectionStorageManager); + DockerConnectionManager.getInstance().setConnectionStorageManager(connectionStorageManager); final SWTWorkbenchBot bot = new SWTWorkbenchBot(); - final DockerExplorerView dockerExplorerView = getView(bot, DockerExplorerView.VIEW_ID); - final DockerContainersView dockerContainersView = getView(bot, DockerContainersView.VIEW_ID); + final DockerExplorerView dockerExplorerView = SWTUtils.getView(bot, DockerExplorerView.VIEW_ID); + final DockerContainersView dockerContainersView = (DockerContainersView) SWTUtils.getView(bot, + DockerContainersView.VIEW_ID); SWTUtils.syncExec(() -> { DockerConnectionManager.getInstance().reloadConnections(); if (dockerExplorerView != null) { @@ -65,17 +65,6 @@ public class DockerConnectionManagerUtils { dockerContainersView.getViewer().refresh(); } }); - SWTUtils.wait(1, TimeUnit.SECONDS); - } - - @SuppressWarnings("unchecked") - private static <T> T getView(final SWTWorkbenchBot bot, final String viewId) { - final Optional<SWTBotView> viewBot = bot.views().stream().filter(v -> v.getReference().getId().equals(viewId)) - .findFirst(); - if(viewBot.isPresent()) { - return UIThreadRunnable.syncExec(() -> (T) (viewBot.get().getViewReference().getView(true))); - } - return null; } } diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ProjectExplorerViewRule.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ProjectExplorerViewRule.java new file mode 100644 index 0000000000..b0de77ffb0 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ProjectExplorerViewRule.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2016 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.testutils.swt; + +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.junit.Rule; +import org.junit.rules.ExternalResource; + +/** + * A JUnit {@link Rule} to open the Project Explorer view. + */ +public class ProjectExplorerViewRule extends ExternalResource { + + private SWTBotView projectExplorerBotView; + + public static final String PROJECT_EXPLORER_VIEW_ID = "org.eclipse.ui.navigator.ProjectExplorer"; + + @Override + protected void before() throws Throwable { + final SWTWorkbenchBot bot = new SWTWorkbenchBot(); + SWTUtils.syncExec(() -> { + try { + return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() + .showView(PROJECT_EXPLORER_VIEW_ID); + } catch (PartInitException e) { + e.printStackTrace(); + return null; + } + }); + this.projectExplorerBotView = bot.viewById(PROJECT_EXPLORER_VIEW_ID); + this.projectExplorerBotView.setFocus(); + } + + public SWTBotView getProjectExplorerBotView() { + return this.projectExplorerBotView; + } +} diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/SWTUtils.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/SWTUtils.java index 1f7729a63f..73aa1f1373 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/SWTUtils.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/SWTUtils.java @@ -33,14 +33,17 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Tree; +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; import org.eclipse.swtbot.eclipse.finder.waits.Conditions; import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; import org.eclipse.swtbot.swt.finder.results.Result; import org.eclipse.swtbot.swt.finder.results.VoidResult; import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarButton; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; +import org.eclipse.ui.console.IConsoleConstants; import org.eclipse.ui.progress.UIJob; import org.junit.Assert; import org.junit.ComparisonFailure; @@ -51,7 +54,7 @@ import org.junit.ComparisonFailure; public class SWTUtils { /** - * Calls <strong>synchronously</strong> the given {@link Runnable} in the + * Calls <strong>synchronously</strong> the given {@link Supplier} in the * default Display and returns the result * * @param supplier @@ -145,7 +148,7 @@ public class SWTUtils { swtException.add(e2); } }); - if(waitForJobsToComplete) { + if (waitForJobsToComplete) { waitForJobsToComplete(); } if (!failure.isEmpty()) { @@ -174,9 +177,9 @@ public class SWTUtils { * @throws InterruptedException */ public static void waitForJobsToComplete(Object familly) { -// while (Job.getJobManager().find(familly).length > 0) { -// wait(1, TimeUnit.SECONDS); -// } + // while (Job.getJobManager().find(familly).length > 0) { + // wait(1, TimeUnit.SECONDS); + // } Conditions.waitForJobs(DockerExplorerView.class, "Docker Explorer View jobs"); } @@ -195,9 +198,12 @@ public class SWTUtils { /** * - * @param parentTreeItem the parent tree item from which to start - * @param paths the relative path to the item to return - * @return the {@link SWTBotTreeItem} that matches the given path from the given parent tree item + * @param parentTreeItem + * the parent tree item from which to start + * @param paths + * the relative path to the item to return + * @return the {@link SWTBotTreeItem} that matches the given path from the + * given parent tree item */ public static SWTBotTreeItem getTreeItem(final SWTBotTreeItem parentTreeItem, final String... paths) { if (paths.length == 1) { @@ -263,8 +269,11 @@ public class SWTUtils { /** * Waits for the given duration - * @param duration the duration - * @param unit the duration unit + * + * @param duration + * the duration + * @param unit + * the duration unit */ public static void wait(final int duration, final TimeUnit unit) { try { @@ -275,26 +284,9 @@ public class SWTUtils { } /** - * Selects <strong> all child items</strong> in the given <code>parentTreeItem</code> whose - * labels match the given <code>items</code>. - * - * @param parentTreeItem - * the parent tree item - * @param firstItem - * the first item to select - * @param otherItems - * the other items to select - * @return - */ - public static SWTBotTreeItem select(final SWTBotTreeItem parentTreeItem, final String firstItem, final String... otherItems) { - final String[] matchItems = new String[otherItems.length]; - matchItems[0] = firstItem; - return select(parentTreeItem, matchItems); - } - - /** - * Selects <strong> all child items</strong> in the given <code>parentTreeItem</code> whose - * labels match the given <code>items</code>. + * Selects <strong> all child items</strong> in the given + * <code>parentTreeItem</code> whose labels match the given + * <code>items</code>. * * @param parentTreeItem * the parent tree item @@ -302,16 +294,16 @@ public class SWTUtils { * the items to select * @return */ - public static SWTBotTreeItem select(final SWTBotTreeItem parentTreeItem, final String[] matchItems) { - final List<String> fullyQualifiedItems = Stream.of(parentTreeItem.getItems()) - .filter(treeItem -> Stream.of(matchItems) - .anyMatch(matchItem -> treeItem.getText().startsWith(matchItem))) + public static SWTBotTreeItem select(final SWTBotTreeItem parentTreeItem, final String... matchItems) { + final List<String> fullyQualifiedItems = Stream.of(parentTreeItem.getItems()).filter( + treeItem -> Stream.of(matchItems).anyMatch(matchItem -> treeItem.getText().startsWith(matchItem))) .map(item -> item.getText()).collect(Collectors.toList()); return parentTreeItem.select(fullyQualifiedItems.toArray(new String[0])); } + /** - * Selects the given <code>treeItem</code> whose - * labels match the given <code>items</code>. + * Selects the given <code>treeItem</code> whose labels match the given + * <code>items</code>. * * @param treeItem * the parent tree item @@ -323,26 +315,31 @@ public class SWTUtils { } /** - * @param tree the root {@link SWTBotTree} - * @param path the path for the menu - * @return the child {@link SWTBotMenu} named with the first item in the given <code>path</code> from the given {@link SWTBotTree} + * @param tree + * the root {@link SWTBotTree} + * @param path + * the path for the menu + * @return the child {@link SWTBotMenu} named with the first item in the + * given <code>path</code> from the given {@link SWTBotTree} */ public static SWTBotMenu getContextMenu(final SWTBotTree tree, String... path) { final SWTBotMenu contextMenu = tree.contextMenu(path[0]); - if(contextMenu == null) { - Assert.fail("Failed to find context menu '" + path[0] +"'."); + if (contextMenu == null) { + Assert.fail("Failed to find context menu '" + path[0] + "'."); } - if(path.length == 1) { + if (path.length == 1) { return contextMenu; } - final String[] remainingPath = new String[path.length -1]; + final String[] remainingPath = new String[path.length - 1]; System.arraycopy(path, 1, remainingPath, 0, remainingPath.length); return getSubMenu(contextMenu, remainingPath); } /** * Hides the menu for the given <code>tree</code> - * @param tree the tree whose {@link Menu} should be hidden + * + * @param tree + * the tree whose {@link Menu} should be hidden */ public static void hideMenu(final SWTBotTree tree) { final Menu menu = UIThreadRunnable.syncExec((Result<Menu>) () -> tree.widget.getMenu()); @@ -363,19 +360,22 @@ public class SWTUtils { } /** - * @param menu the parent menu - * @param path the path for the menu - * @return the child {@link SWTBotMenu} named with the first item in the given <code>path</code> from the given {@link SWTBotMenu} + * @param menu + * the parent menu + * @param path + * the path for the menu + * @return the child {@link SWTBotMenu} named with the first item in the + * given <code>path</code> from the given {@link SWTBotMenu} */ public static SWTBotMenu getSubMenu(final SWTBotMenu menu, String... path) { final SWTBotMenu subMenu = menu.menu(path[0]); - if(subMenu == null) { - Assert.fail("Failed to find submenu '" + path[0] +"'."); + if (subMenu == null) { + Assert.fail("Failed to find submenu '" + path[0] + "'."); } - if(path.length == 1) { + if (path.length == 1) { return subMenu; } - final String[] remainingPath = new String[path.length -1]; + final String[] remainingPath = new String[path.length - 1]; System.arraycopy(path, 1, remainingPath, 0, remainingPath.length); return getSubMenu(subMenu, remainingPath); } @@ -416,7 +416,8 @@ public class SWTUtils { public void done(IJobChangeEvent event) { final int maxAttempts = 30; int currentAttempt = 0; - while(currentAttempt < maxAttempts && treeItem.getItems().length == 1 && treeItem.getItems()[0].getText().isEmpty()) { + while (currentAttempt < maxAttempts && treeItem.getItems().length == 1 + && treeItem.getItems()[0].getText().isEmpty()) { SWTUtils.wait(1, TimeUnit.SECONDS); currentAttempt++; } @@ -428,5 +429,29 @@ public class SWTUtils { return treeItem; } + @SuppressWarnings("unchecked") + public static SWTBotView getSWTBotView(final SWTWorkbenchBot bot, final String viewId) { + return bot.views().stream().filter(v -> v.getViewReference().getId().equals(viewId)).findFirst().orElse(null); + } + + @SuppressWarnings("unchecked") + public static <T> T getView(final SWTWorkbenchBot bot, final String viewId) { + return (T) bot.views().stream().filter(v -> v.getViewReference().getId().equals(viewId)).findFirst() + .map(v -> v.getReference().getView(false)).orElse(null); + } + + /** + * @return <code>true</code> if the Console view is visible in the active + * page, <code>false</code> otherwise. + * @throws InterruptedException + */ + public static boolean isConsoleViewVisible(final SWTWorkbenchBot bot) { + return SWTUtils.getView(bot, IConsoleConstants.ID_CONSOLE_VIEW) != null; + } + + public static SWTBotToolbarButton getConsoleToolbarButtonWithTooltipText(final SWTWorkbenchBot bot, final String tooltipText) { + return bot.viewById(IConsoleConstants.ID_CONSOLE_VIEW).getToolbarButtons().stream() + .filter(button -> button.getToolTipText().equals(tooltipText)).findFirst().get(); + } } diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ToolbarButtonAssertion.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ToolbarButtonAssertion.java new file mode 100644 index 0000000000..07be08f0e9 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/testutils/swt/ToolbarButtonAssertion.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2015 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.testutils.swt; + +import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarButton; + +/** + * Custom assertions on a given {@link SWTBotButton}. + */ +public class ToolbarButtonAssertion extends AbstractSWTBotAssertion<ToolbarButtonAssertion, SWTBotToolbarButton> { + + protected ToolbarButtonAssertion(final SWTBotToolbarButton actual) { + super(actual, ToolbarButtonAssertion.class); + } + + public static ToolbarButtonAssertion assertThat(final SWTBotToolbarButton actual) { + return new ToolbarButtonAssertion(actual); + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerContainersViewSWTBotTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerContainersViewSWTBotTest.java index b4b9e4cbba..32c1678802 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerContainersViewSWTBotTest.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerContainersViewSWTBotTest.java @@ -47,7 +47,8 @@ public class DockerContainersViewSWTBotTest { private SWTBotView dockerExplorerBotView; @ClassRule - public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule(); + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.DOCKER_PERSPECTIVE_ID); @Rule public TestLoggerRule watcher = new TestLoggerRule(); diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerExplorerViewSWTBotTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerExplorerViewSWTBotTest.java index 8e692ab945..c73e09e14d 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerExplorerViewSWTBotTest.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerExplorerViewSWTBotTest.java @@ -64,7 +64,8 @@ public class DockerExplorerViewSWTBotTest { private DockerExplorerView dockerExplorerView; @ClassRule - public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule(); + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.DOCKER_PERSPECTIVE_ID); @Rule public TestLoggerRule watcher = new TestLoggerRule(); diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerImageHierarchyViewSWTBotTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerImageHierarchyViewSWTBotTest.java index 4440b20ec4..2cb68f726e 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerImageHierarchyViewSWTBotTest.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerImageHierarchyViewSWTBotTest.java @@ -48,7 +48,8 @@ public class DockerImageHierarchyViewSWTBotTest { private DockerExplorerView dockerExplorerView; @ClassRule - public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule(); + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.DOCKER_PERSPECTIVE_ID); @Rule public TestLoggerRule watcher = new TestLoggerRule(); diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerImagesViewSWTBotTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerImagesViewSWTBotTest.java index 50f5da3c5a..56346e5fdb 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerImagesViewSWTBotTest.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerImagesViewSWTBotTest.java @@ -48,7 +48,8 @@ public class DockerImagesViewSWTBotTest { private SWTBotView dockerExplorerBotView; @ClassRule - public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule(); + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.DOCKER_PERSPECTIVE_ID); @Rule public TestLoggerRule watcher = new TestLoggerRule(); diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/EditDockerConnectionSWTBotTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/EditDockerConnectionSWTBotTest.java index cffb330684..225f958524 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/EditDockerConnectionSWTBotTest.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/EditDockerConnectionSWTBotTest.java @@ -21,6 +21,7 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.wizard.Wizard; import org.eclipse.linuxtools.docker.core.DockerConnectionManager; import org.eclipse.linuxtools.docker.core.EnumDockerConnectionState; @@ -44,8 +45,8 @@ import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerHostConfigF import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerImageFactory; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ButtonAssertion; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CheckBoxAssertion; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseShellRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWelcomePageRule; -import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWizardRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.DockerConnectionManagerUtils; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.RadioAssertion; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.SWTBotViewRule; @@ -81,10 +82,11 @@ public class EditDockerConnectionSWTBotTest { private static String PATH_TO_CERTS = System.getProperty("java.io.tmpdir"); @ClassRule - public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule(); + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.DOCKER_PERSPECTIVE_ID); @Rule - public CloseWizardRule closeWizard = new CloseWizardRule(); + public CloseShellRule closeShell = new CloseShellRule(IDialogConstants.CANCEL_LABEL); @Rule public TemporaryFolder folder = new TemporaryFolder(); diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullSWTBotTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullSWTBotTest.java index 2d69be176a..591b9f9392 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullSWTBotTest.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePullSWTBotTest.java @@ -11,6 +11,7 @@ package org.eclipse.linuxtools.internal.docker.ui.wizards; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.linuxtools.internal.docker.core.DockerConnection; import org.eclipse.linuxtools.internal.docker.core.DockerProgressHandler; import org.eclipse.linuxtools.internal.docker.core.RegistryAccountInfo; @@ -22,8 +23,8 @@ import org.eclipse.linuxtools.internal.docker.ui.testutils.MockImageFactory; import org.eclipse.linuxtools.internal.docker.ui.testutils.MockRegistryAccountManagerFactory; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ButtonAssertion; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ClearConnectionManagerRule; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseShellRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWelcomePageRule; -import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWizardRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.DockerConnectionManagerUtils; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.SWTUtils; import org.eclipse.linuxtools.internal.docker.ui.views.DockerExplorerView; @@ -51,13 +52,14 @@ public class ImagePullSWTBotTest { private SWTBotView dockerExplorerViewBot; @ClassRule - public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule(); + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.DOCKER_PERSPECTIVE_ID); @Rule public ClearConnectionManagerRule clearConnectionManager = new ClearConnectionManagerRule(); @Rule - public CloseWizardRule closeWizard = new CloseWizardRule(); + public CloseShellRule closeShell = new CloseShellRule(IDialogConstants.CANCEL_LABEL); private RegistryAccountStorageManager defaultRegistryAccountStorageManager; private DockerClient client; diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePushSWTBotTests.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePushSWTBotTests.java index 9d1da2dafa..a73b741ec3 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePushSWTBotTests.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImagePushSWTBotTests.java @@ -15,6 +15,7 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.concurrent.TimeUnit; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.linuxtools.docker.core.AbstractRegistry; import org.eclipse.linuxtools.internal.docker.core.DockerConnection; import org.eclipse.linuxtools.internal.docker.core.RegistryAccountInfo; @@ -25,8 +26,8 @@ import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerConnectionF import org.eclipse.linuxtools.internal.docker.ui.testutils.MockImageFactory; import org.eclipse.linuxtools.internal.docker.ui.testutils.MockRegistryAccountManagerFactory; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ClearConnectionManagerRule; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseShellRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWelcomePageRule; -import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWizardRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ComboAssertion; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.DockerConnectionManagerUtils; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.SWTUtils; @@ -56,20 +57,21 @@ public class ImagePushSWTBotTests { private SWTBotView dockerExplorerViewBot; @ClassRule - public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule(); + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.DOCKER_PERSPECTIVE_ID); @Rule public ClearConnectionManagerRule clearConnectionManager = new ClearConnectionManagerRule(); @Rule - public CloseWizardRule closeWizard = new CloseWizardRule(); + public CloseShellRule closeShell = new CloseShellRule(IDialogConstants.CANCEL_LABEL); private RegistryAccountStorageManager defaultRegistryAccountStorageManager; private DockerClient client; @Before public void lookupDockerExplorerView() { - this.dockerExplorerViewBot = bot.viewById("org.eclipse.linuxtools.docker.ui.dockerExplorerView"); + this.dockerExplorerViewBot = SWTUtils.getSWTBotView(bot, DockerExplorerView.VIEW_ID); this.dockerExplorerView = (DockerExplorerView) (dockerExplorerViewBot.getViewReference().getView(true)); this.dockerExplorerViewBot.show(); this.dockerExplorerViewBot.setFocus(); diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageRunSWTBotTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageRunSWTBotTest.java index 37a58ef0e7..c802827384 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageRunSWTBotTest.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageRunSWTBotTest.java @@ -18,6 +18,7 @@ import java.util.concurrent.TimeUnit; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.linuxtools.internal.docker.core.DockerConnection; import org.eclipse.linuxtools.internal.docker.ui.launch.IRunDockerImageLaunchConfigurationConstants; import org.eclipse.linuxtools.internal.docker.ui.launch.LaunchConfigurationUtils; @@ -27,9 +28,10 @@ import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerClientFacto import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerConnectionFactory; import org.eclipse.linuxtools.internal.docker.ui.testutils.MockImageFactory; import org.eclipse.linuxtools.internal.docker.ui.testutils.MockImageInfoFactory; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ButtonAssertion; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ClearConnectionManagerRule; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseShellRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWelcomePageRule; -import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWizardRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.DockerConnectionManagerUtils; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.SWTUtils; import org.eclipse.linuxtools.internal.docker.ui.views.DockerExplorerView; @@ -62,13 +64,14 @@ public class ImageRunSWTBotTest { private SWTBotView dockerExplorerViewBot; @ClassRule - public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule(); + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.DOCKER_PERSPECTIVE_ID); @Rule public ClearConnectionManagerRule clearConnectionManager = new ClearConnectionManagerRule(); @Rule - public CloseWizardRule closeWizard = new CloseWizardRule(); + public CloseShellRule closeShell = new CloseShellRule(IDialogConstants.CANCEL_LABEL); @Before public void lookupDockerExplorerView() { @@ -95,9 +98,10 @@ public class ImageRunSWTBotTest { // when use an existing container name bot.textWithLabel(WizardMessages.getString("ImageRunSelectionPage.containerName")).setText("foo_bar"); // then - // wait for https://bugs.eclipse.org/bugs/show_bug.cgi?id=482889 to be able to check the wiazard validation message + // wait for https://bugs.eclipse.org/bugs/show_bug.cgi?id=482889 to be + // able to check the wizard validation message //assertThat(bot.text(WizardMessages.getString("ImageRunSelectionPage.containerWithSameName"))).isNotNull(); - assertThat(bot.button("Finish").isEnabled()).isEqualTo(false); + ButtonAssertion.assertThat(bot.button("Finish")).isNotEnabled(); } @Test diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageSearchSWTBotTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageSearchSWTBotTest.java index 5ef6009880..4eaeec732a 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageSearchSWTBotTest.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/ImageSearchSWTBotTest.java @@ -13,14 +13,15 @@ package org.eclipse.linuxtools.internal.docker.ui.wizards; import static org.assertj.core.api.Assertions.assertThat; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.linuxtools.docker.ui.wizards.ImageSearch; import org.eclipse.linuxtools.internal.docker.core.DockerConnection; import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerClientFactory; import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerConnectionFactory; import org.eclipse.linuxtools.internal.docker.ui.testutils.MockImageSearchResultFactory; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.ClearConnectionManagerRule; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseShellRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWelcomePageRule; -import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWizardRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.DockerConnectionManagerUtils; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.SWTUtils; import org.eclipse.linuxtools.internal.docker.ui.views.DockerExplorerView; @@ -45,13 +46,14 @@ public class ImageSearchSWTBotTest { private SWTBotView dockerExplorerViewBot; @ClassRule - public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule(); + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.DOCKER_PERSPECTIVE_ID); @Rule public ClearConnectionManagerRule clearConnectionManager = new ClearConnectionManagerRule(); @Rule - public CloseWizardRule closeWizard = new CloseWizardRule(); + public CloseShellRule closeShell = new CloseShellRule(IDialogConstants.CANCEL_LABEL); @Before public void lookupDockerExplorerView() { diff --git a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/NewDockerConnectionSWTBotTest.java b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/NewDockerConnectionSWTBotTest.java index ee0b57de8e..edf3e24fbc 100644 --- a/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/NewDockerConnectionSWTBotTest.java +++ b/containers/org.eclipse.linuxtools.docker.ui.tests/src/org/eclipse/linuxtools/internal/docker/ui/wizards/NewDockerConnectionSWTBotTest.java @@ -14,11 +14,12 @@ package org.eclipse.linuxtools.internal.docker.ui.wizards; import java.io.File; import java.io.IOException; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.wizard.Wizard; import org.eclipse.linuxtools.internal.docker.ui.testutils.MockDockerConnectionSettingsFinder; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CheckBoxAssertion; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWelcomePageRule; -import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseWizardRule; +import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.CloseShellRule; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.RadioAssertion; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.SWTBotTreeItemAssertions; import org.eclipse.linuxtools.internal.docker.ui.testutils.swt.SWTUtils; @@ -55,10 +56,11 @@ public class NewDockerConnectionSWTBotTest { private SWTBotView dockerExplorerViewBot; @ClassRule - public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule(); + public static CloseWelcomePageRule closeWelcomePage = new CloseWelcomePageRule( + CloseWelcomePageRule.DOCKER_PERSPECTIVE_ID); @Rule - public CloseWizardRule closeWizard = new CloseWizardRule(); + public CloseShellRule closeShell = new CloseShellRule(IDialogConstants.CANCEL_LABEL); @Before public void lookupDockerExplorerView() throws Exception { 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 ccbafea112..99b887f22b 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/META-INF/MANIFEST.MF +++ b/containers/org.eclipse.linuxtools.docker.ui/META-INF/MANIFEST.MF @@ -26,7 +26,8 @@ Require-Bundle: org.eclipse.ui, com.spotify.docker.client;bundle-version="3.1.1", org.eclipse.linuxtools.docker.editor, org.eclipse.e4.ui.workbench;bundle-version="1.4.0", - org.eclipse.e4.ui.model.workbench;bundle-version="1.2.0" + org.eclipse.e4.ui.model.workbench;bundle-version="1.2.0", + org.eclipse.tm.terminal.view.ui;bundle-version="4.1.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Bundle-Localization: plugin @@ -34,8 +35,8 @@ Export-Package: org.eclipse.linuxtools.docker.ui, org.eclipse.linuxtools.docker.ui.launch, org.eclipse.linuxtools.docker.ui.wizards, org.eclipse.linuxtools.internal.docker.ui.commands;x-friends:="org.eclipse.linuxtools.docker.ui.tests", + org.eclipse.linuxtools.internal.docker.ui.consoles;x-friends:="org.eclipse.linuxtools.docker.ui.tests", org.eclipse.linuxtools.internal.docker.ui.launch;x-friends:="org.eclipse.linuxtools.docker.ui.tests", org.eclipse.linuxtools.internal.docker.ui.preferences, org.eclipse.linuxtools.internal.docker.ui.views;x-friends:="org.eclipse.linuxtools.docker.ui.tests", - org.eclipse.linuxtools.internal.docker.ui.launch;x-friends:="org.eclipse.linuxtools.docker.ui.tests", org.eclipse.linuxtools.internal.docker.ui.wizards;x-friends:="org.eclipse.linuxtools.docker.ui.tests" diff --git a/containers/org.eclipse.linuxtools.docker.ui/plugin.properties b/containers/org.eclipse.linuxtools.docker.ui/plugin.properties index 2f7f1b66b0..01b52dabd3 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/plugin.properties +++ b/containers/org.eclipse.linuxtools.docker.ui/plugin.properties @@ -12,6 +12,9 @@ DockerPerspective.name=Docker Tooling DockerfileShortcut.label=Docker Image Build DockerfileShortcut.desc=Build an Image from a Dockerfile +DockerComposeUpShortcut.label=Docker Compose +DockerComposeUpShortcut.desc=Run with Docker Compose + TopLevelImagesViewFilter.name=Top-level images IntermediateImagesViewFilter.name=Intermediate images DanglingImagesViewFilter.name=Dangling (untagged) images @@ -20,6 +23,7 @@ StoppedContainerViewFilter.name=Stopped containers DockerPreferencePage.name=Docker LoggingPreferencePage.name=Logging DockerMachinePreferencePage.name=Docker Machine +DockerComposePreferencePage.name=Docker Compose DockerRegistryAccountPreferencePage.name=Registry Accounts Info.label=Info @@ -28,6 +32,7 @@ Settings.label=Settings BuildDockerImageLaunchConfigType.name=Build Docker Image RunDockerImageLaunchConfigType.name=Run Docker Image +DockerComposeUpLaunchConfigurationType.name=Docker Compose command.refreshimages.label=&Refresh command.refreshimages.tooltip=Refresh list of images diff --git a/containers/org.eclipse.linuxtools.docker.ui/plugin.xml b/containers/org.eclipse.linuxtools.docker.ui/plugin.xml index b97f0bc182..fa8fda9301 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/plugin.xml +++ b/containers/org.eclipse.linuxtools.docker.ui/plugin.xml @@ -23,6 +23,12 @@ </page> <page category="org.eclipse.linuxtools.docker.ui.preferences.DockerPreferencePage" + class="org.eclipse.linuxtools.internal.docker.ui.preferences.DockerComposePreferencePage" + id="org.eclipse.linuxtools.docker.ui.preferences.DockerComposePreferencePage" + name="%DockerComposePreferencePage.name"> + </page> + <page + category="org.eclipse.linuxtools.docker.ui.preferences.DockerPreferencePage" class="org.eclipse.linuxtools.internal.docker.ui.preferences.DockerRegistryAccountPreferencePage" id="org.eclipse.linuxtools.docker.ui.preferences.DockerRegistryAccountPreferencePage" name="%DockerRegistryAccountPreferencePage.name"> @@ -726,6 +732,14 @@ properties="isRunning,isStopped,isPaused,isRemovable,isUnknown" type="org.eclipse.linuxtools.docker.core.IDockerContainer"> </propertyTester> + <propertyTester + class="org.eclipse.linuxtools.internal.docker.ui.consoles.DockerComposeConsolePropertyTester" + id="org.eclipse.linuxtools.docker.dockerComposePropertyTester" + namespace="org.eclipse.linuxtools.docker.dockerComposePropertyTester" + properties="isDockerComposeConsole" + type="org.eclipse.linuxtools.internal.docker.ui.consoles.DockerComposeConsole"> + </propertyTester> + <propertyTester class="org.eclipse.linuxtools.internal.docker.ui.propertytesters.ImagePropertyTester" id="org.eclipse.linuxtools.docker.ui.imagePropertyTester" @@ -1732,11 +1746,17 @@ public="true"> </launchConfigurationType> <launchConfigurationType - delegate="org.eclipse.linuxtools.internal.docker.ui.launch.RunDockerImageLaunchConfigurationDelegate" id="org.eclipse.linuxtools.docker.ui.runDockerImageLaunchConfigurationType" + delegate="org.eclipse.linuxtools.internal.docker.ui.launch.RunDockerImageLaunchConfigurationDelegate" modes="run" name="%RunDockerImageLaunchConfigType.name"> </launchConfigurationType> + <launchConfigurationType + delegate="org.eclipse.linuxtools.internal.docker.ui.launch.DockerComposeUpLaunchConfigurationDelegate" + id="org.eclipse.linuxtools.docker.ui.dockerComposeUpLaunchConfigurationType" + modes="run" + name="%DockerComposeUpLaunchConfigurationType.name"> + </launchConfigurationType> </extension> <extension point="org.eclipse.debug.ui.launchConfigurationTypeImages"> @@ -1750,6 +1770,11 @@ icon="icons/container_started.png" id="org.eclipse.linuxtools.docker.ui.runDockerImageLaunchConfigurationTypeImage"> </launchConfigurationTypeImage> + <launchConfigurationTypeImage + configTypeID="org.eclipse.linuxtools.docker.ui.dockerComposeUpLaunchConfigurationType" + icon="icons/run_exc.png" + id="org.eclipse.linuxtools.docker.ui.dockerComposeUpLaunchConfigurationTypeImage"> + </launchConfigurationTypeImage> </extension> <extension point="org.eclipse.debug.ui.launchConfigurationTabGroups"> @@ -1763,15 +1788,36 @@ </launchConfigurationTabGroup> </extension> <extension + point="org.eclipse.debug.ui.launchConfigurationTabGroups"> + <launchConfigurationTabGroup + class="org.eclipse.linuxtools.internal.docker.ui.launch.DockerComposeUpLaunchConfigurationTabGroup" + id="org.eclipse.linuxtools.docker.ui.dockerComposeUpLaunchConfigurationTypeTabGroup" + type="org.eclipse.linuxtools.docker.ui.dockerComposeUpLaunchConfigurationType"> + <launchMode + mode="run"> + </launchMode> + </launchConfigurationTabGroup> + </extension> + <extension point="org.eclipse.ui.console.consolePageParticipants"> <consolePageParticipant - class="org.eclipse.linuxtools.internal.docker.ui.RunConsolePageParticipant" - id="org.eclipse.linuxtools.docker.ui.consolePageParticipant"> + class="org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsolePageParticipant" + id="org.eclipse.linuxtools.docker.ui.runConsolePageParticipant"> <enablement> <instanceof - value="org.eclipse.linuxtools.internal.docker.ui.RunConsole"> + value="org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole"> </instanceof></enablement> </consolePageParticipant> + <consolePageParticipant + class="org.eclipse.linuxtools.internal.docker.ui.consoles.DockerComposeConsolePageParticipant" + id="org.eclipse.linuxtools.docker.ui.dockerComposeConsolePageParticipant"> + <enablement> + <test + forcePluginActivation="true" + property="org.eclipse.linuxtools.docker.dockerComposePropertyTester.isDockerComposeConsole" + value="true"> + </test></enablement> + </consolePageParticipant> </extension> <extension point="org.eclipse.debug.ui.launchShortcuts"> @@ -1779,7 +1825,7 @@ class="org.eclipse.linuxtools.internal.docker.ui.launch.BuildDockerImageShortcut" description="%DockerfileShortcut.desc" icon="icons/build_exec.png" - id="org.eclipse.linuxtools.docker.ui.dockerfile.shortcut" + id="org.eclipse.linuxtools.docker.ui.buildDockerfileShortcut" label="%DockerfileShortcut.label" modes="run"> <contextualLaunch> @@ -1804,6 +1850,35 @@ </enablement> </contextualLaunch> </shortcut> + <shortcut + class="org.eclipse.linuxtools.internal.docker.ui.launch.DockerComposeUpShortcut" + description="%DockerComposeUpShortcut.desc" + icon="icons/run_exc.png" + id="org.eclipse.linuxtools.docker.ui.dockerComposeUpShortcut" + label="%DockerComposeUpShortcut.label" + modes="run"> + <contextualLaunch> + <enablement> + <with variable="selection"> + <count value="1"/> + <iterate + ifEmpty="false" + operator="or"> + <adapt + type="org.eclipse.core.resources.IResource"> + <and> + <test + forcePluginActivation="true" + property="org.eclipse.core.resources.name" + value="docker-compose.yml"> + </test> + </and> + </adapt> + </iterate> + </with> + </enablement> + </contextualLaunch> + </shortcut> </extension> <extension point="org.eclipse.debug.ui.launchConfigurationTabGroups"> diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/Activator.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/Activator.java index b7958589ff..549f7d4130 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/Activator.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/Activator.java @@ -60,6 +60,11 @@ public class Activator extends AbstractUIPlugin { log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, message, null)); } + public static void logWarningMessage(final String message) { + log(new Status(IStatus.WARNING, PLUGIN_ID, IStatus.WARNING, message, + null)); + } + public static void logErrorMessage(final String message, final Throwable e) { log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, message, e)); @@ -86,4 +91,5 @@ public class Activator extends AbstractUIPlugin { return null; } + } 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 146e01f4eb..8b9e55ebb0 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 @@ -33,8 +33,8 @@ import org.eclipse.linuxtools.internal.docker.core.DockerConnection; import org.eclipse.linuxtools.internal.docker.core.DockerContainerConfig; import org.eclipse.linuxtools.internal.docker.core.DockerHostConfig; import org.eclipse.linuxtools.internal.docker.core.DockerPortBinding; -import org.eclipse.linuxtools.internal.docker.ui.ConsoleOutputStream; -import org.eclipse.linuxtools.internal.docker.ui.RunConsole; +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.views.DVMessages; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; @@ -271,9 +271,7 @@ public class ContainerLauncher { final IDockerHostConfig hostConfig = hostBuilder.build(); - final IDockerConnection[] connections = DockerConnectionManager - .getInstance().getConnections(); - if (connections.length == 0) { + if (!DockerConnectionManager.getInstance().hasConnections()) { Display.getDefault() .syncExec(() -> MessageDialog.openError( PlatformUI.getWorkbench().getActiveWorkbenchWindow() @@ -285,15 +283,9 @@ public class ContainerLauncher { // Try and use the specified connection that was used before, // otherwise, open an error - int defaultIndex = -1; - String[] connectionNames = new String[connections.length]; - for (int i = 0; i < connections.length; ++i) { - connectionNames[i] = connections[i].getName(); - if (connections[i].getUri().equals(connectionUri)) - defaultIndex = i; - } - - if (defaultIndex == -1) { + final IDockerConnection connection = DockerConnectionManager + .getInstance().getConnectionByUri(connectionUri); + if (connection == null) { Display.getDefault() .syncExec(() -> MessageDialog.openError( PlatformUI.getWorkbench().getActiveWorkbenchWindow() @@ -303,9 +295,7 @@ public class ContainerLauncher { ERROR_NO_CONNECTION_WITH_URI, connectionUri))); return; - } - final IDockerConnection connection = connections[defaultIndex]; final String imageName = image; final boolean keepContainer = keep; final String consoleId = id; @@ -424,23 +414,16 @@ public class ContainerLauncher { * the container info */ public void cleanup(String connectionUri, IDockerContainerInfo info) { - final IDockerConnection[] connections = DockerConnectionManager - .getInstance().getConnections(); - if (connections.length == 0) { + if (!DockerConnectionManager.getInstance().hasConnections()) { return; } // Try and find the specified connection - IDockerConnection connection = null; - for (int i = 0; i < connections.length; ++i) { - if (connections[i].getUri().equals(connectionUri)) - connection = connections[i]; - } - + final IDockerConnection connection = DockerConnectionManager + .getInstance().getConnectionByUri(connectionUri); if (connection == null) { return; } - try { connection.killContainer(info.id()); } catch (DockerException | InterruptedException e) { diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/BuildImageCommandHandler.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/BuildImageCommandHandler.java index 0a9874e359..4ffa5b5a1d 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/BuildImageCommandHandler.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/BuildImageCommandHandler.java @@ -50,7 +50,6 @@ public class BuildImageCommandHandler extends AbstractHandler { private static final String ERROR_BUILDING_IMAGE = "ImageBuildError.msg"; //$NON-NLS-1$ private static final String IMAGE_DIRECTORY_VALIDATE = "ImageDirectoryValidate.msg"; //$NON-NLS-1$ - private IDockerConnection connection; @Override public Object execute(final ExecutionEvent event) { @@ -65,14 +64,14 @@ public class BuildImageCommandHandler extends AbstractHandler { activePage = window.getActivePage(); if (activePage != null) activePart = activePage.getActivePart(); - connection = CommandUtils.getCurrentConnection(activePart); + IDockerConnection connection = CommandUtils + .getCurrentConnection(activePart); // if no current connection, try the first connection in the list of // connections if (connection == null) { - IDockerConnection[] connections = DockerConnectionManager - .getInstance().getConnections(); - if (connections.length > 0) - connection = connections[0]; + connection = DockerConnectionManager.getInstance() + .getFirstConnection(); + } if (connection == null || !connection.isOpen()) { // if no active connection, issue error message dialog and return @@ -85,12 +84,13 @@ public class BuildImageCommandHandler extends AbstractHandler { } final boolean buildImage = wizardDialog.open() == Window.OK; if (buildImage) { - performBuildImage(wizard); + performBuildImage(wizard, connection); } return null; } - private void performBuildImage(final ImageBuild wizard) { + private void performBuildImage(final ImageBuild wizard, + final IDockerConnection connection) { final Job buildImageJob = new Job( DVMessages.getString(BUILD_IMAGE_JOB_TITLE)) { diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandMessages.properties b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandMessages.properties index 0c26b61bf9..adcbb21e2b 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandMessages.properties +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandMessages.properties @@ -1,7 +1,3 @@ -BuildImageCommandHandler.no.connections.msg=No Docker connection exists -BuildImageCommandHandler.no.connections.desc=Built images must be stored under a particular Docker Daemon, \ -but there are no existing docker connections to select. Do you wish to create a new Docker Daemon connection ? - command.showIn.propertiesView=Opening in Properties View... command.showIn.propertiesView.failure=Failed to open in Properties View diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtils.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtils.java index 11c525b724..500f0070c7 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtils.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtils.java @@ -34,7 +34,7 @@ import org.eclipse.linuxtools.docker.core.IDockerImage; import org.eclipse.linuxtools.docker.core.IDockerPortMapping; import org.eclipse.linuxtools.docker.ui.Activator; import org.eclipse.linuxtools.internal.docker.ui.DockerConnectionWatcher; -import org.eclipse.linuxtools.internal.docker.ui.RunConsole; +import org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole; import org.eclipse.linuxtools.internal.docker.ui.preferences.PreferenceConstants; import org.eclipse.linuxtools.internal.docker.ui.views.DockerContainersView; import org.eclipse.linuxtools.internal.docker.ui.views.DockerExplorerContentProvider.DockerContainerVolume; @@ -84,13 +84,10 @@ public class CommandUtils { return ((DockerImagesView) activePart).getConnection(); } else { // fall back to first active connection in list if one exists - IDockerConnection connections[] = DockerConnectionManager - .getInstance().getConnections(); - if (connections != null && connections.length > 0) { - for (int i = 0; i < connections.length; ++i) { - if (connections[i].isOpen()) - return connections[i]; - } + if (DockerConnectionManager.getInstance().hasConnections()) { + return DockerConnectionManager.getInstance().getAllConnections() + .stream().filter(c -> c.isOpen()).findFirst() + .orElse(null); } } return null; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/DisplayContainerLogCommandHandler.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/DisplayContainerLogCommandHandler.java index c766630b78..0192e328eb 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/DisplayContainerLogCommandHandler.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/DisplayContainerLogCommandHandler.java @@ -21,7 +21,7 @@ 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.internal.docker.core.DockerConnection; -import org.eclipse.linuxtools.internal.docker.ui.RunConsole; +import org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole; import org.eclipse.linuxtools.internal.docker.ui.views.DVMessages; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbenchPart; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RemoveContainerLogCommandHandler.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RemoveContainerLogCommandHandler.java index 2ff1635744..ffd4fcd299 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RemoveContainerLogCommandHandler.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RemoveContainerLogCommandHandler.java @@ -16,7 +16,7 @@ import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.docker.core.IDockerContainer; -import org.eclipse.linuxtools.internal.docker.ui.RunConsole; +import org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole; import org.eclipse.linuxtools.internal.docker.ui.views.DockerContainersView; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.handlers.HandlerUtil; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RemoveContainersCommandHandler.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RemoveContainersCommandHandler.java index 39ebf7d23b..68f95de715 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RemoveContainersCommandHandler.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RemoveContainersCommandHandler.java @@ -18,7 +18,7 @@ import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.linuxtools.docker.core.DockerException; import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.docker.core.IDockerContainer; -import org.eclipse.linuxtools.internal.docker.ui.RunConsole; +import org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole; import org.eclipse.linuxtools.internal.docker.ui.views.DVMessages; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RunImageCommandHandler.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RunImageCommandHandler.java index b7b13a4f16..3a1874bb0a 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RunImageCommandHandler.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/RunImageCommandHandler.java @@ -33,7 +33,7 @@ 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.RunConsole; +import org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole; 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.views.DockerExplorerView; @@ -82,6 +82,15 @@ public class RunImageCommandHandler extends AbstractHandler { 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 IDockerHostConfig hostConfig, final String containerName, diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/StartContainersCommandHandler.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/StartContainersCommandHandler.java index 9f7647136d..7b6c1386af 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/StartContainersCommandHandler.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/StartContainersCommandHandler.java @@ -19,7 +19,7 @@ import org.eclipse.linuxtools.docker.core.DockerException; import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.docker.core.IDockerContainer; import org.eclipse.linuxtools.internal.docker.core.DockerConnection; -import org.eclipse.linuxtools.internal.docker.ui.RunConsole; +import org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole; import org.eclipse.linuxtools.internal.docker.ui.views.DVMessages; /** diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/UnpauseContainersCommandHandler.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/UnpauseContainersCommandHandler.java index d8b096c02d..66b8ec52db 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/UnpauseContainersCommandHandler.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/UnpauseContainersCommandHandler.java @@ -18,7 +18,7 @@ import java.util.List; import org.eclipse.linuxtools.docker.core.DockerException; import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.docker.core.IDockerContainer; -import org.eclipse.linuxtools.internal.docker.ui.RunConsole; +import org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole; import org.eclipse.linuxtools.internal.docker.ui.views.DVMessages; /** diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/BuildConsole.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/BuildConsole.java index 6b69e5631d..4702318384 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/BuildConsole.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/BuildConsole.java @@ -9,7 +9,7 @@ * Red Hat - Initial Contribution *******************************************************************************/ -package org.eclipse.linuxtools.internal.docker.ui; +package org.eclipse.linuxtools.internal.docker.ui.consoles; import java.io.IOException; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ConsoleMessages.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/ConsoleMessages.java index 8c0e1a2550..2c388ce0fc 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ConsoleMessages.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/ConsoleMessages.java @@ -8,7 +8,7 @@ * Contributors: * Red Hat - Initial Contribution *******************************************************************************/ -package org.eclipse.linuxtools.internal.docker.ui; +package org.eclipse.linuxtools.internal.docker.ui.consoles; import java.text.MessageFormat; import java.util.MissingResourceException; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ConsoleMessages.properties b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/ConsoleMessages.properties index 724946752c..e14e277131 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ConsoleMessages.properties +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/ConsoleMessages.properties @@ -11,4 +11,8 @@ BuildConsole.title=Build Docker Image Console RunConsoleRemove.action=Remove Console -RunConsoleRemove.tooltip=Remove the Container Log
\ No newline at end of file +RunConsoleRemove.tooltip=Remove the Container Log + +DockerComposeConsole.title=Docker Compose Console ({0}) +DockerComposeStopAction.label=Stop +DockerComposeStopAction.tooltip=Stop services diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ConsoleOutputStream.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/ConsoleOutputStream.java index 706d70d54a..4aba1ddb32 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ConsoleOutputStream.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/ConsoleOutputStream.java @@ -8,7 +8,7 @@ * Contributors: * Red Hat - Initial Contribution *******************************************************************************/ -package org.eclipse.linuxtools.internal.docker.ui; +package org.eclipse.linuxtools.internal.docker.ui.consoles; import java.io.IOException; import java.io.OutputStream; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeConsole.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeConsole.java new file mode 100644 index 0000000000..260e06f9ad --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeConsole.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2016 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.consoles; + +import java.io.IOException; +import java.util.stream.Stream; + +import org.eclipse.debug.core.IStreamListener; +import org.eclipse.debug.core.model.IProcess; +import org.eclipse.debug.core.model.IStreamMonitor; +import org.eclipse.jface.viewers.StyledString; +import org.eclipse.linuxtools.docker.core.IDockerConnection; +import org.eclipse.linuxtools.docker.ui.Activator; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.console.IOConsole; +import org.eclipse.ui.console.IOConsoleOutputStream; + +/** + * An {@link IOConsole} for the {@code docker-compose} dockerComposeProcess. + */ +public class DockerComposeConsole extends IOConsole { + + public static final String CONSOLE_TYPE = "org.eclipse.linuxtools.internal.docker.ui.consoles.DockerComposeConsole"; + + private final IDockerConnection connection; + + private final String workingDir; + + private IProcess dockerComposeProcess; + + public DockerComposeConsole( + final IDockerConnection connection, final String workingDir) { + super(ConsoleMessages.getFormattedString("DockerComposeConsole.title", //$NON-NLS-1$ + workingDir), null); + this.workingDir = workingDir; + this.connection = connection; + setType(CONSOLE_TYPE); + } + + public IDockerConnection getConnection() { + return this.connection; + } + + public String getWorkingDir() { + return this.workingDir; + } + + public IProcess getDockerComposeProcess() { + return this.dockerComposeProcess; + } + + public void setDockerComposeProcess(final IProcess dockerComposeProcess) { + this.dockerComposeProcess = dockerComposeProcess; + // activate and clear the console if it has previous content + activate(); + clearConsole(); + // catch up with the content that was already output by the Java Process + writeContentInConsole(dockerComposeProcess.getStreamsProxy() + .getOutputStreamMonitor().getContents()); + // then follow the streams + dockerComposeProcess.getStreamsProxy().getOutputStreamMonitor() + .addListener(new IStreamListener() { + @Override + public void streamAppended(final String text, + final IStreamMonitor monitor) { + writeContentInConsole(text); + + } + }); + // dockerComposeProcess.getStreamsProxy().getErrorStreamMonitor() + // .addListener(new IStreamListener() { + // @Override + // public void streamAppended(final String text, + // final IStreamMonitor monitor) { + // writeContentInConsole(text); + // + // } + // }); + } + + private void writeContentInConsole(final String text) { + Display.getDefault().asyncExec(() -> { + final StyledString styledString = StyledTextBuilder.parse(text); + final StyleRange[] styleRanges = styledString.getStyleRanges(); + Stream.of(styleRanges).forEach(range -> { + try (final IOConsoleOutputStream consoleStream = newOutputStream()) { + consoleStream.setColor(range.foreground); + consoleStream.write(styledString.getString() + .substring(range.start, range.start + range.length) + .getBytes()); + } catch (IOException e) { + Activator.log(e); + } + }); + }); + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeConsolePageParticipant.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeConsolePageParticipant.java new file mode 100644 index 0000000000..a5ea473ff3 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeConsolePageParticipant.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2015 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 Inc - modified to use in Docker UI + *******************************************************************************/ +package org.eclipse.linuxtools.internal.docker.ui.consoles; + +import java.util.stream.Stream; + +import org.eclipse.debug.core.DebugEvent; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.IDebugEventSetListener; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.ui.console.IConsole; +import org.eclipse.ui.console.IConsoleConstants; +import org.eclipse.ui.console.IConsolePageParticipant; +import org.eclipse.ui.part.IPageBookViewPage; + +/** + * an {@link IConsolePageParticipant} for the {@code docker-compose} console. + */ +public class DockerComposeConsolePageParticipant + implements IConsolePageParticipant, IDebugEventSetListener { + + private DockerComposeConsole dockerComposeConsole; + private IPageBookViewPage dockerComposeConsolePage; + private DockerComposeStopAction stopAction; + + private boolean dockerComposeConsoleTerminated = false; + + @Override + public <T> T getAdapter(Class<T> adapter) { + return null; + } + + @Override + public void init(final IPageBookViewPage dockerComposeConsolePage, + final IConsole console) { + this.dockerComposeConsolePage = dockerComposeConsolePage; + this.dockerComposeConsole = (DockerComposeConsole) console; + this.stopAction = new DockerComposeStopAction( + dockerComposeConsole.getConnection(), + dockerComposeConsole.getWorkingDir()); + // contribute to toolbar + configureToolBar(dockerComposeConsolePage.getSite().getActionBars() + .getToolBarManager()); + if (this.dockerComposeConsole.getDockerComposeProcess() == null + || this.dockerComposeConsoleTerminated) { + this.stopAction.setEnabled(false); + } + DebugPlugin.getDefault().addDebugEventListener(this); + } + + /** + * Contribute actions to the toolbar + */ + protected void configureToolBar(final IToolBarManager toolBarManager) { + toolBarManager.appendToGroup(IConsoleConstants.LAUNCH_GROUP, + stopAction); + } + + @Override + public void dispose() { + } + + @Override + public void activated() { + } + + @Override + public void deactivated() { + } + + @Override + public void handleDebugEvents(DebugEvent[] events) { + Stream.of(events) + .filter(event -> event.getSource() + .equals(this.dockerComposeConsole + .getDockerComposeProcess())) + .forEach(event -> { + processEvent(event); + }); + + } + + private void processEvent(DebugEvent event) { + switch (event.getKind()) { + case DebugEvent.CREATE: + this.dockerComposeConsoleTerminated = false; + stopAction.setEnabled(true); + break; + case DebugEvent.TERMINATE: + this.dockerComposeConsoleTerminated = true; + stopAction.setEnabled(false); + break; + } + } +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeConsolePropertyTester.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeConsolePropertyTester.java new file mode 100644 index 0000000000..d699129a04 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeConsolePropertyTester.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2016 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.consoles; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.ui.console.MessageConsole; + +/** + * A {@link PropertyTester} for the {@code docker-compose} + * {@link MessageConsole}. + */ +public class DockerComposeConsolePropertyTester extends PropertyTester { + + @Override + public boolean test(Object receiver, String property, Object[] args, + Object expectedValue) { + return (receiver instanceof DockerComposeConsole); + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeConsoleUtils.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeConsoleUtils.java new file mode 100644 index 0000000000..509485794f --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeConsoleUtils.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2016 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.consoles; + +import java.util.stream.Stream; + +import org.eclipse.linuxtools.docker.core.IDockerConnection; +import org.eclipse.ui.console.ConsolePlugin; +import org.eclipse.ui.console.IConsole; +import org.eclipse.ui.console.MessageConsole; + +/** + * A utility class for the {@code Docker Compose} {@link MessageConsole}. + */ +public class DockerComposeConsoleUtils { + + /** + * The constant to store the working directory for a Docker Compose process + * execution. + */ + public static final String WORKING_DIR = "org.eclipse.linuxtools.internal.docker.ui.consoles.DockerComposeConsole.workingDir"; //$NON-NLS-1$ + + /** + * The constant to store the name of the connection associated with a Docker + * Compose process execution. + */ + public static final String DOCKER_CONNECTION = "org.eclipse.linuxtools.internal.docker.ui.consoles.DockerComposeConsole.dockerConnection"; //$NON-NLS-1$ + + private DockerComposeConsoleUtils() { + } + + /** + * Returns a reference to the console that is for the given container id. If + * such a console does not yet exist, it will be created. + * + * @param connection + * the {@link IDockerConnection} that is used to run the + * {@code docker-compose} command. + * + * @param workingDir + * The working directory in which the {@code docker-compose} + * command is executed. <code>null</code>. + * @return A console instance or <code>null</code> if the given workingDir + * was <code>null</code>. + */ + public static DockerComposeConsole findConsole( + final IDockerConnection connection, final String workingDir) { + if (workingDir == null) { + return null; + } + return Stream + .of(ConsolePlugin.getDefault().getConsoleManager() + .getConsoles()) + .filter(c -> c.getType() != null && c.getType() + .equals(DockerComposeConsole.CONSOLE_TYPE)) + .map(c -> (DockerComposeConsole) c) + .filter(c -> c.getAttribute(DOCKER_CONNECTION) != null + && c.getAttribute(DOCKER_CONNECTION).equals(connection) + && c.getAttribute(WORKING_DIR) != null + && c.getAttribute(WORKING_DIR).equals(workingDir)) + .findFirst() + // if no match found, create and register a new console + .orElseGet(() -> { + final DockerComposeConsole dockerComposeConsole = new DockerComposeConsole( + connection, workingDir); + dockerComposeConsole.setAttribute(DOCKER_CONNECTION, + connection); + dockerComposeConsole.setAttribute(WORKING_DIR, workingDir); + ConsolePlugin.getDefault().getConsoleManager().addConsoles( + new IConsole[] { dockerComposeConsole }); + return dockerComposeConsole; + }); + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeStopAction.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeStopAction.java new file mode 100644 index 0000000000..fe69d29cc1 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/DockerComposeStopAction.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2016 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.consoles; + +import org.eclipse.jface.action.Action; +import org.eclipse.linuxtools.docker.core.IDockerConnection; +import org.eclipse.linuxtools.internal.docker.ui.SWTImagesFactory; +import org.eclipse.linuxtools.internal.docker.ui.jobs.DockerComposeStopJob; + +/** + * An {@link Action} to stop the current {@code docker-compose} {@link Process}. + */ +public class DockerComposeStopAction extends Action { + + private final IDockerConnection connection; + + private final String workingDir; + + public DockerComposeStopAction(final IDockerConnection connection, + final String workingDir) { + super(ConsoleMessages.getString("DockerComposeStopAction.label")); //$NON-NLS-1$ + this.connection = connection; + this.workingDir = workingDir; + setToolTipText( + ConsoleMessages.getString("DockerComposeStopAction.tooltip")); //$NON-NLS-1$ + setImageDescriptor(SWTImagesFactory.DESC_STOP); + setDisabledImageDescriptor(SWTImagesFactory.DESC_STOPD); + } + + @Override + public void run() { + new DockerComposeStopJob(connection, workingDir).schedule(); + setEnabled(false); + } + + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/RunConsole.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/RunConsole.java index 418e03e78f..933d8f679f 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/RunConsole.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/RunConsole.java @@ -9,7 +9,7 @@ * Alexander Kurtakov - initial API and implementation * Red Hat Inc - modified to use in Docker UI *******************************************************************************/ -package org.eclipse.linuxtools.internal.docker.ui; +package org.eclipse.linuxtools.internal.docker.ui.consoles; import java.io.IOException; import java.io.InputStream; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/RunConsolePageParticipant.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/RunConsolePageParticipant.java index 1cd38b99fa..2b720f09ec 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/RunConsolePageParticipant.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/RunConsolePageParticipant.java @@ -8,7 +8,7 @@ * Contributors: * Red Hat Inc - modified to use in Docker UI *******************************************************************************/ -package org.eclipse.linuxtools.internal.docker.ui; +package org.eclipse.linuxtools.internal.docker.ui.consoles; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.ui.IActionBars; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/RunConsoleRemove.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/RunConsoleRemove.java index a902f18efa..946ea50c17 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/RunConsoleRemove.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/RunConsoleRemove.java @@ -8,11 +8,12 @@ * Contributors: * Red Hat Inc - modified to use in Docker UI *******************************************************************************/ -package org.eclipse.linuxtools.internal.docker.ui; +package org.eclipse.linuxtools.internal.docker.ui.consoles; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.linuxtools.internal.docker.ui.SWTImagesFactory; import org.eclipse.ui.IViewActionDelegate; import org.eclipse.ui.IViewPart; import org.eclipse.ui.console.ConsolePlugin; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/StyledTextBuilder.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/StyledTextBuilder.java new file mode 100644 index 0000000000..b1cd3649aa --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/StyledTextBuilder.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2016 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.consoles; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.jface.viewers.StyledString; +import org.eclipse.swt.custom.StyledText; + +/** + * A builder for {@link StyledText} + */ +public class StyledTextBuilder { + + /** The 'ESC' character that prefixes ANSI code sequences. */ + public static final char ESC = (char) 27; + + /** + * Parses the given {@code lineText} and returns a {@link StyledString} with + * configured foreground color on specific portions. + * + * @param lineText + * the line of text to parse + * @return the corresponding {@link StyledString} + * @see <a href="https://en.wikipedia.org/wiki/ANSI_escape_code">ANSI escape + * codes</a> + */ + public static StyledString parse(final String lineText) { + final StyledString result = new StyledString(); + // looking for blocks of characters starting with 'ESC[xxm' (where 'xx' + // is + // a color code) + // and optionally ending with 'ESC[0m' + final Pattern colorSequencePattern = Pattern + .compile("\\x1b\\[(?<colorcode>\\d{1,2})m(?<content>.*)"); //$NON-NLS-1$ + final Matcher colorSequenceMatcher = colorSequencePattern + .matcher(lineText); + int lastColorSequencePosition = 0; + int lastColorSequenceCode = 0; // default color (Black) + while (colorSequenceMatcher.find(lastColorSequencePosition)) { + final int currentColorSequenceStartPosition = colorSequenceMatcher + .start(); + final String colorCode = colorSequenceMatcher.group("colorcode"); + // catch-up with initial in-between content that has no specific + // color code boundaries or with the last color sequence position + if (lastColorSequencePosition < currentColorSequenceStartPosition) { + final String inbetweenContent = lineText.substring( + lastColorSequencePosition, + currentColorSequenceStartPosition); + if (!inbetweenContent.isEmpty()) { + result.append(inbetweenContent, + StylerBuilder.styler(lastColorSequenceCode)); + } + } + lastColorSequencePosition = currentColorSequenceStartPosition + // counting the 'ESC' char too + + (ESC + "[" + colorCode + "m").length(); + lastColorSequenceCode = Integer.parseInt(colorCode); + } + // catch-up with remaining content that has no specific color code + // boundaries + if (lastColorSequencePosition < lineText.length()) { + final String lastSequence = lineText + .substring(lastColorSequencePosition); + result.append(new StyledString(lastSequence, + StylerBuilder.styler(lastColorSequenceCode))); + } + return result; + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/StylerBuilder.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/StylerBuilder.java new file mode 100644 index 0000000000..6cffcbce6f --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/StylerBuilder.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2016 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.consoles; + +import java.util.function.Consumer; + +import org.eclipse.jface.viewers.StyledString.Styler; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.TextStyle; +import org.eclipse.swt.widgets.Display; + +/** + * A utility class to build {@link Styler} + */ +public class StylerBuilder { + + // color fg bg + // black 30 40 + // red 31 41 + // green 32 42 + // yellow 33 43 + // blue 34 44 + // purple 35 45 + // cyan 36 46 + // gray/white 37 47 + + /** + * @return a {@link Styler} configured with a {@link SWT#COLOR_BLACK} + * foreground color. + */ + public static Styler defaultStyler() { + return styler(30); + } + + /** + * Returns a {@link Styler} configured with a foreground color based on the + * given {@code}: + * <ul> + * <li>30: {@link SWT#COLOR_BLACK}</li> + * <li>31: {@link SWT#COLOR_DARK_RED}</li> + * <li>32: {@link SWT#COLOR_DARK_GREEN}</li> + * <li>33: {@link SWT#COLOR_DARK_YELLOW}</li> + * <li>34: {@link SWT#COLOR_DARK_BLUE}</li> + * <li>35: {@link SWT#COLOR_DARK_MAGENTA}</li> + * <li>36: {@link SWT#COLOR_DARK_CYAN}</li> + * <li>37: {@link SWT#COLOR_DARK_GRAY}</li> + * </ul> + * If the code is unknown, the {@link SWT#COLOR_BLACK} is used as the + * foreground color. + * + * @param code + * the code for the foreground color + * @return the configured {@link Styler} + */ + public static Styler styler(final int code) { + switch (code) { + case 31: + return styler(textStyle -> textStyle.foreground = Display.getDefault().getSystemColor(SWT.COLOR_DARK_RED)); + case 32: + return styler( + textStyle -> textStyle.foreground = Display.getDefault().getSystemColor(SWT.COLOR_DARK_GREEN)); + case 33: + return styler( + textStyle -> textStyle.foreground = Display.getDefault().getSystemColor(SWT.COLOR_DARK_YELLOW)); + case 34: + return styler(textStyle -> textStyle.foreground = Display.getDefault().getSystemColor(SWT.COLOR_DARK_BLUE)); + case 35: + return styler( + textStyle -> textStyle.foreground = Display.getDefault().getSystemColor(SWT.COLOR_DARK_MAGENTA)); + case 36: + return styler(textStyle -> textStyle.foreground = Display.getDefault().getSystemColor(SWT.COLOR_DARK_CYAN)); + case 37: + return styler(textStyle -> textStyle.foreground = Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY)); + case 30: + default: + return styler(textStyle -> textStyle.foreground = Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); + } + + } + + /** + * @return a {@link Styler} that sets the colors by the help of the given + * {@code colorSetter} what the given + * @param colorSetter + * the {@link Consumer} to call to set the colors. + */ + private static Styler styler(final Consumer<TextStyle> colorSetter) { + return new Styler() { + + @Override + public void applyStyles(final TextStyle textStyle) { + colorSetter.accept(textStyle); + } + }; + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/package-info.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/package-info.java new file mode 100644 index 0000000000..47bff1ec63 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/package-info.java @@ -0,0 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2016 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.consoles;
\ No newline at end of file diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/BuildDockerImageJob.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/BuildDockerImageJob.java index 09bb9061b5..7305e2312b 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/BuildDockerImageJob.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/BuildDockerImageJob.java @@ -32,7 +32,7 @@ import org.eclipse.linuxtools.docker.core.IDockerProgressHandler; import org.eclipse.linuxtools.docker.core.IDockerProgressMessage; import org.eclipse.linuxtools.docker.ui.Activator; import org.eclipse.linuxtools.internal.docker.core.DockerConnection; -import org.eclipse.linuxtools.internal.docker.ui.BuildConsole; +import org.eclipse.linuxtools.internal.docker.ui.consoles.BuildConsole; import org.eclipse.linuxtools.internal.docker.ui.launch.IBuildDockerImageLaunchConfigurationConstants; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/DockerComposeStopJob.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/DockerComposeStopJob.java new file mode 100644 index 0000000000..bfcbba974f --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/DockerComposeStopJob.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2016 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.jobs; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.linuxtools.docker.core.DockerException; +import org.eclipse.linuxtools.docker.core.IDockerConnection; +import org.eclipse.linuxtools.docker.core.IDockerProgressHandler; +import org.eclipse.linuxtools.docker.ui.Activator; +import org.eclipse.linuxtools.internal.docker.core.DockerCompose; +import org.eclipse.linuxtools.internal.docker.ui.preferences.PreferenceConstants; + +/** + * An {@link IDockerProgressHandler} {@link Job} to execute a + * {@code docker-compose stop} commandline. + */ +public class DockerComposeStopJob extends Job { + + /** The {@link IDockerConnection} to use. */ + private final IDockerConnection connection; + + /** The workDir containing the {@code docker-compose.yml}. */ + private final String workingDir; + + /** + * Constructor + * + * @param connection + * the {@link IDockerConnection} to use + * @param workingDir + * the workDir containing the {@code docker-compose.yml} + */ + public DockerComposeStopJob(final IDockerConnection connection, + final String workingDir) { + super(JobMessages.getString("DockerComposeStop.title")); //$NON-NLS-1$ + this.connection = connection; + this.workingDir = workingDir; + } + + @Override + protected IStatus run(final IProgressMonitor monitor) { + final String dockerComposeInstallDir = Activator.getDefault() + .getPreferenceStore().getString( + PreferenceConstants.DOCKER_COMPOSE_INSTALLATION_DIRECTORY); + try { + final Process dockerComposeStopProcess = DockerCompose.getInstance() + .stop(this.connection, + dockerComposeInstallDir, this.workingDir); + dockerComposeStopProcess.waitFor(); + } catch (InterruptedException | DockerException e) { + Activator.logErrorMessage( + JobMessages.getString("DockerComposeStop.error"), e); //$NON-NLS-1$ + } + return Status.OK_STATUS; + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/DockerComposeUpJob.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/DockerComposeUpJob.java new file mode 100644 index 0000000000..aa863ed65a --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/DockerComposeUpJob.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (c) 2016 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.jobs; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.core.Launch; +import org.eclipse.debug.core.model.IProcess; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.linuxtools.docker.core.DockerException; +import org.eclipse.linuxtools.docker.core.IDockerConnection; +import org.eclipse.linuxtools.docker.core.IDockerProgressHandler; +import org.eclipse.linuxtools.docker.ui.Activator; +import org.eclipse.linuxtools.internal.docker.core.DockerCompose; +import org.eclipse.linuxtools.internal.docker.ui.consoles.DockerComposeConsole; +import org.eclipse.linuxtools.internal.docker.ui.consoles.DockerComposeConsoleUtils; +import org.eclipse.linuxtools.internal.docker.ui.preferences.PreferenceConstants; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.console.ConsolePlugin; + +/** + * An {@link IDockerProgressHandler} {@link Job} to run the + * {@code docker-compose up} commandline. + */ +public class DockerComposeUpJob extends Job { + + /** The {@link IDockerConnection} to use. */ + private final IDockerConnection connection; + + /** The workingDir containing the {@code docker-compose.yml}. */ + private final String workingDir; + + /** The {@link ILaunchConfiguration} that was used to launch the job. */ + private final ILaunchConfiguration launchConfiguration; + + /** The dockerComposeConsole used to display output messages. */ + private final DockerComposeConsole dockerComposeConsole; + + /** + * Constructor + * + * @param connection + * the {@link IDockerConnection} to use + * @param workingDir + * the workingDir containing the {@code docker-compose.yml} + * @param launchConfiguration + */ + public DockerComposeUpJob(final IDockerConnection connection, + final String workingDir, + final ILaunchConfiguration launchConfiguration) { + super(JobMessages.getString("DockerComposeUp.title")); //$NON-NLS-1$ + this.connection = connection; + this.workingDir = workingDir; + this.launchConfiguration = launchConfiguration; + this.dockerComposeConsole = DockerComposeConsoleUtils + .findConsole(connection, workingDir); + } + + @Override + protected IStatus run(final IProgressMonitor monitor) { + final String dockerComposeInstallDir = Activator.getDefault() + .getPreferenceStore().getString( + PreferenceConstants.DOCKER_COMPOSE_INSTALLATION_DIRECTORY); + + final Thread commandThread = new Thread(() -> { + // open console view + ConsolePlugin.getDefault().getConsoleManager() + .showConsoleView(dockerComposeConsole); + try { + // run the 'docker-compose up' command + final Process dockerComposeSystemProcess = DockerCompose + .getInstance() + .up(this.connection, dockerComposeInstallDir, + this.workingDir); + final ILaunch launch = new Launch(launchConfiguration, + ILaunchManager.RUN_MODE, null); + final IProcess dockerComposeProcess = DebugPlugin.newProcess( + launch, dockerComposeSystemProcess, + "docker-compose up"); //$NON-NLS-1$ + dockerComposeConsole + .setDockerComposeProcess(dockerComposeProcess); // $NON-NLS-1$ + final int exitCode = dockerComposeSystemProcess.waitFor(); + if (exitCode != 0) { + Activator.logErrorMessage( + "'docker-compose up' exited with code " + exitCode); //$NON-NLS-1$ + } + } catch (DockerException | InterruptedException e) { + Display.getDefault() + .asyncExec(() -> MessageDialog.openError( + Display.getCurrent().getActiveShell(), + JobMessages.getString( + "DockerCompose.dialog.title"), //$NON-NLS-1$ + e.getMessage())); + Activator.log(e); + } + + }); + commandThread.start(); + return Status.OK_STATUS; + + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/JobMessages.properties b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/JobMessages.properties index 6d89693187..7fbb111032 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/JobMessages.properties +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/jobs/JobMessages.properties @@ -12,4 +12,8 @@ BuildImageJob.title=Building Docker Image BuildImageError.msg=Error while building Docker Image SkipEmptydockerfile.msg=Skipping empty Docker build file. -RetrieveImageHierarchyJob.title=Retrieving Docker Image hierarchy
\ No newline at end of file +RetrieveImageHierarchyJob.title=Retrieving Docker Image hierarchy +DockerCompose.dialog.title=Docker Compose +DockerComposeUp.title=Running 'docker-compose up' command +DockerComposeStop.title=Stopping Docker Compose... +DockerComposeStop.error=Docker Compose failed to stop diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/BaseResourceAwareLaunchShortcut.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/BaseResourceAwareLaunchShortcut.java new file mode 100644 index 0000000000..04a8790881 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/BaseResourceAwareLaunchShortcut.java @@ -0,0 +1,163 @@ +package org.eclipse.linuxtools.internal.docker.ui.launch; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationType; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugModelPresentation; +import org.eclipse.debug.ui.ILaunchShortcut; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.linuxtools.docker.core.IDockerConnection; +import org.eclipse.linuxtools.docker.ui.Activator; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.dialogs.ElementListSelectionDialog; + +/** + * Base class for {@link ILaunchShortcut} that rely on an + * {@link IDockerConnection} and an {@link IResource}. A matching + * {@link ILaunchConfiguration} may be retrieved from the selected + * {@link IResource} or a new one may be created if needed. + */ +public abstract class BaseResourceAwareLaunchShortcut implements ILaunchShortcut { + + @Override + public void launch(ISelection selection, String mode) { + if (selection instanceof IStructuredSelection) { + IResource resource = (IResource) ((IStructuredSelection) selection) + .toArray()[0]; + launch(resource, mode); + } + } + + @Override + public void launch(IEditorPart editor, String mode) { + launch(editor.getEditorInput().getAdapter(IResource.class), mode); + } + + /** + * Locate a configuration to launch for the given type. If one cannot be + * found, create one. + * + * @param resource + * The {@code docker-compose.yml} to look up launch for. + * + * @return A re-useable config or <code>null</code> if none was found. + */ + protected ILaunchConfiguration findLaunchConfiguration( + final String configTypeId, final IResource resource, + final Predicate<ILaunchConfiguration> predicate) { + final ILaunchConfigurationType configType = LaunchConfigurationUtils + .getLaunchConfigType( + configTypeId); + final List<ILaunchConfiguration> candidateConfigs = new ArrayList<>(); + try { + final ILaunchConfiguration[] configs = DebugPlugin.getDefault() + .getLaunchManager().getLaunchConfigurations(configType); + Stream.of(configs).filter(predicate) + .forEach(config -> candidateConfigs.add(config)); + } catch (CoreException e) { + Activator.log(e); + } + + // If there are no existing configurations associated with the + // given resource, + // create one. If there is exactly one configuration associated with the + // given resource, return it. Otherwise, if there is more than one + // configuration associated with the given resource, prompt the user to + // choose + // one. + int candidateCount = candidateConfigs.size(); + if (candidateCount < 1) { + return createConfiguration(resource); + } else if (candidateCount == 1) { + return candidateConfigs.get(0); + } else { + // Prompt the user to choose a configuration. A null result means + // the user + // cancelled the dialog, in which case this method returns null, + // since canceling the dialog should also cancel launching + // anything. + return chooseConfiguration(candidateConfigs); + } + } + + /** + * Get the path of the {@code Dockerfile}. + * + * @param sourcePathLocation + * - location path of the {@code Dockerfile} + * @param sourcePathWorkspaceRelativeLocation + * - true, if path above is relative to workspace + * @return the absolute file path of the {@code Dockerfile} + */ + public static IPath getPath(final String sourcePathLocation, + final boolean sourcePathWorkspaceRelativeLocation) { + if (sourcePathWorkspaceRelativeLocation) { + final IResource resource = ResourcesPlugin.getWorkspace().getRoot() + .findMember(new Path(sourcePathLocation)); + if (resource != null) + return resource.getLocation(); + else // return an empty path that won't match an existing resource + return new Path(""); //$NON-NLS-1$ + } + return new Path(sourcePathLocation); + } + + protected abstract ILaunchConfiguration createConfiguration( + final IResource resource); + + /** + * Show a selection dialog that allows the user to choose one of the + * specified launch configurations. + * + * @param configList + * The list of launch configurations to choose from. + * @return The chosen config, or <code>null</code> if the user cancelled the + * dialog. + */ + protected ILaunchConfiguration chooseConfiguration(List<ILaunchConfiguration> configList) { + IDebugModelPresentation labelProvider = DebugUITools + .newDebugModelPresentation(); + ElementListSelectionDialog dialog = new ElementListSelectionDialog( + getActiveWorkbenchShell(), labelProvider); + dialog.setElements(configList.toArray()); + dialog.setTitle( + LaunchMessages.getString( + "DockerComposeUpShortcutConfigSelection.title")); //$NON-NLS-1$ + dialog.setMessage( + LaunchMessages + .getString("DockerComposeUpShortcutChooseLaunch.msg")); //$NON-NLS-1$ + dialog.setMultipleSelection(false); + int result = dialog.open(); + labelProvider.dispose(); + if (result == IStatus.OK) { + return (ILaunchConfiguration) dialog.getFirstResult(); + } + return null; + } + + /** + * Get the active Workbench shell. + * + * @return active shell as returned by the plug-in + */ + protected Shell getActiveWorkbenchShell() { + return Activator.getActiveWorkbenchShell(); + } + + protected abstract void launch(IResource resource, String mode); + +}
\ No newline at end of file diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/BuildDockerImageLaunchConfigurationDelegate.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/BuildDockerImageLaunchConfigurationDelegate.java index f2cec9cd53..942bcb5e6b 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/BuildDockerImageLaunchConfigurationDelegate.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/BuildDockerImageLaunchConfigurationDelegate.java @@ -38,7 +38,6 @@ import org.eclipse.linuxtools.docker.core.DockerConnectionManager; import org.eclipse.linuxtools.docker.core.DockerException; import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.docker.ui.Activator; -import org.eclipse.linuxtools.internal.docker.core.DockerConnection; import org.eclipse.linuxtools.internal.docker.ui.jobs.BuildDockerImageJob; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; @@ -69,8 +68,8 @@ public class BuildDockerImageLaunchConfigurationDelegate .getAttribute(DOCKER_CONNECTION, (String) null); final String repoName = configuration.getAttribute(REPO_NAME, (String) null); - final DockerConnection connection = (DockerConnection) getDockerConnection( - connectionName); + final IDockerConnection connection = DockerConnectionManager + .getInstance().getConnectionByName(connectionName); final Map<String, Object> buildOptions = new HashMap<>(); buildOptions.put(QUIET_BUILD, configuration.getAttribute(QUIET_BUILD, false)); @@ -102,22 +101,4 @@ public class BuildDockerImageLaunchConfigurationDelegate } } - /** - * Finds the {@link IDockerConnection} from the given name - * - * @param connectionName - * the name of the connection to find - * @return the {@link IDockerConnection} or <code>null</code> if none - * matched. - */ - private IDockerConnection getDockerConnection(final String connectionName) { - for (IDockerConnection connection : DockerConnectionManager - .getInstance().getConnections()) { - if (connection.getName().equals(connectionName)) { - return connection; - } - } - return null; - } - } diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/BuildDockerImageShortcut.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/BuildDockerImageShortcut.java index b86a902114..d7c2189f33 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/BuildDockerImageShortcut.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/BuildDockerImageShortcut.java @@ -11,90 +11,37 @@ package org.eclipse.linuxtools.internal.docker.ui.launch; -import java.util.ArrayList; -import java.util.List; +import java.util.function.Predicate; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Path; -import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.ui.DebugUITools; -import org.eclipse.debug.ui.IDebugModelPresentation; import org.eclipse.debug.ui.ILaunchShortcut; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.jface.viewers.ILabelProviderListener; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.linuxtools.docker.core.DockerConnectionManager; -import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.docker.ui.Activator; -import org.eclipse.linuxtools.internal.docker.ui.SWTImagesFactory; -import org.eclipse.linuxtools.internal.docker.ui.commands.CommandMessages; import org.eclipse.linuxtools.internal.docker.ui.commands.CommandUtils; import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageBuildDialog; import org.eclipse.linuxtools.internal.docker.ui.wizards.NewDockerConnection; -import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IEditorPart; import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.dialogs.ElementListSelectionDialog; -public class BuildDockerImageShortcut implements ILaunchShortcut { - private static final String LaunchShortcut_Config_Selection = "ImageBuildShortcutConfigSelection.title"; //$NON-NLS-1$ - private static final String LaunchShortcut_Choose_Launch = "ImageBuildShortcutChooseLaunch.msg"; //$NON-NLS-1$ - private static final String LaunchShortcut_Connection_Selection = "ImageBuildShortcutConnectionSelection.title"; //$NON-NLS-1$ - private static final String LaunchShortcut_Choose_Connection = "ImageBuildShortcutChooseConnection.msg"; //$NON-NLS-1$ +/** + * An {@link ILaunchShortcut} to build a Docker image from a selected + * Dockerfile. + */ +public class BuildDockerImageShortcut + extends BaseResourceAwareLaunchShortcut { @Override - public void launch(ISelection selection, String mode) { - if (selection instanceof IStructuredSelection) { - IResource resource = (IResource) ((IStructuredSelection) selection) - .toArray()[0]; - launch(resource, mode); - } - } - - @Override - public void launch(IEditorPart editor, String mode) { - launch(editor.getEditorInput().getAdapter(IResource.class), mode); - } - - public void launch(IResource resource, String mode) { - final ILaunchConfiguration config = findLaunchConfiguration(resource); - if (config != null) { - DebugUITools.launch(config, mode); - } else { - Activator.logErrorMessage( - "Unable to find the launch configuration to build the Docker image from the selected Dockerfile."); - } - } - - /** - * Locate a configuration to launch for the given type. If one cannot be - * found, create one. - * - * @param resource - * The Dockerfile to look up launch for. - * - * @return A re-useable config or <code>null</code> if none. - */ - protected ILaunchConfiguration findLaunchConfiguration(IResource resource) { - final ILaunchConfigurationType configType = LaunchConfigurationUtils - .getLaunchConfigType( - IBuildDockerImageLaunchConfigurationConstants.CONFIG_TYPE_ID); - final List<ILaunchConfiguration> candidateConfigs = new ArrayList<>(); - try { - final ILaunchConfiguration[] configs = DebugPlugin.getDefault() - .getLaunchManager().getLaunchConfigurations(configType); - for (ILaunchConfiguration config : configs) { + protected void launch(IResource resource, String mode) { + // the predicate to apply on the launch configuration to find the + // matching candidates + final Predicate<ILaunchConfiguration> predicate = config -> { + try { final String sourcePath = config.getAttribute( IBuildDockerImageLaunchConfigurationConstants.SOURCE_PATH_LOCATION, ""); //$NON-NLS-1$ @@ -103,85 +50,51 @@ public class BuildDockerImageShortcut implements ILaunchShortcut { false); final IPath dockerfilePath = getPath(sourcePath, workspaceRelative); - if (dockerfilePath - .equals(resource.getLocation().removeLastSegments(1))) { - candidateConfigs.add(config); - } + return dockerfilePath + .equals(resource.getLocation().removeLastSegments(1)); + } catch (CoreException e) { + Activator.log(e); + return false; } - } catch (CoreException e) { - Activator.log(e); - } + }; - // If there are no existing configurations associated with the - // Dockerfile, - // create one. If there is exactly one configuration associated with the - // Dockerfile, return it. Otherwise, if there is more than one - // configuration associated with the Dockerfile, prompt the user to - // choose - // one. - int candidateCount = candidateConfigs.size(); - if (candidateCount < 1) { - return createConfiguration(resource); - } else if (candidateCount == 1) { - return candidateConfigs.get(0); + final ILaunchConfiguration config = findLaunchConfiguration( + IBuildDockerImageLaunchConfigurationConstants.CONFIG_TYPE_ID, + resource, predicate); + if (config != null) { + DebugUITools.launch(config, mode); } else { - // Prompt the user to choose a configuration. A null result means - // the user - // cancelled the dialog, in which case this method returns null, - // since canceling the dialog should also cancel launching - // anything. - return chooseConfiguration(candidateConfigs); - } - } - - /** - * Get the path of the Dockerfile. - * - * @param sourcePathLocation - * - location path of the Dockerfile - * @param sourcePathWorkspaceRelativeLocation - * - true, if path above is relative to workspace - * @return the absolute file path of the Dockerfile - */ - private IPath getPath(final String sourcePathLocation, - final boolean sourcePathWorkspaceRelativeLocation) { - if (sourcePathWorkspaceRelativeLocation) { - IResource resource = ResourcesPlugin.getWorkspace().getRoot() - .findMember(new Path(sourcePathLocation)); - if (resource != null) - return resource.getLocation(); - else // return an empty path that won't match an existing resource - return new Path(""); //$NON-NLS-1$ + Activator.logErrorMessage( + LaunchMessages.getString( + "BuildDockerImageShortcut.launchconfig.error")); //$NON-NLS-1$ } - return new Path(sourcePathLocation); } - + /** * Create a launch configuration based on a Dockerfile resource, and * optionally save it to the underlying resource. * * @param dockerfile - * a Dockerfile file to build + * a {@code Dockerfile} file to build * @return a launch configuration generated for the Dockerfile build. */ + @Override protected ILaunchConfiguration createConfiguration( final IResource dockerfile) { try { - final IDockerConnection[] connections = DockerConnectionManager - .getInstance().getConnections(); - if (connections.length == 0) { + if (!DockerConnectionManager.getInstance().hasConnections()) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { boolean confirm = MessageDialog.openQuestion( PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getShell(), - CommandMessages.getString( - "BuildImageCommandHandler.no.connections.msg"), //$NON-NLS-1$ - CommandMessages.getString( - "BuildImageCommandHandler.no.connections.desc")); //$NON-NLS-1$ + LaunchMessages.getString( + "BuildDockerImageShortcut.no.connections.msg"), //$NON-NLS-1$ + LaunchMessages.getString( + "BuildDockerImageShortcut.no.connections.desc")); //$NON-NLS-1$ if (confirm) { - NewDockerConnection newConnWizard = new NewDockerConnection(); + final NewDockerConnection newConnWizard = new NewDockerConnection(); CommandUtils.openWizard(newConnWizard, PlatformUI.getWorkbench() .getActiveWorkbenchWindow() @@ -207,110 +120,4 @@ public class BuildDockerImageShortcut implements ILaunchShortcut { return null; } - - private class ConnectionSelectionLabelProvider implements ILabelProvider { - - private Image CONNECTION_IMAGE = SWTImagesFactory.DESC_REPOSITORY_MIDDLE - .createImage(); - - @Override - public void removeListener(ILabelProviderListener listener) { - } - - @Override - public boolean isLabelProperty(Object element, String property) { - return false; - } - - @Override - public void dispose() { - CONNECTION_IMAGE.dispose(); - } - - @Override - public void addListener(ILabelProviderListener listener) { - } - - @Override - public String getText(Object element) { - return element.toString(); - } - - @Override - public Image getImage(Object element) { - return CONNECTION_IMAGE; - } - } - - /** - * Show a selection dialog that allows the user to choose one of the - * connections to use to build the Image. - * - * @param connections - * Array of connections. - * @return The chosen connection, or <code>null</code> if the user cancelled - * the dialog. - */ - protected IDockerConnection chooseConnection( - IDockerConnection[] connections) { - IDebugModelPresentation labelProvider = DebugUITools - .newDebugModelPresentation(); - ElementListSelectionDialog dialog = new ElementListSelectionDialog( - getActiveWorkbenchShell(), - new ConnectionSelectionLabelProvider() { - - }); - - dialog.setElements(connections); - dialog.setTitle( - LaunchMessages.getString(LaunchShortcut_Connection_Selection)); - dialog.setMessage( - LaunchMessages.getString(LaunchShortcut_Choose_Connection)); - dialog.setMultipleSelection(false); - int result = dialog.open(); - labelProvider.dispose(); - if (result == IStatus.OK) { - return (IDockerConnection) dialog.getFirstResult(); - } - return null; - } - - /** - * Show a selection dialog that allows the user to choose one of the - * specified launch configurations. - * - * @param configList - * The list of launch configurations to choose from. - * @return The chosen config, or <code>null</code> if the user cancelled the - * dialog. - */ - protected ILaunchConfiguration chooseConfiguration( - List<ILaunchConfiguration> configList) { - IDebugModelPresentation labelProvider = DebugUITools - .newDebugModelPresentation(); - ElementListSelectionDialog dialog = new ElementListSelectionDialog( - getActiveWorkbenchShell(), labelProvider); - dialog.setElements(configList.toArray()); - dialog.setTitle( - LaunchMessages.getString(LaunchShortcut_Config_Selection)); - dialog.setMessage( - LaunchMessages.getString(LaunchShortcut_Choose_Launch)); - dialog.setMultipleSelection(false); - int result = dialog.open(); - labelProvider.dispose(); - if (result == IStatus.OK) { - return (ILaunchConfiguration) dialog.getFirstResult(); - } - return null; - } - - /** - * Get the active Workbench shell. - * - * @return active shell as returned by the plug-in - */ - protected Shell getActiveWorkbenchShell() { - return Activator.getActiveWorkbenchShell(); - } - } diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeUpLaunchConfigurationDelegate.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeUpLaunchConfigurationDelegate.java new file mode 100644 index 0000000000..afa91b4359 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeUpLaunchConfigurationDelegate.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2016 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.launch; + +import static org.eclipse.linuxtools.internal.docker.ui.launch.IDockerComposeLaunchConfigurationConstants.DOCKER_CONNECTION; +import static org.eclipse.linuxtools.internal.docker.ui.launch.IDockerComposeLaunchConfigurationConstants.WORKING_DIR; +import static org.eclipse.linuxtools.internal.docker.ui.launch.IDockerComposeLaunchConfigurationConstants.WORKING_DIR_WORKSPACE_RELATIVE_LOCATION; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.model.ILaunchConfigurationDelegate; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.ILaunchGroup; +import org.eclipse.linuxtools.docker.core.DockerConnectionManager; +import org.eclipse.linuxtools.docker.core.IDockerConnection; +import org.eclipse.linuxtools.internal.docker.ui.jobs.DockerComposeUpJob; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; + +/** + * The {@link ILaunchConfigurationDelegate} to run the "docker-compose up' + * command from the directory containing the specified 'docker-compose.yml' + * file. + */ +public class DockerComposeUpLaunchConfigurationDelegate + implements ILaunchConfigurationDelegate { + + @Override + public void launch(final ILaunchConfiguration configuration, + final String mode, final ILaunch launch, + final IProgressMonitor monitor) throws CoreException { + final String sourcePathLocation = configuration + .getAttribute(WORKING_DIR, (String) null); + final boolean sourcePathWorkspaceRelativeLocation = configuration + .getAttribute(WORKING_DIR_WORKSPACE_RELATIVE_LOCATION, false); + final IPath sourcePath = BuildDockerImageUtils.getPath( + sourcePathLocation, sourcePathWorkspaceRelativeLocation); + final String connectionName = configuration + .getAttribute(DOCKER_CONNECTION, (String) null); + final IDockerConnection connection = DockerConnectionManager + .getInstance().getConnectionByName(connectionName); + if (connection != null && sourcePath != null) { + final Job dockerComposeUpJob = new DockerComposeUpJob(connection, + sourcePath.toOSString(), configuration); + dockerComposeUpJob.schedule(); + } else { + final ILaunchGroup launchGroup = DebugUITools + .getLaunchGroup(configuration, "run"); //$NON-NLS-1$ + // prompt the user with the launch configuration editor + Display.getDefault() + .syncExec(() -> DebugUITools.openLaunchConfigurationDialog( + PlatformUI.getWorkbench().getActiveWorkbenchWindow() + .getShell(), + configuration, launchGroup.getIdentifier(), null)); + + } + } +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeUpLaunchConfigurationMainTab.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeUpLaunchConfigurationMainTab.java new file mode 100644 index 0000000000..1e2f3e8067 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeUpLaunchConfigurationMainTab.java @@ -0,0 +1,296 @@ +/******************************************************************************* + * Copyright (c) 2015, 2016 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.internal.docker.ui.launch; + +import static org.eclipse.linuxtools.internal.docker.ui.launch.IDockerComposeLaunchConfigurationConstants.DOCKER_CONNECTION; +import static org.eclipse.linuxtools.internal.docker.ui.launch.IDockerComposeLaunchConfigurationConstants.WORKING_DIR; +import static org.eclipse.linuxtools.internal.docker.ui.launch.IDockerComposeLaunchConfigurationConstants.WORKING_DIR_WORKSPACE_RELATIVE_LOCATION; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.linuxtools.docker.core.DockerConnectionManager; +import org.eclipse.linuxtools.docker.ui.Activator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.DirectoryDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; +import org.eclipse.ui.model.WorkbenchContentProvider; +import org.eclipse.ui.model.WorkbenchLabelProvider; +import org.eclipse.ui.views.navigator.ResourceComparator; + +/** + * The main launch configuration tab for the {@code docker-compose up} process. + */ +public class DockerComposeUpLaunchConfigurationMainTab + extends AbstractLaunchConfigurationTab { + + /** the Docker daemon to use for the image build. */ + private ComboViewer connectionSelectionComboViewer; + /** the path to the docker compose config file. */ + private Text dockerComposeWorkingDirPathText; + /** + * whether path to the docker compose config file is relative to the + * workspace or not. + */ + private boolean dockerComposeFilePathWorkspaceRelative; + + @Override + public void createControl(final Composite parent) { + final Composite container = new Composite(parent, SWT.BORDER); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL) + .grab(true, false).applyTo(container); + GridLayoutFactory.fillDefaults().margins(6, 6).applyTo(container); + setControl(container); + + // connection selection + final Group connectionGroup = new Group(container, SWT.BORDER); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL) + .grab(true, false).applyTo(connectionGroup); + GridLayoutFactory.fillDefaults().numColumns(2).margins(6, 6) + .applyTo(connectionGroup); + connectionGroup.setText(LaunchMessages.getString( + "DockerComposeUpLaunchConfigurationMainTab.connection.group.label")); //$NON-NLS-1$ + connectionGroup.setToolTipText(LaunchMessages.getString( + "DockerComposeUpLaunchConfigurationMainTab.connection.group.tooltip")); //$NON-NLS-1$ + final Combo connectionSelectionCombo = new Combo(connectionGroup, + SWT.NONE); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .grab(true, false).applyTo(connectionSelectionCombo); + this.connectionSelectionComboViewer = new ComboViewer( + connectionSelectionCombo); + this.connectionSelectionComboViewer + .setContentProvider(new ArrayContentProvider()); + this.connectionSelectionComboViewer.setInput( + DockerConnectionManager.getInstance().getConnectionNames()); + connectionSelectionCombo + .addSelectionListener(new LaunchConfigurationChangeListener()); + // docker compose config file + createDockerComposeWorkingDirLocationGroup(container); + } + + private void createDockerComposeWorkingDirLocationGroup(final Composite container) { + final Group dockerComposeWorkingDirLocationGroup = new Group(container, + SWT.BORDER); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL) + .grab(true, false).applyTo(dockerComposeWorkingDirLocationGroup); + GridLayoutFactory.fillDefaults().margins(6, 6).numColumns(3) + .applyTo(dockerComposeWorkingDirLocationGroup); + dockerComposeWorkingDirLocationGroup + .setText(LaunchMessages.getString( + "DockerComposeUpLaunchConfigurationMainTab.dockerComposePath.group.label")); //$NON-NLS-1$ + this.dockerComposeWorkingDirPathText = new Text(dockerComposeWorkingDirLocationGroup, + SWT.BORDER); + this.dockerComposeWorkingDirPathText + .addModifyListener(new LaunchConfigurationChangeListener()); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .grab(true, false).span(3, 1) + .applyTo(this.dockerComposeWorkingDirPathText); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .grab(true, false) + .applyTo(new Label(dockerComposeWorkingDirLocationGroup, SWT.NONE)); + final Button browseWorkspaceButton = new Button( + dockerComposeWorkingDirLocationGroup, SWT.NONE); + browseWorkspaceButton.setText(LaunchMessages.getString( + "DockerComposeUpLaunchConfigurationMainTab.dockerComposePath.browseworkspace.button.label")); //$NON-NLS-1$ + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .grab(false, false).applyTo(browseWorkspaceButton); + browseWorkspaceButton.addSelectionListener( + onBrowseWorkspace(dockerComposeWorkingDirPathText, IContainer.class)); + final Button browseFileSystemButton = new Button( + dockerComposeWorkingDirLocationGroup, SWT.NONE); + browseFileSystemButton.setText(LaunchMessages.getString( + "DockerComposeUpLaunchConfigurationMainTab.dockerComposePath.browsefilesystem.button.label")); //$NON-NLS-1$ + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .grab(false, false).applyTo(browseFileSystemButton); + browseFileSystemButton.addSelectionListener( + onBrowseFileSystemForDirectory(this.dockerComposeWorkingDirPathText)); + } + + /** + * Opens a dialog to browse the workspace + * + * @return + */ + private SelectionListener onBrowseWorkspace(final Text pathText, + final Class<?> expectedType) { + return new SelectionAdapter() { + + @Override + public void widgetSelected(final SelectionEvent e) { + final ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog( + getShell(), new WorkbenchLabelProvider(), + new WorkbenchContentProvider()); + dialog.setInput(ResourcesPlugin.getWorkspace().getRoot()); + dialog.setTitle(LaunchMessages.getString( + "DockerComposeUpLaunchConfigurationMainTab.dockerComposePath.browseworkspace.dialog.title")); //$NON-NLS-1$ + dialog.setComparator( + new ResourceComparator(ResourceComparator.NAME)); + dialog.setAllowMultiple(false); + dialog.setValidator(selection -> { + if (selection.length == 1 && expectedType + .isAssignableFrom(selection[0].getClass())) { + return new Status(IStatus.OK, Activator.PLUGIN_ID, + null); + } + return new Status(IStatus.ERROR, Activator.PLUGIN_ID, null); + }); + if (dialog.open() == IDialogConstants.OK_ID) { + final IResource selection = (IResource) dialog + .getFirstResult(); + pathText.setText(selection.getFullPath().toOSString()); + dockerComposeFilePathWorkspaceRelative = true; + } + } + }; + } + + /** + * Opens a dialog to browse the file system and select a directory + * + * @return + */ + private SelectionListener onBrowseFileSystemForDirectory( + final Text pathText) { + return new SelectionAdapter() { + + @Override + public void widgetSelected(final SelectionEvent e) { + final DirectoryDialog dialog = new DirectoryDialog(getShell()); + final String selection = dialog.open(); + if (selection != null) { + pathText.setText(selection); + dockerComposeFilePathWorkspaceRelative = false; + } + } + }; + } + + @Override + public void setDefaults( + final ILaunchConfigurationWorkingCopy configuration) { + } + + @Override + public void initializeFrom(final ILaunchConfiguration configuration) { + try { + this.connectionSelectionComboViewer + .setSelection(new StructuredSelection( + configuration.getAttribute(DOCKER_CONNECTION, ""))); + this.dockerComposeWorkingDirPathText + .setText(configuration.getAttribute(WORKING_DIR, "")); + this.dockerComposeFilePathWorkspaceRelative = configuration + .getAttribute(WORKING_DIR_WORKSPACE_RELATIVE_LOCATION, + false); + } catch (CoreException e) { + Activator.log(e); + } + } + + @Override + public boolean isValid(final ILaunchConfiguration launchConfig) { + try { + // verify the connection + final String dockerConnection = launchConfig + .getAttribute(DOCKER_CONNECTION, ""); // $NON-NLS-1$ + // verify the source path + final String sourcePathLocation = launchConfig + .getAttribute(WORKING_DIR, ""); // $NON-NLS-1$ + final boolean sourcePathWorkspaceRelativeLocation = launchConfig + .getAttribute(WORKING_DIR_WORKSPACE_RELATIVE_LOCATION, + false); + final IPath sourcePath = BuildDockerImageUtils.getPath( + sourcePathLocation, sourcePathWorkspaceRelativeLocation); + if (dockerConnection.isEmpty() || dockerConnection == null + || DockerConnectionManager.getInstance() + .findConnection(dockerConnection) == null) { + setErrorMessage(LaunchMessages.getString( + "DockerComposeUpLaunchConfigurationMainTab.connection.missing")); //$NON-NLS-1$ + return false; + } else if (sourcePathLocation.isEmpty() || sourcePath == null) { + setErrorMessage(LaunchMessages.getString( + "DockerComposeUpLaunchConfigurationMainTab.dockerComposePath.missing")); //$NON-NLS-1$ + return false; + } else if (!sourcePath.append("docker-compose.yml").toFile() + .exists()) { + setErrorMessage(LaunchMessages.getString( + "DockerComposeUpLaunchConfigurationMainTab.dockerComposePath.missingDockerComposeFile")); //$NON-NLS-1$ + return false; + } else { + setErrorMessage(null); + } + } catch (CoreException e) { + Activator.log(e); + } + return super.isValid(launchConfig); + } + + @Override + public void performApply( + final ILaunchConfigurationWorkingCopy configuration) { + final IStructuredSelection connectionSelection = (IStructuredSelection) this.connectionSelectionComboViewer + .getSelection(); + if (connectionSelection.getFirstElement() != null) { + configuration.setAttribute(DOCKER_CONNECTION, + connectionSelection.getFirstElement().toString()); + } + configuration.setAttribute(WORKING_DIR, + this.dockerComposeWorkingDirPathText.getText()); + configuration.setAttribute(WORKING_DIR_WORKSPACE_RELATIVE_LOCATION, + this.dockerComposeFilePathWorkspaceRelative); + } + + @Override + public String getName() { + return LaunchMessages + .getString("DockerComposeUpLaunchConfigurationMainTab.name"); //$NON-NLS-1$ + } + + private class LaunchConfigurationChangeListener extends SelectionAdapter + implements ModifyListener { + + @Override + public void modifyText(final ModifyEvent e) { + updateLaunchConfigurationDialog(); + } + + @Override + public void widgetSelected(final SelectionEvent e) { + updateLaunchConfigurationDialog(); + } + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeUpLaunchConfigurationTabGroup.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeUpLaunchConfigurationTabGroup.java new file mode 100644 index 0000000000..ed7494816c --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeUpLaunchConfigurationTabGroup.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 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.launch; + +import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup; +import org.eclipse.debug.ui.ILaunchConfigurationDialog; +import org.eclipse.debug.ui.ILaunchConfigurationTab; + +/** + * The launch configuration tab group to edit the launch configuration for the + * {@code docker-compose up} process. + */ +public class DockerComposeUpLaunchConfigurationTabGroup + extends AbstractLaunchConfigurationTabGroup { + + @Override + public void createTabs(ILaunchConfigurationDialog dialog, String mode) { + setTabs(new ILaunchConfigurationTab[] { + new DockerComposeUpLaunchConfigurationMainTab(), + new org.eclipse.debug.ui.CommonTab() }); + } + + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeUpShortcut.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeUpShortcut.java new file mode 100644 index 0000000000..a17db9632f --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/DockerComposeUpShortcut.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2016 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.launch; + +import java.util.function.Predicate; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.ILaunchShortcut; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.linuxtools.docker.core.DockerConnectionManager; +import org.eclipse.linuxtools.docker.ui.Activator; +import org.eclipse.linuxtools.internal.docker.ui.commands.CommandUtils; +import org.eclipse.linuxtools.internal.docker.ui.wizards.DockerComposeUpDialog; +import org.eclipse.linuxtools.internal.docker.ui.wizards.NewDockerConnection; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; + +/** + * An {@link ILaunchShortcut} to run the {@code docker-compose up} command from + * a specified {@code docker-compose.yml} file. + */ +public class DockerComposeUpShortcut extends BaseResourceAwareLaunchShortcut { + + @Override + protected void launch(IResource resource, String mode) { + // the predicate to apply on the launch configuration to find the + // matching candidates + final Predicate<ILaunchConfiguration> predicate = config -> { + try { + final String sourcePath = config.getAttribute( + IDockerComposeLaunchConfigurationConstants.WORKING_DIR, + ""); //$NON-NLS-1$ + final boolean workspaceRelative = config.getAttribute( + IDockerComposeLaunchConfigurationConstants.WORKING_DIR_WORKSPACE_RELATIVE_LOCATION, + false); + final IPath dockerfilePath = getPath(sourcePath, + workspaceRelative); + return dockerfilePath + .equals(resource.getLocation().removeLastSegments(1)); + } catch (CoreException e) { + Activator.log(e); + return false; + } + }; + + final ILaunchConfiguration config = findLaunchConfiguration( + IDockerComposeLaunchConfigurationConstants.CONFIG_TYPE_ID, + resource, predicate); + + if (config != null) { + DebugUITools.launch(config, mode); + } else { + Activator.logErrorMessage(LaunchMessages + .getString("DockerComposeUpShortcut.launchconfig.error")); //$NON-NLS-1$ + } + } + + /** + * Create a launch configuration based on a {@code docker-compose.yml} + * resource, and optionally save it to the underlying resource. + * + * @param dockerComposeScript + * a {@code docker-compose.yml} file to use + * + * @return a launch configuration generated for the + * {@code docker-compose.yml}. + */ + @Override + protected ILaunchConfiguration createConfiguration( + final IResource dockerComposeScript) { + try { + if (!DockerConnectionManager.getInstance().hasConnections()) { + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + final boolean confirm = MessageDialog.openQuestion( + PlatformUI.getWorkbench() + .getActiveWorkbenchWindow().getShell(), + LaunchMessages.getString( + "DockerComposeUpShortcut.no.connections.msg"), //$NON-NLS-1$ + LaunchMessages.getString( + "DockerComposeUpShortcut.no.connections.desc")); //$NON-NLS-1$ + if (confirm) { + final NewDockerConnection newConnWizard = new NewDockerConnection(); + CommandUtils.openWizard(newConnWizard, + PlatformUI.getWorkbench() + .getActiveWorkbenchWindow() + .getShell()); + } + } + }); + return null; + } else { + final DockerComposeUpDialog dialog = new DockerComposeUpDialog( + getActiveWorkbenchShell()); + final int result = dialog.open(); + if (result == IDialogConstants.OK_ID) { + return LaunchConfigurationUtils + .createDockerComposeUpLaunchConfiguration( + dialog.getSelectedConnection(), + dockerComposeScript); + } + } + } catch (CoreException e) { + Activator.log(e); + } + return null; + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/IDockerComposeLaunchConfigurationConstants.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/IDockerComposeLaunchConfigurationConstants.java new file mode 100644 index 0000000000..ffde050234 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/IDockerComposeLaunchConfigurationConstants.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2015, 2016 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.launch; + +import org.eclipse.debug.core.ILaunchConfiguration; + +/** + * Constants used to pass values in the {@link ILaunchConfiguration} to build + * Docker Images. + * + */ +public interface IDockerComposeLaunchConfigurationConstants { + + /** name of the connection to use to build the Image. */ + String DOCKER_CONNECTION = "dockerConnection"; //$NON-NLS-1$ + + /** + * the launch id + */ + String CONFIG_TYPE_ID = "org.eclipse.linuxtools.docker.ui.dockerComposeUpLaunchConfigurationType"; //$NON-NLS-1$ + + /** the working directory to execute the 'docker compose' command. */ + String WORKING_DIR = "workingDir"; //$NON-NLS-1$ + + /** + * marker to indicate if the {@code WORKING_DIR} is a workspace-relative + * location. + */ + String WORKING_DIR_WORKSPACE_RELATIVE_LOCATION = "workingDirWorkspaceRelativeLocation"; //$NON-NLS-1$ + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/LaunchConfigurationUtils.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/LaunchConfigurationUtils.java index 40db500afc..0b57b8525f 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/LaunchConfigurationUtils.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/LaunchConfigurationUtils.java @@ -128,27 +128,28 @@ public class LaunchConfigurationUtils { final ILaunchConfigurationType type = manager .getLaunchConfigurationType( IRunDockerImageLaunchConfigurationConstants.CONFIG_TYPE_ID); - final String imageName = image.repoTags().get(0); + final String imageName = createRunImageLaunchConfigurationName(image); // using the image repo + first tag - final ILaunchConfigurationWorkingCopy workingCopy = getLaunchConfigurationworkingCopy( + final ILaunchConfigurationWorkingCopy workingCopy = getLaunchConfigurationWorkingCopy( type, imageName); workingCopy.setAttribute(CREATION_DATE, DATE_FORMAT.format(new Date())); workingCopy.setAttribute(CONNECTION_NAME, image.getConnection().getName()); workingCopy.setAttribute(IMAGE_ID, image.id()); - workingCopy.setAttribute(IMAGE_NAME, image.repoTags().get(0)); + workingCopy.setAttribute(IMAGE_NAME, createRunImageLaunchConfigurationName(image)); if (containerName != null && !containerName.isEmpty()) { workingCopy.setAttribute(CONTAINER_NAME, containerName); } // if we know the raw command string, use it since the container // config will remove quotes to split up command properly DockerContainerConfig config = (DockerContainerConfig) containerConfig; - if (config.rawcmd() != null) + if (config.rawcmd() != null) { workingCopy.setAttribute(COMMAND, config.rawcmd()); - else + } else { workingCopy.setAttribute(COMMAND, toString(containerConfig.cmd())); + } workingCopy.setAttribute(ENTRYPOINT, toString(containerConfig.entrypoint())); // selected ports @@ -222,6 +223,11 @@ public class LaunchConfigurationUtils { return null; } + private static String createRunImageLaunchConfigurationName( + final IDockerImage image) { + return image.repoTags().get(0); + } + private static String toString(final List<String> input) { final StringBuilder command = new StringBuilder(); for (Iterator<String> iterator = input.iterator(); iterator @@ -380,7 +386,7 @@ public class LaunchConfigurationUtils { * {@link ILaunchConfiguration} or a new instance if none was found. * @throws CoreException */ - private static ILaunchConfigurationWorkingCopy getLaunchConfigurationworkingCopy( + private static ILaunchConfigurationWorkingCopy getLaunchConfigurationWorkingCopy( final ILaunchConfigurationType type, final String imageName) throws CoreException { final ILaunchConfiguration existingLaunchConfiguration = getLaunchConfigurationByImageName( @@ -527,7 +533,8 @@ public class LaunchConfigurationUtils { * the Dockerfile to use to build the image * @return the {@link ILaunchConfiguration} name */ - public static String createLaunchConfigurationName(final String imageName, + public static String createBuildImageLaunchConfigurationName( + final String imageName, final IResource resource) { if (imageName != null) { final String repository = BuildDockerImageUtils @@ -574,11 +581,9 @@ public class LaunchConfigurationUtils { final ILaunchConfigurationType configType = LaunchConfigurationUtils .getLaunchConfigType( IBuildDockerImageLaunchConfigurationConstants.CONFIG_TYPE_ID); - final ILaunchConfigurationWorkingCopy wc = configType.newInstance(null, - DebugPlugin.getDefault().getLaunchManager() - .generateLaunchConfigurationName( - createLaunchConfigurationName(repoName, - dockerfile))); + final ILaunchConfigurationWorkingCopy wc = getLaunchConfigurationWorkingCopy( + configType, + createBuildImageLaunchConfigurationName(repoName, dockerfile)); wc.setAttribute( IBuildDockerImageLaunchConfigurationConstants.SOURCE_PATH_LOCATION, dockerfile.getFullPath().removeLastSegments(1).toString()); @@ -593,6 +598,57 @@ public class LaunchConfigurationUtils { } /** + * Creates an {@link ILaunchConfiguration} for to run the + * {@code docker-compose up} command. + * + * @param connection + * the Docker connection to use + * @param dockerComposeScript + * the {@code docker-compose.yml} script + * @return the created {@link ILaunchConfiguration} + * @throws CoreException + * if something wrong happened when creating the + * {@link ILaunchConfiguration} + */ + public static ILaunchConfiguration createDockerComposeUpLaunchConfiguration( + final IDockerConnection connection, + final IResource dockerComposeScript) throws CoreException { + final ILaunchConfigurationType configType = LaunchConfigurationUtils + .getLaunchConfigType( + IDockerComposeLaunchConfigurationConstants.CONFIG_TYPE_ID); + final ILaunchConfigurationWorkingCopy wc = configType.newInstance(null, + DebugPlugin.getDefault().getLaunchManager() + .generateLaunchConfigurationName( + createDockerComposeLaunchConfigurationName( + dockerComposeScript))); + wc.setAttribute(IDockerComposeLaunchConfigurationConstants.WORKING_DIR, + dockerComposeScript.getFullPath().removeLastSegments(1) + .toString()); + wc.setAttribute( + IDockerComposeLaunchConfigurationConstants.WORKING_DIR_WORKSPACE_RELATIVE_LOCATION, + true); + + wc.setAttribute( + IDockerComposeLaunchConfigurationConstants.DOCKER_CONNECTION, + connection.getName()); + return wc.doSave(); + } + + /** + * Creates a Launch Configuration name from the given + * {@code dockerComposeScript}. + * + * @param dockerComposeScript + * the name of the {@code Docker Compose} script + * @return the {@link ILaunchConfiguration} name + */ + private static String createDockerComposeLaunchConfigurationName( + final IResource dockerComposeScript) { + return "Docker Compose [" //$NON-NLS-1$ + + dockerComposeScript.getProject().getName() + "]"; //$NON-NLS-1$ + } + + /** * Updates all {@link ILaunchConfiguration} of the given {@code type} where * there is an attribute with the given {@code attributeName} of the given * {@code oldValue}, and sets the {@code newValue} instead. @@ -639,4 +695,5 @@ public class LaunchConfigurationUtils { e); } } + } 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 4cd8631f40..4656df033a 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 @@ -30,6 +30,11 @@ BuildDockerImageLaunchConfigurationMainTab.options.noCache.button.label=Do not u BuildDockerImageLaunchConfigurationMainTab.options.rm.button.label=Remove intermediate containers after a successful build BuildDockerImageLaunchConfigurationMainTab.options.forceRM.button.label=Always remove intermediate containers +BuildDockerImageShortcut.launchconfig.error=Unable to find the launch configuration to build the Docker image from the selected Dockerfile. +BuildDockerImageShortcut.no.connections.msg=No Docker connection exists +BuildDockerImageShortcut.no.connections.desc=Built images must be stored under a particular Docker Daemon, \ +but there are no existing docker connections to select. Do you wish to create a new Docker Daemon connection ? + ImageBuildShortcut.error.msg=Error while building Docker Image ImageBuildShortcutConfigSelection.title=Launch Configuration Selection ImageBuildShortcutChooseLaunch.msg=Choose a launch configuration to run @@ -53,4 +58,22 @@ RunLabelsTab.name=Labels NoConnectionError.msg=No Docker connection exists UpdateLaunchConfiguration.named.error=Failed to update launch configuration named ''{0}'' after connection name changed -UpdateLaunchConfiguration.error=Failed to retrieve launch configurations after connection name changed
\ No newline at end of file +UpdateLaunchConfiguration.error=Failed to retrieve launch configurations after connection name changed + +DockerComposeUpShortcut.launchconfig.error=Unable to find the launch configuration to run Docker Compose from the selected file. +DockerComposeUpShortcut.no.connections.msg=No Docker connection exists +DockerComposeUpShortcut.no.connections.desc=Docker Compose must be executed on a particular Docker Daemon, \ +but there are no existing docker connections to select. Do you wish to create a new Docker Daemon connection ? + +DockerComposeUpLaunchConfigurationMainTab.name=Main +DockerComposeUpLaunchConfigurationMainTab.connection.group.label=Docker Connection +DockerComposeUpLaunchConfigurationMainTab.connection.group.tooltip=The docker daemon that will be used to run the 'docker-compose up' command +DockerComposeUpLaunchConfigurationMainTab.connection.missing=Docker Connection is missing or invalid +DockerComposeUpLaunchConfigurationMainTab.dockerComposePath.group.label=Docker Compose Working Directory: +DockerComposeUpLaunchConfigurationMainTab.dockerComposePath.missing=Docker Compose working directory is missing or invalid +DockerComposeUpLaunchConfigurationMainTab.dockerComposePath.missingDockerComposeFile=Docker Compose working directory does not contain a 'docker-compose.yml' file +DockerComposeUpLaunchConfigurationMainTab.dockerComposePath.browseworkspace.button.label=Browse Workspace... +DockerComposeUpLaunchConfigurationMainTab.dockerComposePath.browseworkspace.dialog.title=Browse Workspace... +DockerComposeUpLaunchConfigurationMainTab.dockerComposePath.browsefilesystem.button.label=Browse File System... +DockerComposeUpShortcutConfigSelection.title=Docker Compose Configuration +DockerComposeUpShortcutChooseLaunch.msg=Select the launch configuration to run 'docker-compose' diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/RunImageLaunchConfigurationTabGroup.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/RunImageLaunchConfigurationTabGroup.java index 1ec64af463..05585cf5e6 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/RunImageLaunchConfigurationTabGroup.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/RunImageLaunchConfigurationTabGroup.java @@ -15,7 +15,6 @@ import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup; import org.eclipse.debug.ui.ILaunchConfigurationDialog; import org.eclipse.linuxtools.docker.core.DockerConnectionManager; import org.eclipse.linuxtools.docker.core.DockerException; -import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.internal.docker.ui.commands.CommandUtils; import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageRunResourceVolumesVariablesModel; import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageRunSelectionModel; @@ -39,11 +38,9 @@ public class RunImageLaunchConfigurationTabGroup @Override public void createTabs(ILaunchConfigurationDialog dialog, String mode) { - IDockerConnection[] connections = DockerConnectionManager.getInstance() - .getConnections(); runSelectionModel = null; runVolumesModel = null; - if (connections != null && connections.length > 0) { + if (DockerConnectionManager.getInstance().hasConnections()) { runSelectionModel = new ImageRunSelectionModel( CommandUtils.getCurrentConnection(null)); try { diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/RunImageMainTab.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/RunImageMainTab.java index 69c65d080a..b80eaa5a25 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/RunImageMainTab.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/RunImageMainTab.java @@ -178,7 +178,8 @@ public class RunImageMainTab extends AbstractLaunchConfigurationTab { connectionSelectionCombo); connectionSelectionComboViewer .setContentProvider(new ArrayContentProvider()); - connectionSelectionComboViewer.setInput(getConnectionNames()); + connectionSelectionComboViewer.setInput(DockerConnectionManager + .getInstance().getConnectionNames().toArray()); dbc.bindValue( WidgetProperties.selection().observe(connectionSelectionCombo), BeanProperties @@ -289,15 +290,6 @@ public class RunImageMainTab extends AbstractLaunchConfigurationTab { ImageRunSelectionModel.COMMAND).observe(model)); } - private String[] getConnectionNames() { - IDockerConnection[] connections = DockerConnectionManager.getInstance().getConnections(); - ArrayList<String> connectionNames = new ArrayList<>(); - for (IDockerConnection connection : connections) { - connectionNames.add(connection.getName()); - } - return connectionNames.toArray(new String[] {}); - } - /** * Creates an {@link IContentProposalProvider} to propose * {@link IDockerImage} names based on the current text. @@ -493,18 +485,13 @@ public class RunImageMainTab extends AbstractLaunchConfigurationTab { // no connections if (model == null) return; - final IDockerConnection[] connections = DockerConnectionManager - .getInstance() - .getConnections(); try { - String defaultConnectionName = ""; //$NON-NLS-1$ - // Default to first active connection name - if (connections != null && connections.length > 0) { - for (int i = 0; i < connections.length; ++i) { - if (connections[i].isOpen()) - defaultConnectionName = connections[i].getName(); - } - } + final String defaultConnectionName = DockerConnectionManager + .getInstance().getAllConnections().stream() + .filter(connection -> connection.isOpen()) + .map(connection -> connection.getName()).findFirst() + .orElse(""); //$NON-NLS-1$ + // Mark in error if there is no active connection if (defaultConnectionName.equals("")) { //$NON-NLS-1$ setErrorMessage(WizardMessages diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/DockerComposePreferencePage.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/DockerComposePreferencePage.java new file mode 100644 index 0000000000..38931ea1d0 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/DockerComposePreferencePage.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2014 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.preferences; + +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.preference.DirectoryFieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.StringFieldEditor; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.linuxtools.docker.ui.Activator; +import org.eclipse.linuxtools.internal.docker.core.DockerCompose; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +/** + * The {@link IWorkbenchPreferencePage} for the Docker Compose settings. + */ +public class DockerComposePreferencePage extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + + /** + * The {@link DirectoryFieldEditor} to select the installation directory for + * the {@code docker-compose} command. + */ + private DirectoryFieldEditor dockerComposeInstallDir; + + /** + * Constructor. + */ + public DockerComposePreferencePage() { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription(PreferenceMessages.getString("DockerCompose.message")); //$NON-NLS-1$ + } + + @Override + public void init(final IWorkbench workbench) { + } + + @Override + protected void createFieldEditors() { + // installation directory for docker-compose + this.dockerComposeInstallDir = new CustomDirectoryFieldEditor( + PreferenceConstants.DOCKER_COMPOSE_INSTALLATION_DIRECTORY, + PreferenceMessages.getString("DockerComposePath.label"), //$NON-NLS-1$ + getFieldEditorParent()) { + @Override + protected boolean checkState() { + if (isEmptyStringAllowed() + && !this.getStringValue().isEmpty()) { + final boolean validPath = super.checkState(); + if (!validPath) { + return false; + } + if (!DockerCompose.getInstance() + .checkPathToDockerCompose(this.getStringValue())) { + setWarningMessage(NLS.bind( + org.eclipse.linuxtools.docker.core.Messages.Docker_Compose_Command_Not_Found, + this.getStringValue())); + return true; + } + } + setMessage(""); + return true; + } + }; + addField(this.dockerComposeInstallDir); + this.dockerComposeInstallDir.setPreferenceStore(getPreferenceStore()); + // allow empty value if docker-machine is not installed + this.dockerComposeInstallDir.setEmptyStringAllowed(true); + this.dockerComposeInstallDir + .setValidateStrategy(StringFieldEditor.VALIDATE_ON_KEY_STROKE); + this.dockerComposeInstallDir.setPage(this); + this.dockerComposeInstallDir.setErrorMessage( + PreferenceMessages + .getString("DockerComposePath.invalid.label")); //$NON-NLS-1$ + this.dockerComposeInstallDir.showErrorMessage(); + this.dockerComposeInstallDir.load(); + } + + private void setWarningMessage(final String message) { + super.setMessage(message, IMessageProvider.WARNING); + } + + /** + * Subclass of the {@link DirectoryFieldEditor} but with the + * {@link StringFieldEditor#VALIDATE_ON_KEY_STROKE} validation strategy. + */ + private static class CustomDirectoryFieldEditor + extends DirectoryFieldEditor { + + public CustomDirectoryFieldEditor(String name, String labelText, + Composite parent) { + init(name, labelText); + setErrorMessage(JFaceResources + .getString("DirectoryFieldEditor.errorMessage"));//$NON-NLS-1$ + setChangeButtonText(JFaceResources.getString("openBrowse"));//$NON-NLS-1$ + setValidateStrategy(StringFieldEditor.VALIDATE_ON_KEY_STROKE); + createControl(parent); + } + + + + } +}
\ No newline at end of file diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/DockerMachinePreferencePage.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/DockerMachinePreferencePage.java index 4fbee4aea4..46b3311bb1 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/DockerMachinePreferencePage.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/DockerMachinePreferencePage.java @@ -22,12 +22,15 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; +/** + * The {@link IWorkbenchPreferencePage} for the Docker Machine settings. + */ public class DockerMachinePreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { /** * The {@link DirectoryFieldEditor} to select the installation directory for - * the Docker-Machine command. + * the {@code docker-machine} command. */ private DirectoryFieldEditor dockerMachineInstallDir; @@ -37,10 +40,13 @@ public class DockerMachinePreferencePage extends FieldEditorPreferencePage */ private DirectoryFieldEditor vmDriverInstallDir; + /** + * Constructor. + */ public DockerMachinePreferencePage() { super(GRID); setPreferenceStore(Activator.getDefault().getPreferenceStore()); - setDescription(Messages.getString("DockerMachine.message")); //$NON-NLS-1$ + setDescription(PreferenceMessages.getString("DockerMachine.message")); //$NON-NLS-1$ } @Override @@ -52,7 +58,7 @@ public class DockerMachinePreferencePage extends FieldEditorPreferencePage // installation directory for docker-machine this.dockerMachineInstallDir = new CustomDirectoryFieldEditor( PreferenceConstants.DOCKER_MACHINE_INSTALLATION_DIRECTORY, - Messages.getString("DockerMachinePath.label"), //$NON-NLS-1$ + PreferenceMessages.getString("DockerMachinePath.label"), //$NON-NLS-1$ getFieldEditorParent()) { @Override protected boolean checkState() { @@ -82,13 +88,13 @@ public class DockerMachinePreferencePage extends FieldEditorPreferencePage .setValidateStrategy(StringFieldEditor.VALIDATE_ON_KEY_STROKE); this.dockerMachineInstallDir.setPage(this); this.dockerMachineInstallDir.setErrorMessage( - Messages.getString("DockerMachinePath.invalid.label")); //$NON-NLS-1$ + PreferenceMessages.getString("DockerMachinePath.invalid.label")); //$NON-NLS-1$ this.dockerMachineInstallDir.showErrorMessage(); this.dockerMachineInstallDir.load(); // installation directory for underlying VM driver this.vmDriverInstallDir = new CustomDirectoryFieldEditor( PreferenceConstants.VM_DRIVER_INSTALLATION_DIRECTORY, - Messages.getString("VMDriverPath.label"), //$NON-NLS-1$ + PreferenceMessages.getString("VMDriverPath.label"), //$NON-NLS-1$ getFieldEditorParent()); addField(this.vmDriverInstallDir); this.vmDriverInstallDir.setPreferenceStore(getPreferenceStore()); @@ -96,7 +102,7 @@ public class DockerMachinePreferencePage extends FieldEditorPreferencePage this.vmDriverInstallDir.setPage(this); this.vmDriverInstallDir.setEmptyStringAllowed(true); this.vmDriverInstallDir.setErrorMessage( - Messages.getString("VMDriverPath.invalid.label")); //$NON-NLS-1$ + PreferenceMessages.getString("VMDriverPath.invalid.label")); //$NON-NLS-1$ this.vmDriverInstallDir.showErrorMessage(); this.vmDriverInstallDir .setValidateStrategy(StringFieldEditor.VALIDATE_ON_KEY_STROKE); diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/DockerPreferencePage.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/DockerPreferencePage.java index 365c73ee21..9ea511eb54 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/DockerPreferencePage.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/DockerPreferencePage.java @@ -83,14 +83,14 @@ public class DockerPreferencePage extends PreferencePage implements GridLayoutFactory.fillDefaults().margins(0, 0).spacing(10, 2).applyTo(container); refreshTimeField = new IntegerFieldEditor( PreferenceConstants.REFRESH_TIME, - Messages.getString(REFRESH_TIME_MSG), container); + PreferenceMessages.getString(REFRESH_TIME_MSG), container); refreshTimeField.setPreferenceStore(getPreferenceStore()); refreshTimeField .setValidateStrategy(StringFieldEditor.VALIDATE_ON_KEY_STROKE); refreshTimeField.setValidRange(5, 200); refreshTimeField.setPage(this); refreshTimeField - .setErrorMessage(Messages.getString(INVALID_REFRESH_TIME_MSG)); + .setErrorMessage(PreferenceMessages.getString(INVALID_REFRESH_TIME_MSG)); refreshTimeField.showErrorMessage(); refreshTimeField.load(); // If the preference changes, alert the Refresh Manager diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/LoggingPreferencePage.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/LoggingPreferencePage.java index 141e2f3804..16d0d71256 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/LoggingPreferencePage.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/LoggingPreferencePage.java @@ -40,12 +40,12 @@ public class LoggingPreferencePage extends FieldEditorPreferencePage implements protected void createFieldEditors() { autoLogOnStart = new BooleanFieldEditor( PreferenceConstants.AUTOLOG_ON_START, - Messages.getString(AUTO_START_MSG), getFieldEditorParent()); + PreferenceMessages.getString(AUTO_START_MSG), getFieldEditorParent()); addField(autoLogOnStart); addTimeStamp = new BooleanFieldEditor( PreferenceConstants.LOG_TIMESTAMP, - Messages.getString(TIME_STAMP_MSG), getFieldEditorParent()); + PreferenceMessages.getString(TIME_STAMP_MSG), getFieldEditorParent()); addField(addTimeStamp); } diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/PreferenceConstants.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/PreferenceConstants.java index ed0bc39ba8..898f93da9c 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/PreferenceConstants.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/PreferenceConstants.java @@ -24,9 +24,13 @@ public class PreferenceConstants { /** the installation directory for Docker Machine. */ public static final String DOCKER_MACHINE_INSTALLATION_DIRECTORY = "dockerMachineInstallDir"; //$NON-NLS-1$ + /** * the installation directory for the VM driver (eg, VirtualBox). */ public static final String VM_DRIVER_INSTALLATION_DIRECTORY = "vmDriverInstallDir"; //$NON-NLS-1$ + /** the installation directory for Docker Compose. */ + public static final String DOCKER_COMPOSE_INSTALLATION_DIRECTORY = "dockerComposeInstallDir"; //$NON-NLS-1$ + } diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/PreferenceInitializer.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/PreferenceInitializer.java index ae6e21557f..2552b04375 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/PreferenceInitializer.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/PreferenceInitializer.java @@ -11,6 +11,7 @@ package org.eclipse.linuxtools.internal.docker.ui.preferences; import static org.eclipse.linuxtools.internal.docker.ui.preferences.PreferenceConstants.AUTOLOG_ON_START; +import static org.eclipse.linuxtools.internal.docker.ui.preferences.PreferenceConstants.DOCKER_COMPOSE_INSTALLATION_DIRECTORY; import static org.eclipse.linuxtools.internal.docker.ui.preferences.PreferenceConstants.DOCKER_MACHINE_INSTALLATION_DIRECTORY; import static org.eclipse.linuxtools.internal.docker.ui.preferences.PreferenceConstants.LOG_TIMESTAMP; import static org.eclipse.linuxtools.internal.docker.ui.preferences.PreferenceConstants.REFRESH_TIME; @@ -37,17 +38,16 @@ public class PreferenceInitializer extends AbstractPreferenceInitializer { if (SystemUtils.isWindows()) { store.setDefault(DOCKER_MACHINE_INSTALLATION_DIRECTORY, "C:\\Program Files\\Docker Toolbox"); //$NON-NLS-1$ + store.setDefault(DOCKER_COMPOSE_INSTALLATION_DIRECTORY, + "C:\\Program Files\\Docker Toolbox"); //$NON-NLS-1$ store.setDefault(VM_DRIVER_INSTALLATION_DIRECTORY, "C:\\Program Files\\Oracle\\VirtualBox"); //$NON-NLS-1$ - } else if (SystemUtils.isMac()) { + } else if (SystemUtils.isMac() || SystemUtils.isLinux()) { store.setDefault(DOCKER_MACHINE_INSTALLATION_DIRECTORY, "/usr/local/bin"); //$NON-NLS-1$ store.setDefault(VM_DRIVER_INSTALLATION_DIRECTORY, "/usr/local/bin"); //$NON-NLS-1$ - } else if (SystemUtils.isLinux()) { - store.setDefault(DOCKER_MACHINE_INSTALLATION_DIRECTORY, - "/usr/local/bin"); //$NON-NLS-1$ - store.setDefault(VM_DRIVER_INSTALLATION_DIRECTORY, + store.setDefault(DOCKER_COMPOSE_INSTALLATION_DIRECTORY, "/usr/local/bin"); //$NON-NLS-1$ } } diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/Messages.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/PreferenceMessages.java index 0df875cfe0..3379aefdee 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/Messages.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/PreferenceMessages.java @@ -14,9 +14,9 @@ import java.text.MessageFormat; import java.util.MissingResourceException; import java.util.ResourceBundle; -public class Messages { +public class PreferenceMessages { - private static final String BUNDLE_NAME = Messages.class.getName(); + private static final String BUNDLE_NAME = PreferenceMessages.class.getName(); public static String getString(String key) { try { diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/Messages.properties b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/PreferenceMessages.properties index cff6d392a0..44b2ad446a 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/Messages.properties +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/preferences/PreferenceMessages.properties @@ -14,9 +14,15 @@ DefaultHost.label=Default Docker Host AutoLogOnStart.label=Automatically log when Container starts LogTimeStamp.label=Request time stamp for logs PreferencesDesc.txt=Preferences for Docker Manager Plug-ins + DockerMachine.label=Docker Machine DockerMachine.message=Specify the installation directories for Docker Machine and for the underlying VM Driver it uses. DockerMachinePath.label=Docker Machine DockerMachinePath.invalid.label=Path to 'docker-machine' is invalid VMDriverPath.label=VM Driver VMDriverPath.invalid.label=Path to VM driver installation directory is invalid + +DockerCompose.label=Docker Compose +DockerCompose.message=Specify the installation directory for Docker Compose. +DockerComposePath.label=Docker Compose +DockerComposePath.invalid.label=Path to 'docker-compose' is invalid diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/propertytesters/ConnectionPropertyTester.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/propertytesters/ConnectionPropertyTester.java index 0a54b8ecb3..538615c1b3 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/propertytesters/ConnectionPropertyTester.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/propertytesters/ConnectionPropertyTester.java @@ -34,7 +34,8 @@ public class ConnectionPropertyTester extends PropertyTester { case EXISTS_ACTIVE_CONNECTION: return expectedValue.equals(DockerConnectionWatcher.getInstance().getConnection() != null); case EXISTS_ANY_CONNECTION: - return expectedValue.equals(DockerConnectionManager.getInstance().getConnections().length > 0); + return expectedValue.equals( + DockerConnectionManager.getInstance().hasConnections()); } return false; } diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/utils/DisplayUtils.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/utils/DisplayUtils.java new file mode 100644 index 0000000000..e241d7a4ee --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/utils/DisplayUtils.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2016 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.utils; + +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.function.Supplier; + +import org.eclipse.swt.widgets.Display; + +/** + * Utility class for the {@link Display} + */ +public class DisplayUtils { + + /** + * Calls <strong>synchronously</strong> the given {@link Supplier} in the + * default Display and returns the result + * + * @param supplier + * the Supplier to call + * @return the supplier's result + */ + public static <V> V get(final Supplier<V> supplier) { + final Queue<V> result = new ArrayBlockingQueue<>(1); + Display.getDefault().syncExec(() -> result.add(supplier.get())); + return result.poll(); + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerContainersView.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerContainersView.java index 82eae7b72c..9bfad1312a 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerContainersView.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerContainersView.java @@ -291,7 +291,7 @@ public class DockerContainersView extends ViewPart implements } }); // 'Command' column - final TableViewerColumn commandColumn = createColumn(DVMessages.getString("COMMAND")); //$NON-NLS-1$ + final TableViewerColumn commandColumn = createColumn(DVMessages.getString("COMMAND_LINE")); //$NON-NLS-1$ setLayout(commandColumn, tableLayout, 150); commandColumn.setLabelProvider(new ColumnLabelProvider() { @Override diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerExplorerView.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerExplorerView.java index 5bd0914a7d..759fd76ee6 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerExplorerView.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/views/DockerExplorerView.java @@ -81,6 +81,9 @@ public class DockerExplorerView extends CommonNavigator implements private ViewerFilter containersAndImagesSearchFilter; + /** + * Constructor. + */ public DockerExplorerView() { super(); // Make sure DockerConnectionWatcher is up and running before first @@ -195,6 +198,11 @@ public class DockerExplorerView extends CommonNavigator implements super.createPartControl(container); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL) .grab(true, true).applyTo(getCommonViewer().getControl()); + if (DockerConnectionManager.getInstance().hasConnections()) { + final IDockerConnection connection = DockerConnectionManager + .getInstance().getFirstConnection(); + getCommonViewer().setSelection(new StructuredSelection(connection)); + } return form; } @@ -254,16 +262,18 @@ public class DockerExplorerView extends CommonNavigator implements * connections in the {@link DockerConnectionManager}. */ public void showConnectionsOrExplanations() { - if (DockerConnectionManager.getInstance().getConnections().length < 1) { + if (!DockerConnectionManager.getInstance().hasConnections() + && pageBook != explanationsPane) { pageBook.showPage(explanationsPane); this.currentPane = explanationsPane; - } else { + } else if (pageBook != connectionsPane) { pageBook.showPage(connectionsPane); this.currentPane = connectionsPane; registerListeners(); } } + /** * @return <code>true</code> if the current panel is the one containing a * {@link TreeViewer} of {@link IDockerConnection}s, @@ -303,11 +313,11 @@ public class DockerExplorerView extends CommonNavigator implements // move viewer selection to the first connection or set to // null if // no other connection exists - final IDockerConnection[] connections = DockerConnectionManager - .getInstance().getConnections(); - if (connections.length > 0) { + if (DockerConnectionManager.getInstance().hasConnections()) { getCommonViewer().setSelection( - new StructuredSelection(connections[0]), true); + new StructuredSelection(DockerConnectionManager + .getInstance().getFirstConnection()), + true); } else { getCommonViewer().setSelection(null); } @@ -317,13 +327,14 @@ public class DockerExplorerView extends CommonNavigator implements } private void registerListeners() { - for (IDockerConnection connection : DockerConnectionManager - .getInstance().getConnections()) { - registerListeners(connection); - } + DockerConnectionManager.getInstance().getAllConnections().stream() + .forEach(connection -> registerListeners(connection)); } private void registerListeners(final IDockerConnection connection) { + if (connection == null) { + return; + } if (!containersRefreshers.containsKey(connection)) { final ContainersRefresher refresher = new ContainersRefresher(); connection.addContainerListener(refresher); diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/DockerComposeUpDialog.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/DockerComposeUpDialog.java new file mode 100644 index 0000000000..a18343ce17 --- /dev/null +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/DockerComposeUpDialog.java @@ -0,0 +1,280 @@ +/******************************************************************************* + * Copyright (c) 2015, 2016 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.internal.docker.ui.wizards; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.databinding.Binding; +import org.eclipse.core.databinding.DataBindingContext; +import org.eclipse.core.databinding.beans.BeanProperties; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.core.databinding.validation.ValidationStatus; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.databinding.swt.ISWTObservableValue; +import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.fieldassist.ComboContentAdapter; +import org.eclipse.jface.fieldassist.ContentProposal; +import org.eclipse.jface.fieldassist.ContentProposalAdapter; +import org.eclipse.jface.fieldassist.IContentProposal; +import org.eclipse.jface.fieldassist.IContentProposalProvider; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ComboViewer; +import org.eclipse.linuxtools.docker.core.DockerConnectionManager; +import org.eclipse.linuxtools.docker.core.IDockerConnection; +import org.eclipse.linuxtools.docker.core.IDockerContainer; +import org.eclipse.linuxtools.internal.docker.ui.SWTImagesFactory; +import org.eclipse.linuxtools.internal.docker.ui.databinding.BaseDatabindingModel; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +/** + * {@link Dialog} to specify Docker Compose options at launch time. + */ +public class DockerComposeUpDialog extends Dialog { + + private final DockerComposeUpModel model = new DockerComposeUpModel(); + private final DataBindingContext dbc = new DataBindingContext(); + + /** + * Constructor. + * + * @param parentShell + * the parent {@link Shell} + */ + public DockerComposeUpDialog(final Shell parentShell) { + super(parentShell); + } + + @Override + protected void configureShell(final Shell shell) { + super.configureShell(shell); + setShellStyle(getShellStyle() | SWT.RESIZE); + shell.setText(WizardMessages.getString("DockerComposeUpDialog.title")); //$NON-NLS-1$ + } + + @Override + protected Point getInitialSize() { + return new Point(400, super.getInitialSize().y); + } + + @SuppressWarnings("unchecked") + @Override + protected Control createDialogArea(final Composite parent) { + final int COLUMNS = 2; + final Composite container = new Composite(parent, SWT.NONE); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL) + .span(COLUMNS, 1).grab(true, false).applyTo(container); + GridLayoutFactory.fillDefaults().numColumns(COLUMNS).margins(10, 10) + .applyTo(container); + final Label explanationLabel = new Label(container, SWT.NONE); + explanationLabel.setText( + WizardMessages + .getString("DockerComposeUpDialog.explanationLabel")); //$NON-NLS-1$ + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .span(COLUMNS, 1).grab(false, false).applyTo(explanationLabel); + final Label containerLabel = new Label(container, SWT.NONE); + containerLabel.setText( + WizardMessages + .getString("DockerComposeUpDialog.connectionLabel")); //$NON-NLS-1$ + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .grab(false, false).applyTo(containerLabel); + final Combo containerSelectionCombo = new Combo(container, SWT.NONE); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .grab(true, false).applyTo(containerSelectionCombo); + final ComboViewer connectionSelectionComboViewer = new ComboViewer( + containerSelectionCombo); + connectionSelectionComboViewer + .setContentProvider(new ArrayContentProvider()); + final List<String> connectionNames = model.getConnectionNames(); + connectionSelectionComboViewer.setInput(connectionNames); + new ContentProposalAdapter(containerSelectionCombo, + new ComboContentAdapter() { + @Override + public void insertControlContents(Control control, + String text, int cursorPosition) { + final Combo combo = (Combo) control; + final Point selection = combo.getSelection(); + combo.setText(text); + selection.x = text.length(); + selection.y = selection.x; + combo.setSelection(selection); + } + }, getConnectionNameContentProposalProvider( + containerSelectionCombo), + null, null); + final ISWTObservableValue connnectionNameObservable = WidgetProperties + .selection().observe(connectionSelectionComboViewer.getCombo()); + // pre-select with first connection + if (!connectionNames.isEmpty()) { + model.setConnectionName(connectionNames.get(0)); + } + // error message + final Composite errorContainer = new Composite(container, SWT.NONE); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL) + .span(COLUMNS, 1).grab(true, true).applyTo(errorContainer); + GridLayoutFactory.fillDefaults().margins(6, 6).numColumns(2) + .applyTo(errorContainer); + + final Label errorMessageIcon = new Label(errorContainer, SWT.NONE); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .hint(20, SWT.DEFAULT).applyTo(errorMessageIcon); + final Label errorMessageLabel = new Label(errorContainer, SWT.NONE); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER) + .grab(true, false).applyTo(errorMessageLabel); + dbc.bindValue(connnectionNameObservable, + BeanProperties + .value(DockerComposeUpModel.class, + DockerComposeUpModel.CONNECTION_NAME) + .observe(model)); + // must be called after bindings were set + setupValidationSupport(errorMessageIcon, errorMessageLabel); + return container; + } + + private void setupValidationSupport(final Label errorMessageIcon, + final Label errorMessageLabel) { + for (@SuppressWarnings("unchecked") + Iterator<Binding> iterator = dbc.getBindings().iterator(); iterator + .hasNext();) { + final Binding binding = iterator.next(); + binding.getModel().addChangeListener(onSettingsChanged( + errorMessageIcon, errorMessageLabel)); + } + } + + private IChangeListener onSettingsChanged(final Label errorMessageIcon, + final Label errorMessageLabel) { + + return event -> { + final IStatus status = validateInput(); + if (Display.getCurrent() == null) { + return; + } + Display.getCurrent().syncExec(() -> { + if (status.isOK()) { + errorMessageIcon.setVisible(false); + errorMessageLabel.setVisible(false); + setOkButtonEnabled(true); + } else if (status.matches(IStatus.WARNING)) { + errorMessageIcon.setVisible(true); + errorMessageIcon.setImage( + SWTImagesFactory.DESC_WARNING.createImage()); + errorMessageLabel.setVisible(true); + errorMessageLabel.setText(status.getMessage()); + setOkButtonEnabled(true); + } else if (status.matches(IStatus.ERROR)) { + if (status.getMessage() != null + && !status.getMessage().isEmpty()) { + errorMessageIcon.setVisible(true); + errorMessageIcon.setImage( + SWTImagesFactory.DESC_ERROR.createImage()); + errorMessageLabel.setVisible(true); + errorMessageLabel.setText(status.getMessage()); + } + setOkButtonEnabled(false); + } + }); + }; + } + + /** + * Validates that the selected {@link IDockerConnection} exists. + * + * @return a validation status + */ + private IStatus validateInput() { + final String selectedConnectionName = model.getConnectionName(); + if (selectedConnectionName == null + || selectedConnectionName.isEmpty()) { + return Status.CANCEL_STATUS; + } else if (!model.getConnectionNames() + .contains(selectedConnectionName)) { + return ValidationStatus.error(WizardMessages.getFormattedString( + "DockerComposeUpDialog.error.unknownConnection", //$NON-NLS-1$ + selectedConnectionName)); + } + return Status.OK_STATUS; + + } + + /** + * @return the selected {@link IDockerConnection} + */ + public IDockerConnection getSelectedConnection() { + return DockerConnectionManager.getInstance() + .findConnection(model.connectionName); + } + + /** + * Creates an {@link IContentProposalProvider} to propose + * {@link IDockerContainer} names based on the current text. + * + * @param items + * @return + */ + private IContentProposalProvider getConnectionNameContentProposalProvider( + final Combo connectionNamesSelectionCombo) { + return (contents, position) -> { + final List<IContentProposal> proposals = new ArrayList<>(); + for (String connectionName : connectionNamesSelectionCombo + .getItems()) { + if (connectionName.contains(contents)) { + proposals.add(new ContentProposal(connectionName, + connectionName, connectionName, position)); + } + } + return proposals.toArray(new IContentProposal[0]); + }; + } + + private void setOkButtonEnabled(final boolean enabled) { + getButton(IDialogConstants.OK_ID).setEnabled(enabled); + } + + class DockerComposeUpModel extends BaseDatabindingModel { + + public static final String CONNECTION_NAME = "connectionName"; //$NON-NLS-1$ + + private String connectionName; + + private final List<String> connectionNames = DockerConnectionManager + .getInstance().getConnectionNames(); + + public List<String> getConnectionNames() { + return connectionNames; + } + + public String getConnectionName() { + return connectionName; + } + + public void setConnectionName(final String connectionName) { + firePropertyChange(CONNECTION_NAME, this.connectionName, + this.connectionName = connectionName); + } + + } + +} diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/NewDockerConnectionPage.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/NewDockerConnectionPage.java index bb0321f7f2..28d2c8d353 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/NewDockerConnectionPage.java +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/NewDockerConnectionPage.java @@ -17,11 +17,11 @@ import java.io.File; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.StringTokenizer; +import java.util.stream.Collectors; import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.beans.BeanProperties; @@ -710,17 +710,16 @@ public class NewDockerConnectionPage extends WizardPage { } final String dockerMachineInstallDir = getDockerMachineInstallDir(); final String vmDriverInstallDir = getVMDriverInstallDir(); - - final String[] dmNames = DockerMachine - .getNames(dockerMachineInstallDir); - final List<String> activeNames = new ArrayList<>(); - for (String name : dmNames) { - if (DockerMachine.getHost(name, dockerMachineInstallDir, - vmDriverInstallDir) != null) { - activeNames.add(name); - } - } - if (activeNames.size() > 0) { + final Map<String, Boolean> allMachineStates = retrieveDockerMachineNames( + dockerMachineInstallDir, + vmDriverInstallDir); + final List<String> activeMachineNames = allMachineStates + .entrySet().stream() + .filter((machineEntry) -> machineEntry.getValue() + .booleanValue()) + .map((machineEntry) -> machineEntry.getKey()) + .collect(Collectors.toList()); + if (activeMachineNames.size() > 0) { ListDialog connPrompt = new ListDialog(getShell()); connPrompt.setContentProvider(new ConnectionSelectionContentProvider()); connPrompt.setLabelProvider(new ConnectionSelectionLabelProvider()); @@ -728,49 +727,58 @@ public class NewDockerConnectionPage extends WizardPage { "DockerConnectionPage.searchDialog.title")); //$NON-NLS-1$ connPrompt.setMessage(WizardMessages.getString( "DockerConnectionPage.searchDialog.message")); //$NON-NLS-1$ - connPrompt.setInput(activeNames.toArray(new String[0])); + connPrompt.setInput( + activeMachineNames.toArray(new String[0])); if (connPrompt.open() == 0 && connPrompt.getResult().length > 0) { - String name = ((String) connPrompt.getResult()[0]); - String host = DockerMachine.getHost(name, - dockerMachineInstallDir, vmDriverInstallDir); - String certPath = DockerMachine.getCertPath(name, - dockerMachineInstallDir, vmDriverInstallDir); - model.setBindingMode(EnumDockerConnectionSettings.TCP_CONNECTION); + final String name = ((String) connPrompt + .getResult()[0]); + model.setBindingMode( + EnumDockerConnectionSettings.TCP_CONNECTION); model.setConnectionName(name); model.setUnixSocketPath(null); - model.setTcpHost(host); - if (certPath != null) { - model.setTcpTLSVerify(true); - model.setTcpCertPath(certPath); - } else { - model.setTcpTLSVerify(false); - model.setTcpCertPath(null); + try { + final String host = DockerMachine.getHost(name, + dockerMachineInstallDir, + vmDriverInstallDir); + model.setTcpHost(host); + } catch (DockerException e1) { + Activator.log(e1); + } + try { + final String certPath = DockerMachine.getCertPath( + name, dockerMachineInstallDir, + vmDriverInstallDir); + if (certPath != null) { + model.setTcpTLSVerify(true); + model.setTcpCertPath(certPath); + } else { + model.setTcpTLSVerify(false); + model.setTcpCertPath(null); + } + } catch (DockerException e1) { + Activator.log(e1); } } } else { - if (dmNames.length == 1) { + if (allMachineStates.size() == 1) { MessageDialog.openInformation(getShell(), WizardMessages.getString( "DockerConnectionPage.searchDialog.discovery.title"), //$NON-NLS-1$ WizardMessages.getFormattedString( "DockerConnectionPage.searchDialog.discovery.innactive.single", //$NON-NLS-1$ - dmNames[0])); - } else if (dmNames.length > 1) { - final StringBuffer connections = new StringBuffer(); - for (Iterator<String> iterator = Arrays.asList(dmNames) - .iterator(); iterator.hasNext();) { - final String dmName = iterator.next(); - connections.append(dmName); - if (iterator.hasNext()) { - connections.append(", "); //$NON-NLS-1$ - } - } + allMachineStates.entrySet().iterator() + .next().getKey())); + } else if (allMachineStates.size() > 1) { + final String allMachineNames = allMachineStates + .entrySet().stream() + .map((machineEntry) -> machineEntry.getKey()) + .collect(Collectors.joining(", ")); MessageDialog.openInformation(getShell(), WizardMessages.getString( "DockerConnectionPage.searchDialog.discovery.title"), //$NON-NLS-1$ WizardMessages.getFormattedString( "DockerConnectionPage.searchDialog.discovery.innactive.multiple", //$NON-NLS-1$ - connections.toString())); + allMachineNames)); } else { MessageDialog.openInformation(getShell(), WizardMessages.getString( @@ -780,6 +788,37 @@ public class NewDockerConnectionPage extends WizardPage { } } } + + /** + * Retrieves the docker machine names along with a boolean flag to + * indicate if it is running or not. + * + * @param dockerMachineInstallDir + * @param vmDriverInstallDir + * @return + */ + private Map<String, Boolean> retrieveDockerMachineNames( + final String dockerMachineInstallDir, + final String vmDriverInstallDir) { + try { + final String[] dmNames = DockerMachine + .getNames(dockerMachineInstallDir); + return java.util.stream.Stream.of(dmNames) + .collect(Collectors.toMap(name -> name, name -> { + try { + return DockerMachine.getHost(name, + dockerMachineInstallDir, + vmDriverInstallDir) != null; + } catch (DockerException e) { + Activator.log(e); + return false; + } + })); + } catch (DockerException e) { + Activator.log(e); + return Collections.emptyMap(); + } + } }; diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/WizardMessages.properties b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/WizardMessages.properties index 74870d812b..6975164865 100644 --- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/WizardMessages.properties +++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/wizards/WizardMessages.properties @@ -349,7 +349,12 @@ ImageBuildDialog.repoNameLabel=Repository Name: ImageBuildDialog.error.unknownConnection=Connection {0} does not exist. ImageBuildDialog.warning.missingRepoName=A repository name is recommended. -RegistryAccountDialog.add.edit.explanation=Edit a Registry Account +DockerComposeUpDialog.title=Docker Compose Configuration +DockerComposeUpDialog.explanationLabel=Select a connection +DockerComposeUpDialog.connectionLabel=Connection: +DockerComposeUpDialog.error.unknownConnection=Connection {0} does not exist. + +RegistryAccountDialog.add.edit.explanation=Add/Edit a Registry Account RegistryAccountDialog.add.explanation=Add a Registry Account RegistryAccountDialog.email.label=Email: RegistryAccountDialog.password.label=Password: |