CHE-1823: Machine Agent implementation (#2311)
parent
3fa4246981
commit
af2f1098d7
|
|
@ -30,7 +30,7 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.che</groupId>
|
||||
<artifactId>assembly-wsagent-server</artifactId>
|
||||
<type>zip</type>
|
||||
<type>tar.gz</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che</groupId>
|
||||
|
|
@ -65,13 +65,13 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.che.lib</groupId>
|
||||
<artifactId>che-websocket-terminal</artifactId>
|
||||
<type>zip</type>
|
||||
<type>tar.gz</type>
|
||||
<classifier>linux_amd64</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.lib</groupId>
|
||||
<artifactId>che-websocket-terminal</artifactId>
|
||||
<type>zip</type>
|
||||
<type>tar.gz</type>
|
||||
<classifier>linux_arm7</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
|||
|
|
@ -59,36 +59,28 @@
|
|||
<useProjectArtifact>false</useProjectArtifact>
|
||||
<unpack>false</unpack>
|
||||
<outputDirectory>lib</outputDirectory>
|
||||
<outputFileNameMapping>ws-agent.zip</outputFileNameMapping>
|
||||
<outputFileNameMapping>ws-agent.tar.gz</outputFileNameMapping>
|
||||
<includes>
|
||||
<include>org.eclipse.che:assembly-wsagent-server</include>
|
||||
</includes>
|
||||
</dependencySet>
|
||||
<dependencySet>
|
||||
<useProjectArtifact>false</useProjectArtifact>
|
||||
<unpack>true</unpack>
|
||||
<outputDirectory>lib/linux_amd64</outputDirectory>
|
||||
<unpack>false</unpack>
|
||||
<outputDirectory>lib/linux_amd64/terminal</outputDirectory>
|
||||
<outputFileNameMapping>websocket-terminal-linux_amd64.tar.gz</outputFileNameMapping>
|
||||
<includes>
|
||||
<include>org.eclipse.che.lib:che-websocket-terminal:zip:linux_amd64</include>
|
||||
<include>org.eclipse.che.lib:che-websocket-terminal:tar.gz:linux_amd64</include>
|
||||
</includes>
|
||||
<unpackOptions>
|
||||
<excludes>
|
||||
<exclude>META-INF/**</exclude>
|
||||
</excludes>
|
||||
</unpackOptions>
|
||||
</dependencySet>
|
||||
<dependencySet>
|
||||
<useProjectArtifact>false</useProjectArtifact>
|
||||
<unpack>true</unpack>
|
||||
<outputDirectory>lib/linux_arm7</outputDirectory>
|
||||
<unpack>false</unpack>
|
||||
<outputDirectory>lib/linux_arm7/terminal</outputDirectory>
|
||||
<outputFileNameMapping>websocket-terminal-linux_arm7.tar.gz</outputFileNameMapping>
|
||||
<includes>
|
||||
<include>org.eclipse.che.lib:che-websocket-terminal:zip:linux_arm7</include>
|
||||
<include>org.eclipse.che.lib:che-websocket-terminal:tar.gz:linux_arm7</include>
|
||||
</includes>
|
||||
<unpackOptions>
|
||||
<excludes>
|
||||
<exclude>META-INF/**</exclude>
|
||||
</excludes>
|
||||
</unpackOptions>
|
||||
</dependencySet>
|
||||
<dependencySet>
|
||||
<useProjectArtifact>false</useProjectArtifact>
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ function set_environment_variables {
|
|||
# The machine web app project that will be built with the extension
|
||||
PLUGIN_WSAGENT_WAR_DIR="${SDK_DIR}/assembly-wsagent-war"
|
||||
|
||||
# Creates the ws-agent.zip artifact for a Che assembly, which packages Tomcat + machine war into single package
|
||||
# Creates the ws-agent.tar.gz artifact for a Che assembly, which packages Tomcat + machine war into single package
|
||||
PLUGIN_WSAGENT_SERVER_DIR="${SDK_DIR}/assembly-wsagent-server"
|
||||
|
||||
# Generates a new Che assembly that contains new IDE, ws-master, and ws-agent.
|
||||
|
|
@ -294,7 +294,7 @@ if [ "${USE_HELP}" == "false" ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# Re-build the machine web application with custom extension included from workspace/ directories included. This artifact is packaged into ws-agent.zip and deployed into workspace machine.
|
||||
# Re-build the machine web application with custom extension included from workspace/ directories included. This artifact is packaged into ws-agent.tar.gz and deployed into workspace machine.
|
||||
if [ "${SKIP_WSAGENT}" == "false" ]; then
|
||||
|
||||
echo_stage "CHE SDK: Compiling ws-agent plug-ins into new workspace agent."
|
||||
|
|
@ -304,7 +304,7 @@ if [ "${USE_HELP}" == "false" ]; then
|
|||
mvn sortpom:sort
|
||||
mvn -Denforcer.skip=true clean install -Dskip-validate-sources=true
|
||||
|
||||
echo_stage "CHE SDK: Packaging ws-agent web app and Tomcat into ws-agent.zip."
|
||||
echo_stage "CHE SDK: Packaging ws-agent web app and Tomcat into ws-agent.tar.gz."
|
||||
|
||||
cd "${PLUGIN_WSAGENT_SERVER_DIR}"
|
||||
mvn -Denforcer.skip=true clean install -Dskip-validate-sources=true
|
||||
|
|
@ -312,7 +312,7 @@ if [ "${USE_HELP}" == "false" ]; then
|
|||
|
||||
|
||||
if [ "${SKIP_UPDATE}" == "false" ]; then
|
||||
cp -r "${PLUGIN_WSAGENT_SERVER_DIR}"/target/*.zip lib/ws-agent.zip
|
||||
cp -r "${PLUGIN_WSAGENT_SERVER_DIR}"/target/*.tar.gz lib/ws-agent.tar.gz
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
@ -347,12 +347,12 @@ if [ "${USE_HELP}" == "false" ]; then
|
|||
|
||||
if [ "${SKIP_WSAGENT}" == "false" ] && [ "${SKIP_UPDATE}" == "true" ]; then
|
||||
echo "New Workspace Agent:
|
||||
${PLUGIN_WSAGENT_SERVER_DIR}/target/*.zip"
|
||||
${PLUGIN_WSAGENT_SERVER_DIR}/target/*.tar.gz"
|
||||
fi
|
||||
|
||||
if [ "${SKIP_WSAGENT}" == "false" ] && [ "${SKIP_UPDATE}" == "false" ]; then
|
||||
echo "New Workspace Agent:
|
||||
${CHE_HOME}/lib/ws-agent.zip"
|
||||
${CHE_HOME}/lib/ws-agent.tar.gz"
|
||||
fi
|
||||
|
||||
if [ "${ASSEMBLY}" == "true" ]; then
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ compile and runtime.
|
|||
$ mvn -Denforcer.skip=true clean package install -Dskip-validate-sources=true
|
||||
|
||||
5. If your plug-ins are added into the workspace agent, Che packages the agent web app with
|
||||
Tomcat to create a new ws-agent.zip package:
|
||||
Tomcat to create a new ws-agent.tar.gz package:
|
||||
|
||||
/sdk/assembly-wsagent-server
|
||||
$ mvn -Denforcer.skip=true clean package install
|
||||
|
|
@ -84,7 +84,7 @@ compile and runtime.
|
|||
overriding existing applications.
|
||||
|
||||
/sdk/assembly-ide-war/temp/target/*.war --> /tomcat/webapps
|
||||
/sdk/assembly-wsagent-server/target/*.zip --> /lib/ws-agent.zip
|
||||
/sdk/assembly-wsagent-server/target/*.tar.gz --> /lib/ws-agent.tar.gz
|
||||
|
||||
7. If `--assembly` flag, then Che also creates a new distributable package of Che:
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@
|
|||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-agent</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-auth</artifactId>
|
||||
|
|
|
|||
|
|
@ -14,13 +14,14 @@ import com.google.inject.AbstractModule;
|
|||
import com.google.inject.multibindings.Multibinder;
|
||||
import com.google.inject.name.Names;
|
||||
|
||||
import org.eclipse.che.api.agent.server.launcher.AgentLauncher;
|
||||
import org.eclipse.che.api.core.rest.CheJsonProvider;
|
||||
import org.eclipse.che.api.core.rest.MessageBodyAdapter;
|
||||
import org.eclipse.che.api.core.rest.MessageBodyAdapterInterceptor;
|
||||
import org.eclipse.che.api.machine.shared.Constants;
|
||||
import org.eclipse.che.api.workspace.server.stack.StackMessageBodyAdapter;
|
||||
import org.eclipse.che.api.workspace.server.WorkspaceConfigMessageBodyAdapter;
|
||||
import org.eclipse.che.api.workspace.server.WorkspaceMessageBodyAdapter;
|
||||
import org.eclipse.che.api.workspace.server.stack.StackMessageBodyAdapter;
|
||||
import org.eclipse.che.inject.DynaModule;
|
||||
|
||||
import static com.google.inject.matcher.Matchers.subclassesOf;
|
||||
|
|
@ -70,23 +71,20 @@ public class WsMasterModule extends AbstractModule {
|
|||
.toInstance("predefined-recipes.json");
|
||||
|
||||
|
||||
bindConstant().annotatedWith(Names.named(org.eclipse.che.api.agent.server.wsagent.WsAgentLauncherImpl.WS_AGENT_PROCESS_START_COMMAND))
|
||||
.to("rm -rf ~/che && mkdir -p ~/che && unzip -qq /mnt/che/ws-agent.zip -d ~/che/ws-agent && " +
|
||||
"sudo sh -c \"chown -R $(id -u -n) /projects || true\" && " +
|
||||
"export JPDA_ADDRESS=\"4403\" && ~/che/ws-agent/bin/catalina.sh jpda run");
|
||||
bindConstant().annotatedWith(Names.named(org.eclipse.che.plugin.docker.machine.DockerMachineImplTerminalLauncher.START_TERMINAL_COMMAND))
|
||||
.to("sleep 5 && mkdir -p ~/che " +
|
||||
"&& cp /mnt/che/terminal -R ~/che" +
|
||||
"&& ~/che/terminal/che-websocket-terminal -addr :4411 -cmd /bin/bash -static ~/che/terminal/");
|
||||
bindConstant().annotatedWith(Names.named("machine.ws_agent.run_command"))
|
||||
.to("export JPDA_ADDRESS=\"4403\" && ~/che/ws-agent/bin/catalina.sh jpda run");
|
||||
bind(org.eclipse.che.api.workspace.server.WorkspaceValidator.class)
|
||||
.to(org.eclipse.che.api.workspace.server.DefaultWorkspaceValidator.class);
|
||||
|
||||
bind(org.eclipse.che.api.workspace.server.event.MachineStateListener.class).asEagerSingleton();
|
||||
|
||||
bind(org.eclipse.che.api.agent.server.wsagent.WsAgentLauncher.class)
|
||||
.to(org.eclipse.che.api.agent.server.wsagent.WsAgentLauncherImpl.class);
|
||||
bind(org.eclipse.che.api.agent.server.AgentRegistry.class).to(org.eclipse.che.api.agent.server.impl.LocalAgentRegistryImpl.class);
|
||||
|
||||
Multibinder<AgentLauncher> agentLaunchers = Multibinder.newSetBinder(binder(), AgentLauncher.class);
|
||||
agentLaunchers.addBinding().to(org.eclipse.che.api.workspace.server.launcher.WsAgentLauncherImpl.class);
|
||||
agentLaunchers.addBinding().to(org.eclipse.che.api.workspace.server.launcher.TerminalAgentLauncherImpl.class);
|
||||
agentLaunchers.addBinding().to(org.eclipse.che.api.workspace.server.launcher.SshAgentLauncherImpl.class);
|
||||
|
||||
bind(org.eclipse.che.api.agent.server.terminal.MachineTerminalLauncher.class);
|
||||
bind(org.eclipse.che.api.deploy.WsMasterAnalyticsAddresser.class);
|
||||
|
||||
Multibinder<org.eclipse.che.api.machine.server.spi.InstanceProvider> machineImageProviderMultibinder =
|
||||
|
|
@ -96,6 +94,7 @@ public class WsMasterModule extends AbstractModule {
|
|||
bind(org.eclipse.che.api.environment.server.compose.ComposeMachineInstanceProvider.class)
|
||||
.to(org.eclipse.che.plugin.docker.machine.ComposeMachineProviderImpl.class);
|
||||
|
||||
install(new org.eclipse.che.api.agent.server.AgentModule());
|
||||
install(new org.eclipse.che.api.core.rest.CoreRestModule());
|
||||
install(new org.eclipse.che.api.core.util.FileCleaner.FileCleanerModule());
|
||||
install(new org.eclipse.che.plugin.docker.machine.local.LocalDockerModule());
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ docker.connection.tcp.read_timeout_ms=600000
|
|||
|
||||
# This archive contains the server to run the workspace agent and any custom extensions.
|
||||
# Che injects this archive into machines when they are booted or started.
|
||||
machine.server.ext.archive=${che.home}/lib/ws-agent.zip
|
||||
machine.server.ext.archive=${che.home}/lib/ws-agent.tar.gz
|
||||
|
||||
# The machine's log files are stored here
|
||||
machine.logs.location=${che.logs.dir}/machine/logs
|
||||
|
|
@ -91,13 +91,17 @@ machine.logs.location=${che.logs.dir}/machine/logs
|
|||
# Size of the machine by default. What is used if RAM parameter not provided by user or API.
|
||||
machine.default_mem_size_mb=1024
|
||||
|
||||
# When the workspace master launches a new workspace, Che performs checks of the internal Web
|
||||
# When the workspace master launches a new workspace, Che performs checks of the internal Web
|
||||
# services. When Che gets a valid response, we know that the workspace agent is ready for use.
|
||||
machine.ws_agent.max_start_time_ms=60000
|
||||
machine.ws_agent.max_start_time_ms=120000
|
||||
machine.ws_agent.ping_delay_ms=2000
|
||||
machine.ws_agent.ping_conn_timeout_ms=2000
|
||||
machine.ws_agent.ping_timed_out_error_msg=Timeout reached. The Che server has been unable to verify that your workspace's agent has successfully booted. Either the workspace is unreachable, the agent had an error during startup, or your workspace is starting slowly. You can configure machine.ws_agent.max_start_time_ms in Che properties to increase the timeout.
|
||||
|
||||
# When Che start an agent, it performs check if it is launched.
|
||||
machine.agent.max_start_time_ms=120000
|
||||
machine.agent.ping_delay_ms=2000
|
||||
|
||||
# Hosts listed here will be added to /etc/hosts of each workspace machine.
|
||||
# Add an entry here if you write a ws-agent extension that needs to communicate outside the machine
|
||||
machine.docker.machine_extra_hosts=NULL
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.core.util;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.eclipse.che.api.core.util.ErrorFilteredConsumer.ErrorIndicator.DEFAULT_ERROR_INDICATOR;
|
||||
|
||||
/**
|
||||
* Consumes all output and redirect to another consumer
|
||||
* only those lines which contain errors.
|
||||
*
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
public class ErrorFilteredConsumer implements LineConsumer {
|
||||
|
||||
private final ErrorIndicator errorIndicator;
|
||||
private final LineConsumer lineConsumer;
|
||||
|
||||
public ErrorFilteredConsumer(ErrorIndicator errorIndicator, LineConsumer lineConsumer) {
|
||||
this.errorIndicator = errorIndicator;
|
||||
this.lineConsumer = lineConsumer;
|
||||
}
|
||||
|
||||
public ErrorFilteredConsumer(LineConsumer lineConsumer) {
|
||||
this(DEFAULT_ERROR_INDICATOR, lineConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLine(String line) throws IOException {
|
||||
if (errorIndicator.isError(line)) {
|
||||
lineConsumer.writeLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
lineConsumer.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if line contains a error message.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ErrorIndicator {
|
||||
boolean isError(String line);
|
||||
|
||||
ErrorIndicator DEFAULT_ERROR_INDICATOR = line -> line.startsWith("[STDERR]");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.core.util;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
public class ErrorFilteredConsumerTest {
|
||||
|
||||
@Test
|
||||
public void testRedirect() throws Exception {
|
||||
LineConsumer lineConsumer = mock(LineConsumer.class);
|
||||
|
||||
ErrorFilteredConsumer errorFilteredConsumer = new ErrorFilteredConsumer(lineConsumer);
|
||||
|
||||
errorFilteredConsumer.writeLine("Line 1");
|
||||
errorFilteredConsumer.writeLine("Line 2");
|
||||
errorFilteredConsumer.writeLine("[STDERR] Line 3");
|
||||
errorFilteredConsumer.writeLine("[STDERR] Line 4");
|
||||
errorFilteredConsumer.writeLine("Line 5");
|
||||
|
||||
verify(lineConsumer).writeLine("[STDERR] Line 3");
|
||||
verify(lineConsumer).writeLine("[STDERR] Line 4");
|
||||
}
|
||||
}
|
||||
|
|
@ -90,7 +90,8 @@
|
|||
<artifactId>mockito-core</artifactId>
|
||||
<version>${org.mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency> <dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<scope>test</scope>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,16 @@
|
|||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
|
|
@ -45,6 +55,11 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<testResources>
|
||||
<testResource>
|
||||
<directory>src/test/resources</directory>
|
||||
</testResource>
|
||||
</testResources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.mycila</groupId>
|
||||
|
|
|
|||
|
|
@ -243,7 +243,6 @@ public class IoUtil {
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Download file with redirection if got status 301, 302, 303.
|
||||
* Will useful in case redirection http -> https
|
||||
|
|
@ -502,13 +501,13 @@ public class IoUtil {
|
|||
}
|
||||
}
|
||||
|
||||
private static final char[] hex = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
private static final char[] HEX = "0123456789abcdef".toCharArray();
|
||||
|
||||
public static String toHex(byte[] hash) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (int i = 0; i < hash.length; i++) {
|
||||
b.append(hex[(hash[i] >> 4) & 0x0f]);
|
||||
b.append(hex[hash[i] & 0x0f]);
|
||||
b.append(HEX[(hash[i] >> 4) & 0x0f]);
|
||||
b.append(HEX[hash[i] & 0x0f]);
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,13 @@ import java.io.OutputStream;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
|
|
@ -194,6 +198,27 @@ public class ZipUtils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides streams to all resources matching {@code filter} criteria inside the archive.
|
||||
*
|
||||
* @param zip
|
||||
* zip file to get resources from
|
||||
* @param filter
|
||||
* the search criteria
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void getResources(ZipFile zip, Pattern filter, Consumer<InputStream> consumer) throws IOException {
|
||||
Enumeration<? extends ZipEntry> zipEntries = zip.entries();
|
||||
while (zipEntries.hasMoreElements()) {
|
||||
ZipEntry zipEntry = zipEntries.nextElement();
|
||||
final String name = zipEntry.getName();
|
||||
if (filter.matcher(name).matches()) {
|
||||
try (InputStream in = zip.getInputStream(zipEntry)) {
|
||||
consumer.accept(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks is specified file is zip file or not. Zip file <a href="http://en.wikipedia.org/wiki/Zip_(file_format)#File_headers">headers
|
||||
|
|
|
|||
|
|
@ -17,10 +17,20 @@ import org.testng.annotations.Test;
|
|||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Random;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
public class ZipUtilsTest {
|
||||
|
||||
private File zipFile;
|
||||
|
|
@ -42,11 +52,22 @@ public class ZipUtilsTest {
|
|||
zos.closeEntry();
|
||||
zos.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeAbleToDetectZipFile() throws IOException {
|
||||
Assert.assertTrue(ZipUtils.isZipFile(zipFile));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetResources() throws Exception {
|
||||
URL testJar = ZipUtilsTest.class.getResource("/che/che.jar");
|
||||
@SuppressWarnings("unchecked")
|
||||
Consumer<InputStream> consumer = mock(Consumer.class);
|
||||
|
||||
ZipUtils.getResources(new ZipFile(testJar.getFile()), Pattern.compile(".*[//]?codenvy/[^//]+[.]json"), consumer);
|
||||
|
||||
verify(consumer, times(2)).accept(any(InputStream.class));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -117,7 +117,7 @@ export class WorkspaceDetailsController {
|
|||
|
||||
// get dev machine config
|
||||
let devMachineConfig = this.lodash.find(defaultEnv.machines, (machine) => {
|
||||
return machine.agents.indexOf('ws-agent') >= 0;
|
||||
return machine.agents.indexOf('org.eclipse.che.ws-agent') >= 0;
|
||||
});
|
||||
|
||||
//TODO not implemented yet return angular.copy(devMachineConfig.limits.ram);
|
||||
|
|
@ -179,7 +179,7 @@ export class WorkspaceDetailsController {
|
|||
this.lodash.forEach(workspaceNewDetails.config.environments, (env) => {
|
||||
if (env.name === workspaceNewDetails.config.defaultEnv) {
|
||||
this.lodash.forEach(env.machines, (machine) => {
|
||||
if (machine.agents.indexOf('ws-agent') >= 0) {
|
||||
if (machine.agents.indexOf('org.eclipse.che.ws-agent') >= 0) {
|
||||
/* TODO not implemented yet machine.limits.ram = this.newRam;
|
||||
|
||||
if (this.getWorkspaceStatus() === 'STOPPED') {
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ export class CheWorkspace {
|
|||
defaultEnvironment = {
|
||||
'name': config.defaultEnv,
|
||||
'recipe': null,
|
||||
'machines': {'dev-machine': {'attributes': {'memoryLimitBytes': ram}, 'agents': ['ws-agent']}}
|
||||
'machines': {'dev-machine': {'attributes': {'memoryLimitBytes': ram}, 'agents': ['org.eclipse.che.ws-agent']}}
|
||||
};
|
||||
|
||||
config.environments[config.defaultEnv] = defaultEnvironment;
|
||||
|
|
@ -281,7 +281,7 @@ export class CheWorkspace {
|
|||
}
|
||||
|
||||
let devMachine = this.lodash.find(defaultEnvironment.machines, (machine) => {
|
||||
return machine.agents.includes('ws-agent');
|
||||
return machine.agents.includes('org.eclipse.che.ws-agent');
|
||||
});
|
||||
|
||||
//Check dev machine is provided and add if there is no:
|
||||
|
|
@ -291,7 +291,7 @@ export class CheWorkspace {
|
|||
'attributes': {'memoryLimitBytes': ram},
|
||||
'type': 'docker',
|
||||
'source': source,
|
||||
'agents': ['ws-agent']
|
||||
'agents': ['org.eclipse.che.ws-agent']
|
||||
};
|
||||
defaultEnvironment.machines[devMachine.name] = devMachine;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ public class WorkspaceEventsHandler {
|
|||
if (environment != null) {
|
||||
for (Map.Entry<String, ExtendedMachineDto> machineEntry : environment.getMachines()
|
||||
.entrySet()) {
|
||||
if (machineEntry.getValue().getAgents().contains("ws-agent")) {
|
||||
if (machineEntry.getValue().getAgents().contains("org.eclipse.che.ws-agent")) {
|
||||
return machineEntry.getKey();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ public class CreateWorkspacePresenter implements CreateWorkspaceView.ActionDeleg
|
|||
.withLocation(view.getRecipeUrl());
|
||||
|
||||
ExtendedMachineDto machine = dtoFactory.createDto(ExtendedMachineDto.class)
|
||||
.withAgents(singletonList("ws-agent"))
|
||||
.withAgents(singletonList("org.eclipse.che.ws-agent"))
|
||||
.withAttributes(singletonMap("memoryLimitBytes", MEMORY_LIMIT_BYTES));
|
||||
|
||||
EnvironmentDto environment = dtoFactory.createDto(EnvironmentDto.class)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -138,7 +138,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -199,7 +199,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -265,7 +265,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -340,7 +340,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -409,7 +409,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -488,7 +488,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -565,7 +565,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -650,7 +650,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -728,7 +728,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -817,7 +817,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -895,7 +895,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -969,7 +969,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -1038,7 +1038,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -1118,7 +1118,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -1201,7 +1201,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -1274,7 +1274,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -1344,7 +1344,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -1433,7 +1433,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -1499,7 +1499,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
@ -1558,7 +1558,7 @@
|
|||
"machines": {
|
||||
"dev-machine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.terminal", "org.eclipse.che.ws-agent", "org.eclipse.che.ssh"
|
||||
],
|
||||
"servers": {},
|
||||
"attributes" : {
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ import org.eclipse.che.api.environment.server.compose.ComposeMachineInstanceProv
|
|||
import org.eclipse.che.api.environment.server.compose.model.ComposeServiceImpl;
|
||||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.exception.SourceNotFoundException;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineLimitsImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineConfigImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineLimitsImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineSourceImpl;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
|
|
@ -74,7 +74,6 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
|
@ -500,8 +499,10 @@ public class ComposeMachineProviderImpl implements ComposeMachineInstanceProvide
|
|||
|
||||
ContainerConfig config = new ContainerConfig();
|
||||
config.withImage(image)
|
||||
.withExposedPorts(service.getExpose().stream().collect(Collectors.toMap(Function.identity(),
|
||||
value -> Collections.emptyMap())))
|
||||
.withExposedPorts(service.getExpose()
|
||||
.stream()
|
||||
.distinct()
|
||||
.collect(Collectors.toMap(Function.identity(), value -> Collections.emptyMap())))
|
||||
.withHostConfig(hostConfig)
|
||||
.withCmd(toArrayIfNotNull(service.getCommand()))
|
||||
.withEntrypoint(toArrayIfNotNull(service.getEntrypoint()))
|
||||
|
|
|
|||
|
|
@ -1,75 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.docker.machine;
|
||||
|
||||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.eclipse.che.api.agent.server.terminal.MachineImplSpecificTerminalLauncher;
|
||||
import org.eclipse.che.plugin.docker.client.DockerConnector;
|
||||
import org.eclipse.che.plugin.docker.client.Exec;
|
||||
import org.eclipse.che.plugin.docker.client.LogMessage;
|
||||
import org.eclipse.che.plugin.docker.client.params.CreateExecParams;
|
||||
import org.eclipse.che.plugin.docker.client.params.StartExecParams;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Starts websocket terminal in the machine after container start
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
public class DockerMachineImplTerminalLauncher implements MachineImplSpecificTerminalLauncher {
|
||||
public static final String START_TERMINAL_COMMAND = "machine.docker.server.terminal.run_command";
|
||||
|
||||
private final DockerConnector docker;
|
||||
private final String terminalStartCommand;
|
||||
|
||||
@Inject
|
||||
public DockerMachineImplTerminalLauncher(DockerConnector docker,
|
||||
@Named(START_TERMINAL_COMMAND) String terminalStartCommand) {
|
||||
this.docker = docker;
|
||||
this.terminalStartCommand = terminalStartCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMachineType() {
|
||||
return "docker";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchTerminal(Instance machine) throws MachineException {
|
||||
if (!(machine instanceof DockerInstance)) {
|
||||
throw new MachineException("Docker terminal launcher was used to launch terminal in non-docker machine.");
|
||||
}
|
||||
try {
|
||||
final String container = ((DockerInstance)machine).getContainer();
|
||||
|
||||
final Exec exec = docker.createExec(CreateExecParams.create(container,
|
||||
new String[] {"/bin/bash",
|
||||
"-c",
|
||||
terminalStartCommand})
|
||||
.withDetach(true));
|
||||
|
||||
docker.startExec(StartExecParams.create(exec.getId()), logMessage -> {
|
||||
if (logMessage.getType() == LogMessage.Type.STDERR) {
|
||||
try {
|
||||
machine.getLogger().writeLine("Terminal error. %s" + logMessage.getContent());
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new MachineException(e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ import com.google.inject.name.Names;
|
|||
import org.eclipse.che.api.core.model.machine.ServerConf;
|
||||
import org.eclipse.che.inject.CheBootstrap;
|
||||
import org.eclipse.che.plugin.docker.machine.ext.provider.WsAgentServerConfProvider;
|
||||
import org.eclipse.che.plugin.docker.machine.ext.provider.WsAgentVolumeProvider;
|
||||
|
||||
/**
|
||||
* Guice module for extension servers feature in docker machines
|
||||
|
|
@ -38,7 +39,7 @@ public class DockerExtServerModule extends AbstractModule {
|
|||
String.class,
|
||||
Names.named("machine.docker.dev_machine.machine_volumes"));
|
||||
volumesMultibinder.addBinding()
|
||||
.toProvider(org.eclipse.che.plugin.docker.machine.ext.provider.ExtServerVolumeProvider.class);
|
||||
.toProvider(WsAgentVolumeProvider.class);
|
||||
|
||||
Multibinder<String> devMachineEnvVars = Multibinder.newSetBinder(binder(),
|
||||
String.class,
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ import com.google.inject.multibindings.Multibinder;
|
|||
import com.google.inject.name.Names;
|
||||
|
||||
import org.eclipse.che.api.core.model.machine.ServerConf;
|
||||
import org.eclipse.che.api.agent.server.terminal.MachineImplSpecificTerminalLauncher;
|
||||
import org.eclipse.che.plugin.docker.machine.DockerMachineImplTerminalLauncher;
|
||||
import org.eclipse.che.plugin.docker.machine.ext.provider.TerminalServerConfProvider;
|
||||
|
||||
/**
|
||||
|
|
@ -36,9 +34,5 @@ public class DockerTerminalModule extends AbstractModule {
|
|||
Multibinder<String> volumesMultibinder =
|
||||
Multibinder.newSetBinder(binder(), String.class, Names.named("machine.docker.machine_volumes"));
|
||||
volumesMultibinder.addBinding().toProvider(org.eclipse.che.plugin.docker.machine.ext.provider.TerminalVolumeProvider.class);
|
||||
|
||||
Multibinder<MachineImplSpecificTerminalLauncher> terminalLaunchers = Multibinder.newSetBinder(binder(),
|
||||
MachineImplSpecificTerminalLauncher.class);
|
||||
terminalLaunchers.addBinding().to(DockerMachineImplTerminalLauncher.class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.docker.machine.ext.provider;
|
||||
|
||||
import org.eclipse.che.plugin.docker.machine.DockerInstanceRuntimeInfo;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import org.eclipse.che.plugin.docker.machine.DockerInstanceRuntimeInfo;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
|
|
|
|||
|
|
@ -35,30 +35,30 @@ import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
|||
* @author Alexander Garagatyi
|
||||
*/
|
||||
@Singleton
|
||||
public class ExtServerVolumeProvider implements Provider<String> {
|
||||
public class WsAgentVolumeProvider implements Provider<String> {
|
||||
|
||||
private static final String CONTAINER_TARGET = ":/mnt/che/ws-agent.zip:ro,Z";
|
||||
private static final String WS_AGENT = "ws-agent.zip";
|
||||
private static final String CONTAINER_TARGET = ":/mnt/che/ws-agent.tar.gz:ro,Z";
|
||||
private static final String WS_AGENT = "ws-agent.tar.gz";
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ExtServerVolumeProvider.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(WsAgentVolumeProvider.class);
|
||||
|
||||
@Inject
|
||||
@Named("machine.server.ext.archive")
|
||||
private String extServerArchivePath;
|
||||
private String wsAgentArchivePath;
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
if (SystemInfo.isWindows()) {
|
||||
try {
|
||||
final Path cheHome = WindowsHostUtils.ensureCheHomeExist();
|
||||
final Path path = Files.copy(Paths.get(extServerArchivePath), cheHome.resolve(WS_AGENT), REPLACE_EXISTING);
|
||||
final Path path = Files.copy(Paths.get(wsAgentArchivePath), cheHome.resolve(WS_AGENT), REPLACE_EXISTING);
|
||||
return path.toString() + CONTAINER_TARGET;
|
||||
} catch (IOException e) {
|
||||
LOG.warn(e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
return extServerArchivePath + CONTAINER_TARGET;
|
||||
return wsAgentArchivePath + CONTAINER_TARGET;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -162,7 +162,8 @@ public class DockerInstanceProviderTest {
|
|||
EnvironmentContext.setCurrent(envCont);
|
||||
|
||||
|
||||
when(recipeRetriever.getRecipe(any(MachineConfig.class))).thenReturn(new RecipeImpl().withType(DOCKER_FILE_TYPE).withScript("FROM codenvy"));
|
||||
when(recipeRetriever.getRecipe(any(MachineConfig.class)))
|
||||
.thenReturn(new RecipeImpl().withType(DOCKER_FILE_TYPE).withScript("FROM codenvy"));
|
||||
|
||||
when(dockerMachineFactory.createNode(anyString(), anyString())).thenReturn(dockerNode);
|
||||
when(dockerConnector.createContainer(any(CreateContainerParams.class)))
|
||||
|
|
|
|||
|
|
@ -1,101 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.docker.machine;
|
||||
|
||||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.eclipse.che.plugin.docker.client.DockerConnector;
|
||||
import org.eclipse.che.plugin.docker.client.Exec;
|
||||
import org.eclipse.che.plugin.docker.client.params.CreateExecParams;
|
||||
import org.eclipse.che.plugin.docker.client.params.StartExecParams;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Max Shaposhnik (mshaposhnik@codenvy.com)
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
@Listeners(value = {MockitoTestNGListener.class})
|
||||
public class DockerMachineTerminalLauncherTest {
|
||||
private static final String LAUNCH_COMMAND = "launch terminal";
|
||||
private static final String CONTAINER = "test container";
|
||||
private static final String EXEC_ID = "testExecId";
|
||||
|
||||
@Mock
|
||||
private DockerConnector docker;
|
||||
@Mock
|
||||
private Instance testMachineInstance;
|
||||
@Mock
|
||||
private DockerInstance dockerInstance;
|
||||
@Mock
|
||||
private Exec exec;
|
||||
|
||||
private DockerMachineImplTerminalLauncher launcher;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() throws Exception {
|
||||
launcher = new DockerMachineImplTerminalLauncher(docker, LAUNCH_COMMAND);
|
||||
|
||||
when(dockerInstance.getContainer()).thenReturn(CONTAINER);
|
||||
when(docker.createExec(CreateExecParams.create(CONTAINER,
|
||||
new String[] {"/bin/bash",
|
||||
"-c",
|
||||
LAUNCH_COMMAND})
|
||||
.withDetach(true)))
|
||||
.thenReturn(exec);
|
||||
when(exec.getId()).thenReturn(EXEC_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnDockerMachineType() throws Exception {
|
||||
assertEquals(launcher.getMachineType(), "docker");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = MachineException.class,
|
||||
expectedExceptionsMessageRegExp = "Docker terminal launcher was used to launch terminal in non-docker machine.")
|
||||
public void shouldThrowExcIfNonDockerInstanceWasPassedAsArgument() throws Exception {
|
||||
launcher.launchTerminal(testMachineInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateDetachedExecWithTerminalCommandInBash() throws Exception {
|
||||
launcher.launchTerminal(dockerInstance);
|
||||
|
||||
verify(docker).createExec(CreateExecParams.create(CONTAINER, new String[] {"/bin/bash", "-c", LAUNCH_COMMAND})
|
||||
.withDetach(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldStartCreatedExec() throws Exception {
|
||||
launcher.launchTerminal(dockerInstance);
|
||||
|
||||
verify(docker).startExec(eq(StartExecParams.create(EXEC_ID)), any());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = MachineException.class,
|
||||
expectedExceptionsMessageRegExp = "test error")
|
||||
public void shouldThrowMachineExceptionIfIOExceptionWasThrownByDocker() throws Exception {
|
||||
when(docker.createExec(any(CreateExecParams.class))).thenThrow(new IOException("test error"));
|
||||
|
||||
launcher.launchTerminal(dockerInstance);
|
||||
}
|
||||
}
|
||||
|
|
@ -1910,4 +1910,4 @@
|
|||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -1901,4 +1901,4 @@
|
|||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,14 @@
|
|||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>javax.ws.rs-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-agent</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-agent-shared</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-core</artifactId>
|
||||
|
|
|
|||
|
|
@ -10,10 +10,12 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.plugin.machine.ssh;
|
||||
|
||||
import org.eclipse.che.api.agent.server.terminal.MachineImplSpecificTerminalLauncher;
|
||||
import org.eclipse.che.api.agent.server.launcher.AbstractAgentLauncher;
|
||||
import org.eclipse.che.api.agent.server.launcher.ProcessIsLaunchedChecker;
|
||||
import org.eclipse.che.api.agent.server.terminal.WebsocketTerminalFilesPathProvider;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.core.ConflictException;
|
||||
import org.eclipse.che.api.core.util.AbstractLineConsumer;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
import org.eclipse.che.api.core.util.ListLineConsumer;
|
||||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.model.impl.CommandImpl;
|
||||
|
|
@ -23,7 +25,6 @@ import org.slf4j.Logger;
|
|||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
|
@ -34,8 +35,9 @@ import static org.slf4j.LoggerFactory.getLogger;
|
|||
* Launch websocket terminal in ssh machines.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
public class SshMachineImplTerminalLauncher implements MachineImplSpecificTerminalLauncher {
|
||||
public class SshMachineImplTerminalLauncher extends AbstractAgentLauncher {
|
||||
private static final Logger LOG = getLogger(SshMachineImplTerminalLauncher.class);
|
||||
|
||||
// Regex to parse output of command 'uname -sm'
|
||||
|
|
@ -46,62 +48,39 @@ public class SshMachineImplTerminalLauncher implements MachineImplSpecificTermin
|
|||
private static final Pattern UNAME_OUTPUT = Pattern.compile("\\[STDOUT\\] (?<os>[\\S]+) (?<architecture>[\\S]+)");
|
||||
private static final String DEFAULT_ARCHITECTURE = "linux_amd64";
|
||||
|
||||
public static final String TERMINAL_LAUNCH_COMMAND_PROPERTY = "machine.ssh.server.terminal.run_command";
|
||||
public static final String TERMINAL_LOCATION_PROPERTY = "machine.ssh.server.terminal.location";
|
||||
|
||||
private final String runTerminalCommand;
|
||||
private final String terminalLocation;
|
||||
private final WebsocketTerminalFilesPathProvider archivePathProvider;
|
||||
private final String terminalLocation;
|
||||
|
||||
@Inject
|
||||
public SshMachineImplTerminalLauncher(@Named(TERMINAL_LAUNCH_COMMAND_PROPERTY) String runTerminalCommand,
|
||||
@Named(TERMINAL_LOCATION_PROPERTY) String terminalLocation,
|
||||
public SshMachineImplTerminalLauncher(@Named("machine.agent.max_start_time_ms") long agentMaxStartTimeMs,
|
||||
@Named("machine.agent.ping_delay_ms") long agentPingDelayMs,
|
||||
@Named("machine.ssh.server.terminal.location") String terminalLocation,
|
||||
WebsocketTerminalFilesPathProvider terminalPathProvider) {
|
||||
this.runTerminalCommand = runTerminalCommand;
|
||||
this.terminalLocation = terminalLocation;
|
||||
super(agentMaxStartTimeMs, agentPingDelayMs, new ProcessIsLaunchedChecker("che-websocket-terminal"));
|
||||
this.archivePathProvider = terminalPathProvider;
|
||||
this.terminalLocation = terminalLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMachineType() {
|
||||
return "ssh";
|
||||
}
|
||||
|
||||
// todo stop outdated terminal
|
||||
// todo check existing version of terminal, do not copy if it is up to date
|
||||
@Override
|
||||
public void launchTerminal(Instance machine) throws MachineException {
|
||||
try {
|
||||
if (!isWebsocketTerminalRunning(machine)) {
|
||||
String architecture = detectArchitecture(machine);
|
||||
|
||||
machine.copy(archivePathProvider.getPath(architecture),
|
||||
terminalLocation);
|
||||
|
||||
startTerminal(machine);
|
||||
}
|
||||
} catch (ConflictException e) {
|
||||
// should never happen
|
||||
throw new MachineException("Internal server error occurs on terminal launching.");
|
||||
}
|
||||
public String getAgentName() {
|
||||
return "org.eclipse.che.terminal";
|
||||
}
|
||||
|
||||
private boolean isWebsocketTerminalRunning(Instance machine) throws MachineException, ConflictException {
|
||||
InstanceProcess checkTerminalAlive = machine.createProcess(
|
||||
new CommandImpl("check if che websocket terminal is running",
|
||||
"ps ax | grep 'che-websocket-terminal' | grep -q -v 'grep che-websocket-terminal' && echo 'found' || echo 'not found'",
|
||||
null),
|
||||
null);
|
||||
ListLineConsumer lineConsumer = new ListLineConsumer();
|
||||
checkTerminalAlive.start(lineConsumer);
|
||||
String checkAliveText = lineConsumer.getText();
|
||||
if ("[STDOUT] not found".equals(checkAliveText)) {
|
||||
return false;
|
||||
} else if (!"[STDOUT] found".equals(checkAliveText)) {
|
||||
LOG.error("Unexpected output of websocket terminal check. Output:" + checkAliveText);
|
||||
return false;
|
||||
@Override
|
||||
public void launch(Instance machine, Agent agent) throws ServerException {
|
||||
try {
|
||||
String architecture = detectArchitecture(machine);
|
||||
machine.copy(archivePathProvider.getPath(architecture), terminalLocation);
|
||||
|
||||
super.launch(machine, agent);
|
||||
} catch (ConflictException e) {
|
||||
// should never happen
|
||||
throw new ServerException("Internal server error occurs on terminal launching.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private String detectArchitecture(Instance machine) throws ConflictException, MachineException {
|
||||
|
|
@ -157,18 +136,4 @@ public class SshMachineImplTerminalLauncher implements MachineImplSpecificTermin
|
|||
return DEFAULT_ARCHITECTURE;
|
||||
}
|
||||
}
|
||||
|
||||
private void startTerminal(Instance machine) throws MachineException, ConflictException {
|
||||
InstanceProcess startTerminal = machine.createProcess(new CommandImpl("websocket terminal",
|
||||
runTerminalCommand,
|
||||
null),
|
||||
null);
|
||||
|
||||
startTerminal.start(new AbstractLineConsumer() {
|
||||
@Override
|
||||
public void writeLine(String line) throws IOException {
|
||||
machine.getLogger().writeLine("[Terminal] " + line);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ import com.google.inject.assistedinject.FactoryModuleBuilder;
|
|||
import com.google.inject.multibindings.Multibinder;
|
||||
import com.google.inject.name.Names;
|
||||
|
||||
import org.eclipse.che.api.agent.server.terminal.MachineImplSpecificTerminalLauncher;
|
||||
|
||||
/**
|
||||
* Provides bindings needed for ssh machine implementation usage.
|
||||
*
|
||||
|
|
@ -40,16 +38,10 @@ public class SshMachineModule extends AbstractModule {
|
|||
org.eclipse.che.plugin.machine.ssh.jsch.JschSshClient.class)
|
||||
.build(SshMachineFactory.class));
|
||||
|
||||
Multibinder<MachineImplSpecificTerminalLauncher> terminalLaunchers =
|
||||
Multibinder.newSetBinder(binder(),
|
||||
MachineImplSpecificTerminalLauncher.class);
|
||||
terminalLaunchers.addBinding().to(SshMachineImplTerminalLauncher.class);
|
||||
bindConstant().annotatedWith(Names.named("machine.ssh.server.terminal.location")).to("~/che");
|
||||
|
||||
bindConstant().annotatedWith(Names.named(SshMachineImplTerminalLauncher.TERMINAL_LAUNCH_COMMAND_PROPERTY))
|
||||
.to("~/che/terminal/che-websocket-terminal -addr :4411 -cmd /bin/bash -static ~/che/terminal/");
|
||||
|
||||
bindConstant().annotatedWith(Names.named(SshMachineImplTerminalLauncher.TERMINAL_LOCATION_PROPERTY))
|
||||
.to("~/che/terminal/");
|
||||
Multibinder.newSetBinder(binder(), org.eclipse.che.api.agent.server.launcher.AgentLauncher.class)
|
||||
.addBinding().to(org.eclipse.che.plugin.machine.ssh.SshMachineImplTerminalLauncher.class);
|
||||
|
||||
Multibinder<org.eclipse.che.api.core.model.machine.ServerConf> machineServers =
|
||||
Multibinder.newSetBinder(binder(),
|
||||
|
|
|
|||
21
pom.xml
21
pom.xml
|
|
@ -66,7 +66,7 @@
|
|||
<groupId>org.eclipse.che</groupId>
|
||||
<artifactId>assembly-wsagent-server</artifactId>
|
||||
<version>${che.version}</version>
|
||||
<type>zip</type>
|
||||
<type>tar.gz</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che</groupId>
|
||||
|
|
@ -80,6 +80,16 @@
|
|||
<version>${che.version}</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-agent</artifactId>
|
||||
<version>${che.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-agent-shared</artifactId>
|
||||
<version>${che.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-auth</artifactId>
|
||||
|
|
@ -319,7 +329,7 @@
|
|||
<groupId>org.eclipse.che.lib</groupId>
|
||||
<artifactId>che-websocket-terminal</artifactId>
|
||||
<version>${che.lib.version}</version>
|
||||
<type>zip</type>
|
||||
<type>tar.gz</type>
|
||||
<classifier>linux_amd64</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
@ -327,6 +337,13 @@
|
|||
<artifactId>che-websocket-terminal</artifactId>
|
||||
<version>${che.lib.version}</version>
|
||||
<type>zip</type>
|
||||
<classifier>linux_amd64</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.lib</groupId>
|
||||
<artifactId>che-websocket-terminal</artifactId>
|
||||
<version>${che.lib.version}</version>
|
||||
<type>tar.gz</type>
|
||||
<classifier>linux_arm7</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
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:
|
||||
Codenvy, S.A. - initial API and implementation
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>che-master-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>5.0.0-M1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-api-agent-shared</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Che Core :: API :: Agent :: Shared</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-dto</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-commons-annotations</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.shared.dto;
|
||||
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.dto.shared.DTO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Anatoliy Bazko
|
||||
*/
|
||||
@DTO
|
||||
public interface AgentDto extends Agent {
|
||||
|
||||
@Override
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
|
||||
AgentDto withName(String name);
|
||||
|
||||
@Override
|
||||
String getVersion();
|
||||
|
||||
void setVersion(String version);
|
||||
|
||||
AgentDto withVersion(String version);
|
||||
|
||||
@Override
|
||||
List<String> getDependencies();
|
||||
|
||||
void setDependencies(List<String> dependencies);
|
||||
|
||||
AgentDto withDependencies(List<String> dependencies);
|
||||
|
||||
@Override
|
||||
String getScript();
|
||||
|
||||
void setScript(String script);
|
||||
|
||||
AgentDto withScript(String script);
|
||||
|
||||
@Override
|
||||
Map<String, String> getProperties();
|
||||
|
||||
void setProperties(Map<String, String> properties);
|
||||
|
||||
AgentDto withProperties(Map<String, String> properties);
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.shared.dto;
|
||||
|
||||
import org.eclipse.che.api.agent.shared.model.AgentKey;
|
||||
import org.eclipse.che.dto.shared.DTO;
|
||||
|
||||
/**
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
@DTO
|
||||
public interface AgentKeyDto extends AgentKey {
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
|
||||
AgentKeyDto withName(String name);
|
||||
|
||||
String getVersion();
|
||||
|
||||
void setVersion(String version);
|
||||
|
||||
AgentKeyDto withVersion(String version);
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.shared.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An entity that might additionally injected into machine and brings functionality.
|
||||
*
|
||||
* @author Anatoliy Bazko
|
||||
*/
|
||||
public interface Agent {
|
||||
|
||||
/**
|
||||
* Returns the name of the agent.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns the version of the agent.
|
||||
*/
|
||||
String getVersion();
|
||||
|
||||
/**
|
||||
* Returns the depending agents, that must be applied before.
|
||||
*/
|
||||
List<String> getDependencies();
|
||||
|
||||
/**
|
||||
* Returns the script to be applied when machine is started.
|
||||
*/
|
||||
String getScript();
|
||||
|
||||
/**
|
||||
* Returns any machine specific properties.
|
||||
*/
|
||||
Map<String, String> getProperties();
|
||||
}
|
||||
|
|
@ -8,18 +8,25 @@
|
|||
* Contributors:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.wsagent;
|
||||
package org.eclipse.che.api.agent.shared.model;
|
||||
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
import org.eclipse.che.api.core.model.machine.Machine;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Starts ws agent in the machine and wait until ws agent sends notification about its start
|
||||
* A pair of name and version of the agent.
|
||||
* Version part is not mandatory.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
public interface WsAgentLauncher {
|
||||
void startWsAgent(Machine devMachine) throws NotFoundException,
|
||||
ServerException;
|
||||
public interface AgentKey {
|
||||
/**
|
||||
* @return the name of the agent
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* @return the version of the agent
|
||||
*/
|
||||
@Nullable
|
||||
String getVersion();
|
||||
}
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
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:
|
||||
Codenvy, S.A. - initial API and implementation
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>che-master-parent</artifactId>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<version>5.0.0-M1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>che-core-api-agent</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Che Core :: API :: Agent</name>
|
||||
<properties>
|
||||
<dto-generator-out-directory>${project.build.directory}/generated-sources/dto/</dto-generator-out-directory>
|
||||
<findbugs.failonerror>false</findbugs.failonerror>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>javax.ws.rs-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-agent-shared</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-dto</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-machine</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-model</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-commons-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-commons-lang</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.everrest</groupId>
|
||||
<artifactId>everrest-assured</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockitong</groupId>
|
||||
<artifactId>mockitong</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<testSourceDirectory>src/test/java</testSourceDirectory>
|
||||
<outputDirectory>target/classes</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>${project.build.directory}/generated-sources/dto/</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-resource</id>
|
||||
<phase>process-sources</phase>
|
||||
<goals>
|
||||
<goal>add-resource</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${dto-generator-out-directory}/META-INF</directory>
|
||||
<targetPath>META-INF</targetPath>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>add-source</id>
|
||||
<phase>process-sources</phase>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>${dto-generator-out-directory}</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>pre-compile</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-dto-maven-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>generate-server-dto</id>
|
||||
<phase>process-sources</phase>
|
||||
<goals>
|
||||
<goal>generate</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<dtoPackages>
|
||||
<package>org.eclipse.che.api.agent.shared.dto</package>
|
||||
</dtoPackages>
|
||||
<outputDirectory>${dto-generator-out-directory}</outputDirectory>
|
||||
<genClassName>org.eclipse.che.api.agent.server.dto.DtoServerImpls</genClassName>
|
||||
<impl>server</impl>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-agent-shared</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
|
||||
/**
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
public class AgentModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(AgentRegistryService.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server;
|
||||
|
||||
import org.eclipse.che.api.agent.server.exception.AgentException;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentNotFoundException;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.agent.shared.model.AgentKey;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The registry for agents that might be injected into machine.
|
||||
*
|
||||
* @see Agent
|
||||
* @see AgentKey
|
||||
*
|
||||
* @author Anatoliy Bazko
|
||||
*/
|
||||
public interface AgentRegistry {
|
||||
|
||||
/**
|
||||
* Gets {@link Agent}.
|
||||
*
|
||||
* @param agentKey
|
||||
* the agent key
|
||||
* @return {@link Agent}
|
||||
* @throws AgentNotFoundException
|
||||
* if agent not found in the registry
|
||||
* @throws AgentException
|
||||
* if unexpected error occurred
|
||||
*/
|
||||
Agent getAgent(AgentKey agentKey) throws AgentException;
|
||||
|
||||
/**
|
||||
* Returns a list of the available versions of the specific agent.
|
||||
*
|
||||
* @param name
|
||||
* the name of the agent
|
||||
* @return list of versions
|
||||
* @throws AgentNotFoundException
|
||||
* if agent not found in the registry
|
||||
* @throws AgentException
|
||||
* if unexpected error occurred
|
||||
*/
|
||||
List<String> getVersions(String name) throws AgentException;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the list of available agents.
|
||||
*
|
||||
* @return list of agents
|
||||
* @throws AgentException
|
||||
* if unexpected error occurred
|
||||
*/
|
||||
List<String> getAgents() throws AgentException;
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.swagger.annotations.ApiResponse;
|
||||
import io.swagger.annotations.ApiResponses;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.api.agent.server.exception.AgentException;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentNotFoundException;
|
||||
import org.eclipse.che.api.agent.server.model.impl.AgentKeyImpl;
|
||||
import org.eclipse.che.api.agent.shared.dto.AgentDto;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.core.ApiException;
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
import org.eclipse.che.api.core.rest.Service;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import java.util.List;
|
||||
|
||||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
|
||||
import static org.eclipse.che.api.agent.server.DtoConverter.asDto;
|
||||
|
||||
/**
|
||||
* Defines Agent REST API.
|
||||
*
|
||||
* @see AgentRegistry
|
||||
* @see Agent
|
||||
*
|
||||
* @author Anatoliy Bazko
|
||||
*/
|
||||
@Api(value = "/agent", description = "Agent REST API")
|
||||
@Path("/agent")
|
||||
public class AgentRegistryService extends Service {
|
||||
|
||||
private final AgentRegistry agentRegistry;
|
||||
|
||||
@Inject
|
||||
public AgentRegistryService(AgentRegistry agentRegistry) {
|
||||
this.agentRegistry = agentRegistry;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/name/{name}")
|
||||
@Produces(APPLICATION_JSON)
|
||||
@ApiOperation(value = "Gets the latest version of the agent", response = AgentDto.class)
|
||||
@ApiResponses({@ApiResponse(code = 200, message = "The response contains requested agent entity"),
|
||||
@ApiResponse(code = 404, message = "Agent not found in the registry"),
|
||||
@ApiResponse(code = 500, message = "Internal server error occurred")})
|
||||
public Agent getByName(@ApiParam("The agent name") @PathParam("name") String name) throws ApiException {
|
||||
try {
|
||||
return asDto(agentRegistry.getAgent(new AgentKeyImpl(name)));
|
||||
} catch (AgentNotFoundException e) {
|
||||
throw new NotFoundException(e.getMessage());
|
||||
} catch (AgentException e) {
|
||||
throw new ServerException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/name/{name}/version/{version}")
|
||||
@Produces(APPLICATION_JSON)
|
||||
@ApiOperation(value = "Gets the specific version of the agent", response = AgentDto.class)
|
||||
@ApiResponses({@ApiResponse(code = 200, message = "The response contains requested agent entity"),
|
||||
@ApiResponse(code = 404, message = "Agent not found in the registry"),
|
||||
@ApiResponse(code = 500, message = "Internal server error occurred")})
|
||||
public Agent getByName(@ApiParam("The agent name") @PathParam("name") String name,
|
||||
@ApiParam("The agent version") @PathParam("version") String version) throws ApiException {
|
||||
try {
|
||||
return asDto(agentRegistry.getAgent(new AgentKeyImpl(name, version)));
|
||||
} catch (AgentNotFoundException e) {
|
||||
throw new NotFoundException(e.getMessage());
|
||||
} catch (AgentException e) {
|
||||
throw new ServerException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/versions/{name}")
|
||||
@Produces(APPLICATION_JSON)
|
||||
@ApiOperation(value = "Get a list of available versions of the giving agent", response = List.class)
|
||||
@ApiResponses({@ApiResponse(code = 200, message = "The response contains available versions of the giving agent"),
|
||||
@ApiResponse(code = 404, message = "Agent not found"),
|
||||
@ApiResponse(code = 500, message = "Internal server error occurred")})
|
||||
public List<String> getVersions(@ApiParam("The agent name") @PathParam("name") String name) throws ApiException {
|
||||
try {
|
||||
return agentRegistry.getVersions(name);
|
||||
} catch (AgentNotFoundException e) {
|
||||
throw new NotFoundException(e.getMessage());
|
||||
} catch (AgentException e) {
|
||||
throw new ServerException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(APPLICATION_JSON)
|
||||
@ApiOperation(value = "Get a list of the available agents", response = List.class)
|
||||
@ApiResponses({@ApiResponse(code = 200, message = "The response contains list of available agents"),
|
||||
@ApiResponse(code = 500, message = "Internal server error occurred")})
|
||||
public List<String> getAgents() throws ApiException {
|
||||
try {
|
||||
return agentRegistry.getAgents();
|
||||
} catch (AgentNotFoundException e) {
|
||||
throw new NotFoundException(e.getMessage());
|
||||
} catch (AgentException e) {
|
||||
throw new ServerException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server;
|
||||
|
||||
import org.eclipse.che.api.agent.server.exception.AgentException;
|
||||
import org.eclipse.che.api.agent.shared.model.AgentKey;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
public interface AgentRegistryUrlProvider {
|
||||
/**
|
||||
* Returns url to download agent of the specific version.
|
||||
*
|
||||
* @param agentKey
|
||||
* the agent name and version
|
||||
* @return {@link URL}
|
||||
* @throws AgentException
|
||||
* if unexpected error occurred
|
||||
*/
|
||||
URL getAgentUrl(AgentKey agentKey) throws AgentException;
|
||||
|
||||
/**
|
||||
* Returns url to fetch available versions of the agent.
|
||||
|
||||
* @param name
|
||||
* the agent name
|
||||
* @return {@link URL}
|
||||
* @throws AgentException
|
||||
* if unexpected error occurred
|
||||
*/
|
||||
URL getAgentVersionsUrl(String name) throws AgentException;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server;
|
||||
|
||||
import org.eclipse.che.api.agent.shared.dto.AgentDto;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
|
||||
import static org.eclipse.che.dto.server.DtoFactory.newDto;
|
||||
|
||||
/**
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
public class DtoConverter {
|
||||
|
||||
public static AgentDto asDto(Agent agent) {
|
||||
return newDto(AgentDto.class).withName(agent.getName())
|
||||
.withVersion(agent.getVersion())
|
||||
.withProperties(agent.getProperties())
|
||||
.withScript(agent.getScript())
|
||||
.withDependencies(agent.getDependencies());
|
||||
}
|
||||
|
||||
private DtoConverter() { }
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.exception;
|
||||
|
||||
/**
|
||||
* @author Anatoliy Bazko
|
||||
*/
|
||||
public class AgentException extends Exception {
|
||||
public AgentException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AgentException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.exception;
|
||||
|
||||
/**
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
public class AgentNotFoundException extends AgentException {
|
||||
public AgentNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AgentNotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.impl;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.agent.server.AgentRegistry;
|
||||
import org.eclipse.che.api.agent.server.AgentRegistryUrlProvider;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentException;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentNotFoundException;
|
||||
import org.eclipse.che.api.agent.shared.dto.AgentDto;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.agent.shared.model.AgentKey;
|
||||
import org.eclipse.che.api.core.ApiException;
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
|
||||
import org.eclipse.che.api.core.rest.HttpJsonResponse;
|
||||
import org.eclipse.che.api.core.util.FileCleaner;
|
||||
import org.eclipse.che.dto.server.DtoFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.eclipse.che.commons.lang.IoUtil.downloadFile;
|
||||
import static org.eclipse.che.commons.lang.IoUtil.readAndCloseQuietly;
|
||||
|
||||
/**
|
||||
* @author Anatoliy Bazko
|
||||
*/
|
||||
@Singleton
|
||||
public class AgentRegistryImpl implements AgentRegistry {
|
||||
private final AgentRegistryUrlProvider urlProvider;
|
||||
private final HttpJsonRequestFactory requestFactory;
|
||||
|
||||
@Inject
|
||||
public AgentRegistryImpl(AgentRegistryUrlProvider urlProvider,
|
||||
HttpJsonRequestFactory requestFactory) {
|
||||
this.urlProvider = urlProvider;
|
||||
this.requestFactory = requestFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Agent getAgent(AgentKey agentKey) throws AgentException {
|
||||
return doGetRemoteAgent(urlProvider.getAgentUrl(agentKey));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getVersions(String name) throws AgentException {
|
||||
URL url = urlProvider.getAgentVersionsUrl(name);
|
||||
try {
|
||||
HttpJsonResponse response = requestFactory.fromUrl(url.toString()).useGetMethod().request();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> versions = response.as(List.class, new TypeToken<List<String>>() { }.getType());
|
||||
|
||||
return versions;
|
||||
} catch (NotFoundException e) {
|
||||
throw new AgentNotFoundException(format("Agent %s not found", name), e);
|
||||
} catch (IOException | ApiException e) {
|
||||
throw new AgentException(format("Can't fetch available %s version.", name), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAgents() throws AgentException {
|
||||
return asList("org.eclipse.che.terminal",
|
||||
"org.eclipse.che.ws-agent",
|
||||
"org.eclipse.che.ssh");
|
||||
}
|
||||
|
||||
protected Agent doGetRemoteAgent(URL url) throws AgentException {
|
||||
File agent = null;
|
||||
try {
|
||||
agent = downloadFile(new File(System.getProperty("java.io.tmpdir")), "agent", ".tmp", url);
|
||||
String json = readAndCloseQuietly(new FileInputStream(agent));
|
||||
return DtoFactory.getInstance().createDtoFromJson(json, AgentDto.class);
|
||||
} catch (IOException | IllegalArgumentException e) {
|
||||
throw new AgentException("Can't fetch agent configuration", e);
|
||||
} finally {
|
||||
if (agent != null) {
|
||||
try {
|
||||
Files.delete(agent.toPath());
|
||||
} catch (IOException e) {
|
||||
FileCleaner.addFile(agent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.impl;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.agent.server.AgentRegistryUrlProvider;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentException;
|
||||
import org.eclipse.che.api.agent.shared.model.AgentKey;
|
||||
|
||||
import javax.inject.Named;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Provides urls to agents.
|
||||
*
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
@Singleton
|
||||
public class AgentRegistryUrlProviderImpl implements AgentRegistryUrlProvider {
|
||||
public static final String VERSION = "${version}";
|
||||
public static final String NAME = "${name}";
|
||||
|
||||
private final String agentLatestVersionUrl;
|
||||
private final String agentSpecificVersionUrl;
|
||||
private final String agentVersionsUrl;
|
||||
|
||||
@Inject
|
||||
public AgentRegistryUrlProviderImpl(@Named("machine.agent.latest_version_url") String agentLatestVersionUrl,
|
||||
@Named("machine.agent.specific_version_url") String agentSpecificVersionUrl,
|
||||
@Named("machine.agent.all_versions_url") String agentVersionsUrl) {
|
||||
this.agentLatestVersionUrl = agentLatestVersionUrl;
|
||||
this.agentSpecificVersionUrl = agentSpecificVersionUrl;
|
||||
this.agentVersionsUrl = agentVersionsUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getAgentUrl(AgentKey agentKey) throws AgentException {
|
||||
String url;
|
||||
if (agentKey.getVersion() == null) {
|
||||
url = agentLatestVersionUrl.replace(NAME, agentKey.getName());
|
||||
} else {
|
||||
url = agentSpecificVersionUrl.replace(NAME, agentKey.getName()).replace(VERSION, agentKey.getVersion());
|
||||
}
|
||||
try {
|
||||
return new URL(url);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new AgentException("Malformed url " + url, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public URL getAgentVersionsUrl(String name) throws AgentException {
|
||||
String url = agentVersionsUrl.replace(NAME, name);
|
||||
try {
|
||||
return new URL(url);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new AgentException("Malformed url " + url, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.impl;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.agent.server.AgentRegistry;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentException;
|
||||
import org.eclipse.che.api.agent.server.model.impl.AgentKeyImpl;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.agent.shared.model.AgentKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Sort agents respecting dependencies between them.
|
||||
*
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
@Singleton
|
||||
public class AgentSorter {
|
||||
|
||||
private final AgentRegistry agentRegistry;
|
||||
|
||||
@Inject
|
||||
public AgentSorter(AgentRegistry agentRegistry) {
|
||||
this.agentRegistry = agentRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort agents respecting dependencies between them.
|
||||
* Handles circular dependencies.
|
||||
*
|
||||
* @see AgentKey
|
||||
* @see Agent#getDependencies()
|
||||
* @see AgentRegistry#getAgent(AgentKey)
|
||||
*
|
||||
* @param agentKeys list of agents to sort
|
||||
* @return list of created agents in proper order
|
||||
*
|
||||
* @throws AgentException
|
||||
* if circular dependency found or agent creation failed or other unexpected error
|
||||
*/
|
||||
public List<AgentKey> sort(List<String> agentKeys) throws AgentException {
|
||||
List<AgentKey> sorted = new ArrayList<>();
|
||||
Set<String> pending = new HashSet<>();
|
||||
|
||||
if (agentKeys != null) {
|
||||
for (String agentKey : agentKeys) {
|
||||
doSort(agentKeys, AgentKeyImpl.parse(agentKey), sorted, pending);
|
||||
}
|
||||
}
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
private void doSort(List<String> agentKeys, AgentKey agentKey, List<AgentKey> sorted, Set<String> pending) throws AgentException {
|
||||
String agentName = agentKey.getName();
|
||||
|
||||
Optional<AgentKey> alreadySorted = sorted.stream().filter(k -> k.getName().equals(agentName)).findFirst();
|
||||
if (alreadySorted.isPresent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pending.add(agentName)) {
|
||||
throw new AgentException("Agents circular dependency found.");
|
||||
}
|
||||
|
||||
Agent agent = agentRegistry.getAgent(agentKey);
|
||||
|
||||
for (String dependency : agent.getDependencies()) {
|
||||
if (agentKeys.contains(dependency)) {
|
||||
doSort(agentKeys, AgentKeyImpl.parse(dependency), sorted, pending);
|
||||
}
|
||||
}
|
||||
|
||||
sorted.add(agentKey);
|
||||
pending.remove(agentName);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.impl;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.agent.server.AgentRegistry;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentException;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentNotFoundException;
|
||||
import org.eclipse.che.api.agent.shared.dto.AgentDto;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.agent.shared.model.AgentKey;
|
||||
import org.eclipse.che.api.core.util.FileCleaner;
|
||||
import org.eclipse.che.commons.lang.ZipUtils;
|
||||
import org.eclipse.che.dto.server.DtoFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.eclipse.che.commons.lang.IoUtil.downloadFile;
|
||||
import static org.eclipse.che.commons.lang.IoUtil.readAndCloseQuietly;
|
||||
import static org.eclipse.che.commons.lang.ZipUtils.isZipFile;
|
||||
|
||||
/**
|
||||
* Local implementation of the {@link AgentRegistry}.
|
||||
* The name of the agent might represent a url.
|
||||
*
|
||||
* @author Anatoliy Bazko
|
||||
*/
|
||||
@Singleton
|
||||
public class LocalAgentRegistryImpl implements AgentRegistry {
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(LocalAgentRegistryImpl.class);
|
||||
private static final Pattern AGENTS = Pattern.compile(".*[//]?agents/[^//]+[.]json");
|
||||
|
||||
private final Map<String, Agent> agents;
|
||||
private final List<String> agentNames;
|
||||
|
||||
@Inject
|
||||
public LocalAgentRegistryImpl() throws IOException {
|
||||
this.agents = new HashMap<>();
|
||||
findAgents();
|
||||
this.agentNames = ImmutableList.copyOf(agents.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Agent getAgent(AgentKey agentKey) throws AgentException {
|
||||
return doGetAgent(agentKey.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getVersions(String name) throws AgentException {
|
||||
Agent agent = doGetAgent(name);
|
||||
String version = agent.getVersion();
|
||||
return version == null ? Collections.emptyList() : singletonList(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAgents() throws AgentException {
|
||||
return agentNames;
|
||||
}
|
||||
|
||||
protected Agent doGetAgent(String name) throws AgentException {
|
||||
try {
|
||||
URL url = new URL(name);
|
||||
return doGetRemoteAgent(url);
|
||||
} catch (MalformedURLException ignored) {
|
||||
// name doesn't represent a url
|
||||
}
|
||||
|
||||
Optional<Agent> agent = Optional.ofNullable(agents.get(name));
|
||||
return agent.orElseThrow(() -> new AgentNotFoundException(format("Agent %s not found", name)));
|
||||
}
|
||||
|
||||
protected Agent doGetRemoteAgent(URL url) throws AgentException {
|
||||
File agent = null;
|
||||
try {
|
||||
agent = downloadFile(new File(System.getProperty("java.io.tmpdir")), "agent", ".tmp", url);
|
||||
String json = readAndCloseQuietly(new FileInputStream(agent));
|
||||
return DtoFactory.getInstance().createDtoFromJson(json, AgentDto.class);
|
||||
} catch (IOException | IllegalArgumentException e) {
|
||||
throw new AgentException("Can't fetch agent configuration", e);
|
||||
} finally {
|
||||
if (agent != null) {
|
||||
try {
|
||||
Files.delete(agent.toPath());
|
||||
} catch (IOException e) {
|
||||
FileCleaner.addFile(agent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void findAgents() throws IOException {
|
||||
File context = new File(LocalAgentRegistryImpl.class.getProtectionDomain().getCodeSource().getLocation().getPath());
|
||||
|
||||
if (isZipFile(context)) {
|
||||
try (ZipFile zip = new ZipFile(context)) {
|
||||
ZipUtils.getResources(zip, AGENTS, createAgentsConsumer);
|
||||
}
|
||||
} else {
|
||||
Files.walk(context.toPath())
|
||||
.filter(path -> AGENTS.matcher(path.toString()).matches())
|
||||
.forEach(path -> {
|
||||
try (InputStream in = Files.newInputStream(path)) {
|
||||
createAgentsConsumer.accept(in);
|
||||
} catch (IOException ignored) {
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private Consumer<InputStream> createAgentsConsumer = new Consumer<InputStream>() {
|
||||
@Override
|
||||
public void accept(InputStream inputStream) {
|
||||
try {
|
||||
final Agent agent = DtoFactory.getInstance().createDtoFromJson(inputStream, AgentDto.class);
|
||||
agents.put(agent.getName(), agent);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Can't create agent.", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.launcher;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.core.ConflictException;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
import org.eclipse.che.api.core.model.machine.Command;
|
||||
import org.eclipse.che.api.core.util.AbstractLineConsumer;
|
||||
import org.eclipse.che.api.core.util.LineConsumer;
|
||||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.model.impl.CommandImpl;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.eclipse.che.api.machine.server.spi.InstanceProcess;
|
||||
import org.eclipse.che.commons.lang.concurrent.ThreadLocalPropagateContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
/**
|
||||
* Launch agent script asynchronously over target instance and wait when it run.
|
||||
* The policy of checking if agent is run might be different for agents.
|
||||
*
|
||||
* @see Agent#getScript()
|
||||
* @see AgentLaunchingChecker
|
||||
* @see AgentLaunchingChecker#DEFAULT
|
||||
*
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
public abstract class AbstractAgentLauncher implements AgentLauncher {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractAgentLauncher.class);
|
||||
private static final ExecutorService executor =
|
||||
Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("AgentLauncher-%d")
|
||||
.setDaemon(true)
|
||||
.build());
|
||||
|
||||
private final AgentLaunchingChecker agentLaunchingChecker;
|
||||
private final long agentPingDelayMs;
|
||||
private final long agentMaxStartTimeMs;
|
||||
|
||||
public AbstractAgentLauncher(long agentMaxStartTimeMs,
|
||||
long agentPingDelayMs,
|
||||
AgentLaunchingChecker agentLaunchingChecker) {
|
||||
this.agentPingDelayMs = agentPingDelayMs;
|
||||
this.agentMaxStartTimeMs = agentMaxStartTimeMs;
|
||||
this.agentLaunchingChecker = agentLaunchingChecker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(Instance machine, Agent agent) throws ServerException {
|
||||
try {
|
||||
final InstanceProcess process = start(machine, agent);
|
||||
LOG.debug("Waiting for agent {} is launched. Workspace ID:{}", agent.getName(), machine.getWorkspaceId());
|
||||
|
||||
final long pingStartTimestamp = System.currentTimeMillis();
|
||||
while (System.currentTimeMillis() - pingStartTimestamp < agentMaxStartTimeMs) {
|
||||
if (agentLaunchingChecker.isLaunched(agent, process, machine)) {
|
||||
return;
|
||||
} else {
|
||||
Thread.sleep(agentPingDelayMs);
|
||||
}
|
||||
}
|
||||
|
||||
process.kill();
|
||||
} catch (MachineException e) {
|
||||
throw new ServerException(e.getServiceError());
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new ServerException(format("Launching agent %s is interrupted", agent.getName()));
|
||||
}
|
||||
|
||||
final String errMsg = format("Fail launching agent %s. Workspace ID:%s", agent.getName(), machine.getWorkspaceId());
|
||||
LOG.error(errMsg);
|
||||
throw new ServerException(errMsg);
|
||||
}
|
||||
|
||||
|
||||
protected InstanceProcess start(final Instance machine, final Agent agent) throws ServerException {
|
||||
final Command command = new CommandImpl(agent.getName(), agent.getScript(), "agent");
|
||||
final InstanceProcess process = machine.createProcess(command, null);
|
||||
final LineConsumer lineConsumer = new AbstractLineConsumer() {
|
||||
@Override
|
||||
public void writeLine(String line) throws IOException {
|
||||
machine.getLogger().writeLine(line);
|
||||
}
|
||||
};
|
||||
|
||||
executor.execute(ThreadLocalPropagateContext.wrap(() -> {
|
||||
try {
|
||||
process.start(lineConsumer);
|
||||
} catch (ConflictException | MachineException e) {
|
||||
try {
|
||||
machine.getLogger().writeLine(format("[ERROR] %s", e.getMessage()));
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
lineConsumer.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
return process;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.launcher;
|
||||
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
|
||||
/**
|
||||
* Launches {@link Agent#getScript()} on the {@link Instance}.
|
||||
*
|
||||
* @see Instance
|
||||
* @see Agent#getScript()
|
||||
*
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
public interface AgentLauncher {
|
||||
|
||||
/**
|
||||
* @return the name of the agent that launcher is designed for
|
||||
*/
|
||||
String getAgentName();
|
||||
|
||||
/**
|
||||
* @return the machine type that launcher is designed for
|
||||
*/
|
||||
String getMachineType();
|
||||
|
||||
/**
|
||||
* Executes agents scripts over target machine.
|
||||
* The machine should be started.
|
||||
*
|
||||
* @see Agent#getScript()
|
||||
*
|
||||
* @param machine
|
||||
* the machine instance
|
||||
* @param agent
|
||||
* the agent
|
||||
* @throws ServerException
|
||||
* if script execution failed
|
||||
*/
|
||||
void launch(Instance machine, Agent agent) throws ServerException;
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.launcher;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.core.model.machine.MachineConfig;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Provides {@link AgentLauncher} for specific agent to be run on instance.
|
||||
* Returning agent depends on machine type. If no agent found then the default one
|
||||
* will be returned.
|
||||
*
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
@Singleton
|
||||
public class AgentLauncherFactory {
|
||||
|
||||
private final Set<AgentLauncher> launchers;
|
||||
private final AgentLauncher defaultLauncher;
|
||||
|
||||
@Inject
|
||||
public AgentLauncherFactory(Set<AgentLauncher> launchers, DefaultAgentLauncher defaultLauncher) {
|
||||
this.launchers = launchers;
|
||||
this.defaultLauncher = defaultLauncher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find launcher for given agent independently of version.
|
||||
* If the specific {@link AgentLauncher} isn't registered then the default one will be used.
|
||||
*
|
||||
* @see Agent#getName()
|
||||
* @see MachineConfig#getType()
|
||||
*
|
||||
* @param agentName
|
||||
* the agent name
|
||||
* @param machineType
|
||||
* the machine type
|
||||
* @return {@link AgentLauncher}
|
||||
*/
|
||||
public AgentLauncher find(String agentName, String machineType) {
|
||||
return launchers.stream()
|
||||
.filter(l -> l.getAgentName().equals(agentName))
|
||||
.filter(l -> l.getMachineType().equals(machineType))
|
||||
.findAny()
|
||||
.orElse(defaultLauncher);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.launcher;
|
||||
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.eclipse.che.api.machine.server.spi.InstanceProcess;
|
||||
|
||||
/**
|
||||
* Indicates if agent finished working.
|
||||
*
|
||||
* @author Anatoliy Bazko
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface AgentLaunchingChecker {
|
||||
|
||||
/**
|
||||
* Indicates if agent finished working.
|
||||
*
|
||||
* @param agent
|
||||
* the agent is being launched
|
||||
* @param process
|
||||
* the process is generated by launching the target agent
|
||||
* @param machine
|
||||
* the machine instance
|
||||
* @throws MachineException
|
||||
* if unexpected error is occurred
|
||||
*/
|
||||
boolean isLaunched(Agent agent, InstanceProcess process, Instance machine) throws MachineException;
|
||||
|
||||
AgentLaunchingChecker DEFAULT = (agent, process, machine) -> !process.isAlive();
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.launcher;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
/**
|
||||
* Launches agent and waits while it is finished.
|
||||
*
|
||||
* This agents is suited only for those types of agents that install software
|
||||
* and finish working without launching any processes at the end.
|
||||
*
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
@Singleton
|
||||
public class DefaultAgentLauncher extends AbstractAgentLauncher {
|
||||
@Inject
|
||||
public DefaultAgentLauncher(@Named("machine.agent.max_start_time_ms") long agentMaxStartTimeMs,
|
||||
@Named("machine.agent.ping_delay_ms") long agentPingDelayMs) {
|
||||
super(agentMaxStartTimeMs, agentPingDelayMs, AgentLaunchingChecker.DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAgentName() {
|
||||
return "any";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMachineType() {
|
||||
return "any";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.launcher;
|
||||
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.core.ConflictException;
|
||||
import org.eclipse.che.api.core.model.machine.Command;
|
||||
import org.eclipse.che.api.core.util.ListLineConsumer;
|
||||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.model.impl.CommandImpl;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.eclipse.che.api.machine.server.spi.InstanceProcess;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
/**
|
||||
* Verifies if agent started a process with specific name.
|
||||
* It is an indicator that process had been finished.
|
||||
*
|
||||
* @author Anatoliy Bazko
|
||||
*/
|
||||
public class ProcessIsLaunchedChecker implements AgentLaunchingChecker {
|
||||
|
||||
private final String processNameToWait;
|
||||
private long counter;
|
||||
|
||||
public ProcessIsLaunchedChecker(String processNameToWait) {
|
||||
this.processNameToWait = processNameToWait;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLaunched(Agent agent, InstanceProcess process, Instance machine) throws MachineException {
|
||||
Command command = new CommandImpl(format("Wait for %s, try %d", agent.getName(), ++counter),
|
||||
format("ps -fC %s 1>/dev/null && echo 0 || echo 1", processNameToWait),
|
||||
"test");
|
||||
|
||||
try (ListLineConsumer lineConsumer = new ListLineConsumer()) {
|
||||
InstanceProcess waitProcess = machine.createProcess(command, null);
|
||||
waitProcess.start(lineConsumer);
|
||||
return lineConsumer.getText().endsWith("[STDOUT] 0");
|
||||
} catch (ConflictException e) {
|
||||
throw new MachineException(e.getServiceError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.model.impl;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Anatoliy Bazko
|
||||
*/
|
||||
public class AgentImpl implements Agent {
|
||||
private final String name;
|
||||
private final String version;
|
||||
private final List<String> dependencies;
|
||||
private final Map<String, String> properties;
|
||||
private final String script;
|
||||
|
||||
public AgentImpl(String name,
|
||||
String version,
|
||||
List<String> dependencies,
|
||||
Map<String, String> properties,
|
||||
String script) {
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
this.dependencies = dependencies;
|
||||
this.properties = properties;
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
public AgentImpl(Agent agent) {
|
||||
this(agent.getName(),
|
||||
agent.getVersion(),
|
||||
agent.getDependencies(),
|
||||
agent.getProperties(),
|
||||
agent.getScript());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDependencies() {
|
||||
return MoreObjects.firstNonNull(dependencies, new ArrayList<String>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getProperties() {
|
||||
return MoreObjects.firstNonNull(properties, new HashMap<String, String>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScript() {
|
||||
return script;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof AgentImpl)) {
|
||||
return false;
|
||||
}
|
||||
final AgentImpl that = (AgentImpl)obj;
|
||||
return Objects.equals(name, that.name)
|
||||
&& Objects.equals(version, that.version)
|
||||
&& getDependencies().equals(that.getDependencies())
|
||||
&& getProperties().equals(that.getProperties())
|
||||
&& Objects.equals(script, that.script);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 31 * hash + Objects.hashCode(name);
|
||||
hash = 31 * hash + Objects.hashCode(version);
|
||||
hash = 31 * hash + getDependencies().hashCode();
|
||||
hash = 31 * hash + getProperties().hashCode();
|
||||
hash = 31 * hash + Objects.hashCode(script);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AgentImpl{" +
|
||||
"name='" + name + '\'' +
|
||||
", version='" + version + '\'' +
|
||||
", dependencies='" + dependencies + '\'' +
|
||||
", properties='" + properties + "\'}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.model.impl;
|
||||
|
||||
import org.eclipse.che.api.agent.shared.model.AgentKey;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
public class AgentKeyImpl implements AgentKey {
|
||||
private final String name;
|
||||
private final String version;
|
||||
|
||||
public AgentKeyImpl(String name, @Nullable String version) {
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public AgentKeyImpl(String name) {
|
||||
this(name, null);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method. Agent key is basically a string meeting the format: {@code name:version}.
|
||||
* The version part can be omitted.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* in case of wrong format
|
||||
*/
|
||||
public static AgentKeyImpl parse(String agentKey) throws IllegalArgumentException {
|
||||
String[] parts = agentKey.split(":");
|
||||
|
||||
if (parts.length == 1) {
|
||||
return new AgentKeyImpl(parts[0], null);
|
||||
} else if (parts.length == 2) {
|
||||
return new AgentKeyImpl(parts[0], parts[1]);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Illegal format: " + agentKey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof AgentKeyImpl)) return false;
|
||||
AgentKeyImpl agentKey = (AgentKeyImpl)o;
|
||||
return Objects.equals(name, agentKey.name) &&
|
||||
Objects.equals(version, agentKey.version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, version);
|
||||
}
|
||||
|
||||
public String asString() {
|
||||
return name + (version != null ? ":" + version : "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AgentImpl{" +
|
||||
"name='" + name + '\'' +
|
||||
", version='" + version + "\'}";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "org.eclipse.che.ssh",
|
||||
"dependencies": [],
|
||||
"properties": {},
|
||||
"script" : "#\n# Copyright (c) 2012-2016 Codenvy, S.A.\n# All rights reserved. This program and the accompanying materials\n# are made available under the terms of the Eclipse Public License v1.0\n# which accompanies this distribution, and is available at\n# http://www.eclipse.org/legal/epl-v10.html\n#\n# Contributors:\n# Codenvy, S.A. - initial API and implementation\n#\n\nunset SUDO\nunset PACKAGES\ntest \"$(id -u)\" = 0 || SUDO=\"sudo\"\n\nLINUX_TYPE=$(cat /etc/os-release | grep ^ID= | tr '[:upper:]' '[:lower:]')\nLINUX_VERSION=$(cat /etc/os-release | grep ^VERSION=)\n\n###############################\n### Install Needed packaged ###\n###############################\n\n# Red Hat Enterprise Linux 7 \n############################\nif echo ${LINUX_TYPE} | grep -qi \"rhel\"; then\n command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}\" openssh-server\"; }\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} yum -y install ${PACKAGES};\n }\n ${SUDO} sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd\n\n# Ubuntu 14.04 16.04 / Linux Mint 17 \n####################################\nelif echo ${LINUX_TYPE} | grep -qi \"ubuntu\"; then\n command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}\" openssh-server\"; }\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} apt-get update;\n ${SUDO} apt-get -y install ${PACKAGES};\n }\n ${SUDO} sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd\n\n# Debian 8\n##########\nelif echo ${LINUX_TYPE} | grep -qi \"debian\"; then\n command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}\" openssh-server\"; }\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} apt-get update;\n ${SUDO} apt-get -y install ${PACKAGES};\n }\n ${SUDO} sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd\n\n# Fedora 23\n###########\nelif echo ${LINUX_TYPE} | grep -qi \"fedora\"; then\n PACKAGES=${PACKAGES}\" procps-ng\"\n command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}\" openssh-server\"; }\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} dnf -y install ${PACKAGES};\n }\n ${SUDO} sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd\n\n# CentOS 7.1 & Oracle Linux 7.1\n###############################\nelif echo ${LINUX_TYPE} | grep -qi \"centos\"; then\n command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}\" openssh-server\"; }\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} yum -y install ${PACKAGES};\n }\n ${SUDO} sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd\n\n# openSUSE 13.2\n###############\nelif echo ${LINUX_TYPE} | grep -qi \"opensuse\"; then\n command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}\" openSSH\"; }\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} zypper install -y ${PACKAGES};\n }\n ${SUDO} sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd\n\n# Alpine 3.3\n############$$\nelif echo ${LINUX_TYPE} | grep -qi \"alpine\"; then\n command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}\" openssh\"; }\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} apk update;\n ${SUDO} apk add openssh ${PACKAGES};\n }\n\nelse\n >&2 echo \"Unrecognized Linux Type\"\n >&2 cat /etc/os-release\n exit 1\nfi\n\nps -fC sshd && exit\n\n${SUDO} mkdir -p /var/run/sshd\n${SUDO} /usr/bin/ssh-keygen -A && ${SUDO} /usr/sbin/sshd -D\n"
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "org.eclipse.che.terminal",
|
||||
"dependencies": [],
|
||||
"properties": {
|
||||
"ports": "terminal:4411/tcp"
|
||||
},
|
||||
"script" : "#\n# Copyright (c) 2012-2016 Codenvy, S.A.\n# All rights reserved. This program and the accompanying materials\n# are made available under the terms of the Eclipse Public License v1.0\n# which accompanies this distribution, and is available at\n# http://www.eclipse.org/legal/epl-v10.html\n#\n# Contributors:\n# Codenvy, S.A. - initial API and implementation\n#\n\nunset PACKAGES\nunset SUDO\ncommand -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}\" tar\"; }\ncommand -v curl >/dev/null 2>&1 || { PACKAGES=${PACKAGES}\" curl\"; }\ntest \"$(id -u)\" = 0 || SUDO=\"sudo\"\n\nCHE_DIR=$HOME/che\nAGENT_BINARIES_URI=\"file:///mnt/che/terminal/websocket-terminal-\\${PREFIX}.tar.gz\"\nTARGET_AGENT_BINARIES_URI=\"file://\"${CHE_DIR}\"/websocket-terminal-\\${PREFIX}.tar.gz\"\nLINUX_TYPE=$(cat /etc/os-release | grep ^ID= | tr '[:upper:]' '[:lower:]')\nLINUX_VERSION=$(cat /etc/os-release | grep ^VERSION=)\nMACHINE_TYPE=$(uname -m)\n\nmkdir -p ${CHE_DIR}\n\n########################\n### Install packages ###\n########################\n\n# Red Hat Enterprise Linux 7 \n############################\nif echo ${LINUX_TYPE} | grep -qi \"rhel\"; then\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} yum install ${PACKAGES};\n }\n\n# Ubuntu 14.04 16.04 / Linux Mint 17 \n####################################\nelif echo ${LINUX_TYPE} | grep -qi \"ubuntu\"; then\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} apt-get update;\n ${SUDO} apt-get -y install ${PACKAGES};\n }\n\n# Debian 8\n##########\nelif echo ${LINUX_TYPE} | grep -qi \"debian\"; then\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} apt-get update;\n ${SUDO} apt-get -y install ${PACKAGES};\n }\n\n# Fedora 23 \n###########\nelif echo ${LINUX_TYPE} | grep -qi \"fedora\"; then\n PACKAGES=${PACKAGES}\" procps-ng\"\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} dnf -y install ${PACKAGES};\n }\n\n# CentOS 7.1 & Oracle Linux 7.1\n###############################\nelif echo ${LINUX_TYPE} | grep -qi \"centos\"; then\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} yum -y install ${PACKAGES};\n }\n\n# openSUSE 13.2\n###############\nelif echo ${LINUX_TYPE} | grep -qi \"opensuse\"; then\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} zypper install -y ${PACKAGES};\n }\n\n# Alpine 3.3\n############$$\nelif echo ${LINUX_TYPE} | grep -qi \"alpine\"; then\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} apk update\n ${SUDO} apk add ${PACKAGES};\n }\n\nelse\n >&2 echo \"Unrecognized Linux Type\"\n >&2 cat /etc/os-release\n exit 1\nfi\n\nps -fC che-websocket-terminal && exit\n\n########################\n### Install Terminal ###\n########################\nif echo ${MACHINE_TYPE} | grep -qi \"x86_64\"; then\n PREFIX=linux_amd64\nelif echo ${MACHINE_TYPE} | grep -qi \"arm5\"; then\n PREFIX=linux_arm7\nelif echo ${MACHINE_TYPE} | grep -qi \"arm6\"; then\n PREFIX=linux_arm7\nelif echo ${MACHINE_TYPE} | grep -qi \"arm7\"; then\n PREFIX=linux_arm7\nelse\n >&2 echo \"Unrecognized Machine Type\"\n >&2 uname -a\n exit 1\nfi\n\nif curl -o /dev/null --silent --head --fail $(echo ${AGENT_BINARIES_URI} | sed -s 's/\\${PREFIX}/'${PREFIX}'/g'); then\n curl -o $(echo ${TARGET_AGENT_BINARIES_URI} | sed -s 's/\\${PREFIX}/'${PREFIX}'/g' | sed -s 's/file:\\/\\///g') -s $(echo ${AGENT_BINARIES_URI} | sed -s 's/\\${PREFIX}/'${PREFIX}'/g')\nelif curl -o /dev/null --silent --head --fail $(echo ${AGENT_BINARIES_URI} | sed -s 's/-\\${PREFIX}//g'); then\n curl -o $(echo ${TARGET_AGENT_BINARIES_URI} | sed -s 's/\\${PREFIX}/'${PREFIX}'/g' | sed -s 's/file:\\/\\///g') -s $(echo ${AGENT_BINARIES_URI} | sed -s 's/-\\${PREFIX}//g')\nfi\n\ncurl -s $(echo ${TARGET_AGENT_BINARIES_URI} | sed -s 's/\\${PREFIX}/'${PREFIX}'/g') | tar xzf - -C ${CHE_DIR}\n$HOME/che/terminal/che-websocket-terminal -addr :4411 -cmd /bin/bash -static $HOME/che/terminal/"
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "org.eclipse.che.ws-agent",
|
||||
"dependencies": ["org.eclipse.che.terminal"],
|
||||
"properties": {
|
||||
"ports": "ws-agent.debug:4403/tcp,ws-agent:4401/tcp"
|
||||
},
|
||||
"script" : "#\n# Copyright (c) 2012-2016 Codenvy, S.A.\n# All rights reserved. This program and the accompanying materials\n# are made available under the terms of the Eclipse Public License v1.0\n# which accompanies this distribution, and is available at\n# http://www.eclipse.org/legal/epl-v10.html\n#\n# Contributors:\n# Codenvy, S.A. - initial API and implementation\n#\n\nunset PACKAGES\nunset SUDO\ncommand -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}\" tar\"; }\ncommand -v curl >/dev/null 2>&1 || { PACKAGES=${PACKAGES}\" curl\"; }\ntest \"$(id -u)\" = 0 || SUDO=\"sudo\"\n\nAGENT_BINARIES_URI=file:///mnt/che/ws-agent.tar.gz\nCHE_DIR=$HOME/che\nLINUX_TYPE=$(cat /etc/os-release | grep ^ID= | tr '[:upper:]' '[:lower:]')\nLINUX_VERSION=$(cat /etc/os-release | grep ^VERSION=)\nMACHINE_TYPE=$(uname -m)\n\nmkdir -p ${CHE_DIR}\n${SUDO} mkdir -p /projects\n${SUDO} sh -c \"chown -R $(id -u -n) /projects\"\n\n########################\n### Install packages ###\n########################\n\n# Red Hat Enterprise Linux 7\n############################\nif echo ${LINUX_TYPE} | grep -qi \"rhel\"; then\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} yum install ${PACKAGES};\n }\n\n# Ubuntu 14.04 16.04 / Linux Mint 17\n####################################\nelif echo ${LINUX_TYPE} | grep -qi \"ubuntu\"; then\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} apt-get update;\n ${SUDO} apt-get -y install ${PACKAGES};\n }\n\n# Debian 8\n##########\nelif echo ${LINUX_TYPE} | grep -qi \"debian\"; then\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} apt-get update;\n ${SUDO} apt-get -y install ${PACKAGES};\n }\n\n# Fedora 23\n###########\nelif echo ${LINUX_TYPE} | grep -qi \"fedora\"; then\n PACKAGES=${PACKAGES}\" procps-ng\"\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} dnf -y install ${PACKAGES};\n }\n\n# CentOS 7.1 & Oracle Linux 7.1\n###############################\nelif echo ${LINUX_TYPE} | grep -qi \"centos\"; then\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} yum -y install ${PACKAGES};\n }\n\n# openSUSE 13.2\n###############\nelif echo ${LINUX_TYPE} | grep -qi \"opensuse\"; then\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} zypper install -y ${PACKAGES};\n }\n\n# Alpine 3.3\n############$$\nelif echo ${LINUX_TYPE} | grep -qi \"alpine\"; then\n test \"${PACKAGES}\" = \"\" || {\n ${SUDO} apk update\n ${SUDO} apk add ${PACKAGES};\n }\n\nelse\n >&2 echo \"Unrecognized Linux Type\"\n >&2 cat /etc/os-release\n exit 1\nfi\n\n####################\n### Install java ###\n####################\ncommand -v ${JAVA_HOME}/bin/java >/dev/null 2>&1 || {\n export JAVA_HOME=${CHE_DIR}/jdk1.8\n command -v ${JAVA_HOME}/bin/java >/dev/null 2>&1 || {\n JDK_URL=http://download.oracle.com/otn-pub/java/jdk/8u45-b14/jdk-8u45-linux-x64.tar.gz\n curl -s -j -k -L -H \"Cookie: oraclelicense=accept-securebackup-cookie\" \"${JDK_URL}\" | tar -C ${CHE_DIR} -xzf -\n mv ${CHE_DIR}/jdk1.8.0_45 ${CHE_DIR}/jdk1.8\n }\n}\n\n########################\n### Install ws-agent ###\n########################\n\nrm -rf ${CHE_DIR}/ws-agent\nmkdir -p ${CHE_DIR}/ws-agent\ncurl -s ${AGENT_BINARIES_URI} | tar xzf - -C ${CHE_DIR}/ws-agent\n\n###############################################\n### ws-agent run command will be added here ###\n### ~/che/ws-agent/bin/catalina.sh run ###\n###############################################"
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
#
|
||||
# Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
# 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:
|
||||
# Codenvy, S.A. - initial API and implementation
|
||||
#
|
||||
|
||||
unset SUDO
|
||||
unset PACKAGES
|
||||
test "$(id -u)" = 0 || SUDO="sudo"
|
||||
|
||||
LINUX_TYPE=$(cat /etc/os-release | grep ^ID= | tr '[:upper:]' '[:lower:]')
|
||||
LINUX_VERSION=$(cat /etc/os-release | grep ^VERSION=)
|
||||
|
||||
###############################
|
||||
### Install Needed packaged ###
|
||||
###############################
|
||||
|
||||
# Red Hat Enterprise Linux 7
|
||||
############################
|
||||
if echo ${LINUX_TYPE} | grep -qi "rhel"; then
|
||||
command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" openssh-server"; }
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} yum -y install ${PACKAGES};
|
||||
}
|
||||
${SUDO} sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
|
||||
|
||||
# Ubuntu 14.04 16.04 / Linux Mint 17
|
||||
####################################
|
||||
elif echo ${LINUX_TYPE} | grep -qi "ubuntu"; then
|
||||
command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" openssh-server"; }
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} apt-get update;
|
||||
${SUDO} apt-get -y install ${PACKAGES};
|
||||
}
|
||||
${SUDO} sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
|
||||
|
||||
# Debian 8
|
||||
##########
|
||||
elif echo ${LINUX_TYPE} | grep -qi "debian"; then
|
||||
command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" openssh-server"; }
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} apt-get update;
|
||||
${SUDO} apt-get -y install ${PACKAGES};
|
||||
}
|
||||
${SUDO} sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
|
||||
|
||||
# Fedora 23
|
||||
###########
|
||||
elif echo ${LINUX_TYPE} | grep -qi "fedora"; then
|
||||
PACKAGES=${PACKAGES}" procps-ng"
|
||||
command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" openssh-server"; }
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} dnf -y install ${PACKAGES};
|
||||
}
|
||||
${SUDO} sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
|
||||
|
||||
# CentOS 7.1 & Oracle Linux 7.1
|
||||
###############################
|
||||
elif echo ${LINUX_TYPE} | grep -qi "centos"; then
|
||||
command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" openssh-server"; }
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} yum -y install ${PACKAGES};
|
||||
}
|
||||
${SUDO} sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
|
||||
|
||||
# openSUSE 13.2
|
||||
###############
|
||||
elif echo ${LINUX_TYPE} | grep -qi "opensuse"; then
|
||||
command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" openSSH"; }
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} zypper install -y ${PACKAGES};
|
||||
}
|
||||
${SUDO} sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
|
||||
|
||||
# Alpine 3.3
|
||||
############$$
|
||||
elif echo ${LINUX_TYPE} | grep -qi "alpine"; then
|
||||
command -v sshd >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" openssh"; }
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} apk update;
|
||||
${SUDO} apk add openssh ${PACKAGES};
|
||||
}
|
||||
|
||||
else
|
||||
>&2 echo "Unrecognized Linux Type"
|
||||
>&2 cat /etc/os-release
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ps -fC sshd && exit
|
||||
|
||||
${SUDO} mkdir -p /var/run/sshd
|
||||
${SUDO} /usr/bin/ssh-keygen -A && ${SUDO} /usr/sbin/sshd -D
|
||||
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
#
|
||||
# Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
# 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:
|
||||
# Codenvy, S.A. - initial API and implementation
|
||||
#
|
||||
|
||||
unset PACKAGES
|
||||
unset SUDO
|
||||
command -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" tar"; }
|
||||
command -v curl >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" curl"; }
|
||||
test "$(id -u)" = 0 || SUDO="sudo"
|
||||
|
||||
CHE_DIR=$HOME/che
|
||||
AGENT_BINARIES_URI="file:///mnt/che/terminal/websocket-terminal-\\${PREFIX}.tar.gz"
|
||||
TARGET_AGENT_BINARIES_URI="file://"${CHE_DIR}"/websocket-terminal-\\${PREFIX}.tar.gz"
|
||||
LINUX_TYPE=$(cat /etc/os-release | grep ^ID= | tr '[:upper:]' '[:lower:]')
|
||||
LINUX_VERSION=$(cat /etc/os-release | grep ^VERSION=)
|
||||
MACHINE_TYPE=$(uname -m)
|
||||
|
||||
mkdir -p ${CHE_DIR}
|
||||
|
||||
########################
|
||||
### Install packages ###
|
||||
########################
|
||||
|
||||
# Red Hat Enterprise Linux 7
|
||||
############################
|
||||
if echo ${LINUX_TYPE} | grep -qi "rhel"; then
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} yum install ${PACKAGES};
|
||||
}
|
||||
|
||||
# Ubuntu 14.04 16.04 / Linux Mint 17
|
||||
####################################
|
||||
elif echo ${LINUX_TYPE} | grep -qi "ubuntu"; then
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} apt-get update;
|
||||
${SUDO} apt-get -y install ${PACKAGES};
|
||||
}
|
||||
|
||||
# Debian 8
|
||||
##########
|
||||
elif echo ${LINUX_TYPE} | grep -qi "debian"; then
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} apt-get update;
|
||||
${SUDO} apt-get -y install ${PACKAGES};
|
||||
}
|
||||
|
||||
# Fedora 23
|
||||
###########
|
||||
elif echo ${LINUX_TYPE} | grep -qi "fedora"; then
|
||||
PACKAGES=${PACKAGES}" procps-ng"
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} dnf -y install ${PACKAGES};
|
||||
}
|
||||
|
||||
# CentOS 7.1 & Oracle Linux 7.1
|
||||
###############################
|
||||
elif echo ${LINUX_TYPE} | grep -qi "centos"; then
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} yum -y install ${PACKAGES};
|
||||
}
|
||||
|
||||
# openSUSE 13.2
|
||||
###############
|
||||
elif echo ${LINUX_TYPE} | grep -qi "opensuse"; then
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} zypper install -y ${PACKAGES};
|
||||
}
|
||||
|
||||
# Alpine 3.3
|
||||
############$$
|
||||
elif echo ${LINUX_TYPE} | grep -qi "alpine"; then
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} apk update
|
||||
${SUDO} apk add ${PACKAGES};
|
||||
}
|
||||
|
||||
else
|
||||
>&2 echo "Unrecognized Linux Type"
|
||||
>&2 cat /etc/os-release
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ps -fC che-websocket-terminal && exit
|
||||
|
||||
########################
|
||||
### Install Terminal ###
|
||||
########################
|
||||
if echo ${MACHINE_TYPE} | grep -qi "x86_64"; then
|
||||
PREFIX=linux_amd64
|
||||
elif echo ${MACHINE_TYPE} | grep -qi "arm5"; then
|
||||
PREFIX=linux_arm7
|
||||
elif echo ${MACHINE_TYPE} | grep -qi "arm6"; then
|
||||
PREFIX=linux_arm7
|
||||
elif echo ${MACHINE_TYPE} | grep -qi "arm7"; then
|
||||
PREFIX=linux_arm7
|
||||
else
|
||||
>&2 echo "Unrecognized Machine Type"
|
||||
>&2 uname -a
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if curl -o /dev/null --silent --head --fail $(echo ${AGENT_BINARIES_URI} | sed -s 's/\\${PREFIX}/'${PREFIX}'/g'); then
|
||||
curl -o $(echo ${TARGET_AGENT_BINARIES_URI} | sed -s 's/\\${PREFIX}/'${PREFIX}'/g' | sed -s 's/file:\\/\\///g') -s $(echo ${AGENT_BINARIES_URI} | sed -s 's/\\${PREFIX}/'${PREFIX}'/g')
|
||||
elif curl -o /dev/null --silent --head --fail $(echo ${AGENT_BINARIES_URI} | sed -s 's/-\\${PREFIX}//g'); then
|
||||
curl -o $(echo ${TARGET_AGENT_BINARIES_URI} | sed -s 's/\\${PREFIX}/'${PREFIX}'/g' | sed -s 's/file:\\/\\///g') -s $(echo ${AGENT_BINARIES_URI} | sed -s 's/-\\${PREFIX}//g')
|
||||
fi
|
||||
|
||||
curl -s $(echo ${TARGET_AGENT_BINARIES_URI} | sed -s 's/\\${PREFIX}/'${PREFIX}'/g') | tar xzf - -C ${CHE_DIR}
|
||||
$HOME/che/terminal/che-websocket-terminal -addr :4411 -cmd /bin/bash -static $HOME/che/terminal/
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
#
|
||||
# Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
# 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:
|
||||
# Codenvy, S.A. - initial API and implementation
|
||||
#
|
||||
|
||||
unset PACKAGES
|
||||
unset SUDO
|
||||
command -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" tar"; }
|
||||
command -v curl >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" curl"; }
|
||||
test "$(id -u)" = 0 || SUDO="sudo"
|
||||
|
||||
AGENT_BINARIES_URI=file:///mnt/che/ws-agent.tar.gz
|
||||
CHE_DIR=$HOME/che
|
||||
LINUX_TYPE=$(cat /etc/os-release | grep ^ID= | tr '[:upper:]' '[:lower:]')
|
||||
LINUX_VERSION=$(cat /etc/os-release | grep ^VERSION=)
|
||||
MACHINE_TYPE=$(uname -m)
|
||||
|
||||
mkdir -p ${CHE_DIR}
|
||||
${SUDO} mkdir -p /projects
|
||||
${SUDO} sh -c "chown -R $(id -u -n) /projects"
|
||||
|
||||
########################
|
||||
### Install packages ###
|
||||
########################
|
||||
|
||||
# Red Hat Enterprise Linux 7
|
||||
############################
|
||||
if echo ${LINUX_TYPE} | grep -qi "rhel"; then
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} yum install ${PACKAGES};
|
||||
}
|
||||
|
||||
# Ubuntu 14.04 16.04 / Linux Mint 17
|
||||
####################################
|
||||
elif echo ${LINUX_TYPE} | grep -qi "ubuntu"; then
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} apt-get update;
|
||||
${SUDO} apt-get -y install ${PACKAGES};
|
||||
}
|
||||
|
||||
# Debian 8
|
||||
##########
|
||||
elif echo ${LINUX_TYPE} | grep -qi "debian"; then
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} apt-get update;
|
||||
${SUDO} apt-get -y install ${PACKAGES};
|
||||
}
|
||||
|
||||
# Fedora 23
|
||||
###########
|
||||
elif echo ${LINUX_TYPE} | grep -qi "fedora"; then
|
||||
PACKAGES=${PACKAGES}" procps-ng"
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} dnf -y install ${PACKAGES};
|
||||
}
|
||||
|
||||
# CentOS 7.1 & Oracle Linux 7.1
|
||||
###############################
|
||||
elif echo ${LINUX_TYPE} | grep -qi "centos"; then
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} yum -y install ${PACKAGES};
|
||||
}
|
||||
|
||||
# openSUSE 13.2
|
||||
###############
|
||||
elif echo ${LINUX_TYPE} | grep -qi "opensuse"; then
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} zypper install -y ${PACKAGES};
|
||||
}
|
||||
|
||||
# Alpine 3.3
|
||||
############$$
|
||||
elif echo ${LINUX_TYPE} | grep -qi "alpine"; then
|
||||
test "${PACKAGES}" = "" || {
|
||||
${SUDO} apk update
|
||||
${SUDO} apk add ${PACKAGES};
|
||||
}
|
||||
|
||||
else
|
||||
>&2 echo "Unrecognized Linux Type"
|
||||
>&2 cat /etc/os-release
|
||||
exit 1
|
||||
fi
|
||||
|
||||
####################
|
||||
### Install java ###
|
||||
####################
|
||||
command -v ${JAVA_HOME}/bin/java >/dev/null 2>&1 || {
|
||||
export JAVA_HOME=${CHE_DIR}/jdk1.8
|
||||
command -v ${JAVA_HOME}/bin/java >/dev/null 2>&1 || {
|
||||
JDK_URL=http://download.oracle.com/otn-pub/java/jdk/8u45-b14/jdk-8u45-linux-x64.tar.gz
|
||||
curl -s -j -k -L -H "Cookie: oraclelicense=accept-securebackup-cookie" "${JDK_URL}" | tar -C ${CHE_DIR} -xzf -
|
||||
mv ${CHE_DIR}/jdk1.8.0_45 ${CHE_DIR}/jdk1.8
|
||||
}
|
||||
}
|
||||
|
||||
########################
|
||||
### Install ws-agent ###
|
||||
########################
|
||||
|
||||
rm -rf ${CHE_DIR}/ws-agent
|
||||
mkdir -p ${CHE_DIR}/ws-agent
|
||||
curl -s ${AGENT_BINARIES_URI} | tar xzf - -C ${CHE_DIR}/ws-agent
|
||||
|
||||
###############################################
|
||||
### ws-agent run command will be added here ###
|
||||
### ~/che/ws-agent/bin/catalina.sh run ###
|
||||
###############################################
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
# 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:
|
||||
# Codenvy, S.A. - initial API and implementation
|
||||
#
|
||||
|
||||
updateAgentScript() {
|
||||
local DIR=$1
|
||||
local AGENT=$2
|
||||
local SCRIPT=$(cat ${AGENT}.script.sh | sed -r 's/"/\\"/g' | sed -r ':a;N;$!ba;s/\n/\\n/g')
|
||||
|
||||
touch ${AGENT}.json.tmp
|
||||
cat ${DIR}/${AGENT}.json | while read line
|
||||
do
|
||||
if echo ${line} | grep -qi "script"; then
|
||||
echo \"script\" : \"${SCRIPT}\" >> ${AGENT}.json.tmp
|
||||
else
|
||||
echo ${line} >> ${AGENT}.json.tmp
|
||||
fi
|
||||
done
|
||||
|
||||
mv ${AGENT}.json.tmp ${DIR}/${AGENT}.json
|
||||
}
|
||||
|
||||
updateAgentScript ".." "org.eclipse.che.ssh"
|
||||
updateAgentScript ".." "org.eclipse.che.terminal"
|
||||
updateAgentScript ".." "org.eclipse.che.ws-agent"
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.impl;
|
||||
|
||||
import org.eclipse.che.api.agent.server.model.impl.AgentKeyImpl;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertNull;
|
||||
import static org.testng.AssertJUnit.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
public class AgentKeyImplTest {
|
||||
|
||||
@Test
|
||||
public void testAgentKeyWithNameAndVersion() {
|
||||
AgentKeyImpl agentKey = AgentKeyImpl.parse("name:1");
|
||||
|
||||
assertEquals(agentKey.getName(), "name");
|
||||
assertEquals(agentKey.getVersion(), "1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseAgentKeyWithName() {
|
||||
AgentKeyImpl agentKey = AgentKeyImpl.parse("name");
|
||||
|
||||
assertEquals(agentKey.getName(), "name");
|
||||
assertNull(agentKey.getVersion());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testParseAgentKeyFails() {
|
||||
AgentKeyImpl.parse("name:1:2");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.impl;
|
||||
|
||||
import org.eclipse.che.api.agent.server.AgentRegistryUrlProvider;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentException;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentNotFoundException;
|
||||
import org.eclipse.che.api.agent.server.model.impl.AgentKeyImpl;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.agent.shared.model.AgentKey;
|
||||
import org.eclipse.che.api.core.rest.DefaultHttpJsonRequestFactory;
|
||||
import org.eclipse.che.dto.server.JsonArrayImpl;
|
||||
import org.everrest.assured.EverrestJetty;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.ITestContext;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Collection;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.nio.file.Files.copy;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Anatoliy Bazko
|
||||
*/
|
||||
@Listeners(value = {EverrestJetty.class, MockitoTestNGListener.class})
|
||||
public class AgentRegistryImplTest {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private RegistryService service;
|
||||
@Mock
|
||||
private AgentRegistryUrlProvider urlProvider;
|
||||
private AgentRegistryImpl agentRegistry;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp(ITestContext context) throws Exception {
|
||||
agentRegistry = new AgentRegistryImpl(urlProvider, new DefaultHttpJsonRequestFactory());
|
||||
|
||||
final Object port = context.getAttribute(EverrestJetty.JETTY_PORT);
|
||||
when(urlProvider.getAgentUrl(any(AgentKey.class))).thenAnswer(new Answer<URL>() {
|
||||
@Override
|
||||
public URL answer(InvocationOnMock invocation) throws Throwable {
|
||||
AgentKey agentKey = (AgentKey)invocation.getArguments()[0];
|
||||
if (agentKey.getVersion() == null) {
|
||||
return new URL("http://localhost:" + port + "/rest/registry/agent/" + agentKey.getName());
|
||||
} else {
|
||||
return new URL("http://localhost:" + port + "/rest/registry/agent/" + agentKey.getName() + "/" + agentKey.getVersion());
|
||||
}
|
||||
}
|
||||
});
|
||||
when(urlProvider.getAgentVersionsUrl(anyString())).thenAnswer(new Answer<URL>() {
|
||||
@Override
|
||||
public URL answer(InvocationOnMock invocation) throws Throwable {
|
||||
String name = (String)invocation.getArguments()[0];
|
||||
return new URL("http://localhost:" + port + "/rest/registry/updates/" + name);
|
||||
}
|
||||
});
|
||||
|
||||
service = new RegistryService();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateSpecificVersionAgent() throws Exception {
|
||||
Agent agent = agentRegistry.getAgent(new AgentKeyImpl("org.eclipse.che.ws-agent", "1.0"));
|
||||
|
||||
assertEquals(agent.getName(), "org.eclipse.che.ws-agent");
|
||||
assertEquals(agent.getVersion(), "1.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateLatestVersionAgent() throws Exception {
|
||||
Agent agent = agentRegistry.getAgent(new AgentKeyImpl("org.eclipse.che.ws-agent"));
|
||||
|
||||
assertEquals(agent.getName(), "org.eclipse.che.ws-agent");
|
||||
assertEquals(agent.getVersion(), "2.0");
|
||||
}
|
||||
|
||||
|
||||
@Test(expectedExceptions = AgentException.class)
|
||||
public void testGetConfigShouldThrowExceptionIfAgentNotFound() throws Exception {
|
||||
agentRegistry.getAgent(new AgentKeyImpl("terminal", "1.0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAgentsVersion() throws Exception {
|
||||
Collection<String> versions = agentRegistry.getVersions("org.eclipse.che.ws-agent");
|
||||
|
||||
assertEquals(versions.size(), 1);
|
||||
assertTrue(versions.contains("1.0.0"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AgentNotFoundException.class)
|
||||
public void testGetAgentsVersionShouldFailsIfAgentUnknown() throws Exception {
|
||||
agentRegistry.getVersions("terminal");
|
||||
}
|
||||
|
||||
@Path("registry")
|
||||
public class RegistryService {
|
||||
|
||||
@GET
|
||||
@Path("agent/{artifact}/{version}")
|
||||
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||
public Response getAgent(@PathParam("artifact") String artifact, @PathParam("version") String version) throws IOException {
|
||||
return doGetAgent(artifact, version);
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Path("agent/{artifact}")
|
||||
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||
public Response getLatestAgent(@PathParam("artifact") String artifact) throws IOException {
|
||||
return doGetAgent(artifact, "2.0");
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/updates/{artifact}")
|
||||
public Response getUpdates(@PathParam("artifact") final String artifact) {
|
||||
if (!artifact.endsWith("org.eclipse.che.ws-agent")) {
|
||||
return Response.status(Response.Status.NOT_FOUND).entity("{ \"message\" : \"not found\" }").build();
|
||||
}
|
||||
return Response.status(Response.Status.OK).entity(new JsonArrayImpl<>(singletonList("1.0.0"))).build();
|
||||
}
|
||||
|
||||
private Response doGetAgent(String artifact, String version) throws IOException {
|
||||
if (!artifact.endsWith("org.eclipse.che.ws-agent")) {
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
|
||||
String content = format("{ \"name\" : \"%s\", \"version\" : \"%s\"}", artifact, version);
|
||||
java.nio.file.Path file = Paths.get(System.getProperty("java.io.tmpdir"), "config.tmp");
|
||||
file.toFile().deleteOnExit();
|
||||
|
||||
copy(new ByteArrayInputStream(content.getBytes()), file, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
return Response.ok(file.toFile(), MediaType.APPLICATION_OCTET_STREAM)
|
||||
.header("Content-Length", String.valueOf(Files.size(file)))
|
||||
.header("Content-Disposition", "attachment; filename=" + file.getFileName().toString())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.impl;
|
||||
|
||||
import org.eclipse.che.api.agent.server.AgentRegistry;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentException;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentNotFoundException;
|
||||
import org.eclipse.che.api.agent.server.model.impl.AgentKeyImpl;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.agent.shared.model.AgentKey;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.AssertJUnit.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
@Listeners(value = {MockitoTestNGListener.class})
|
||||
public class AgentSorterTest {
|
||||
|
||||
@Mock
|
||||
private AgentRegistry agentRegistry;
|
||||
@Mock
|
||||
private Agent agent1;
|
||||
@Mock
|
||||
private Agent agent2;
|
||||
@Mock
|
||||
private Agent agent3;
|
||||
|
||||
@InjectMocks
|
||||
private AgentSorter agentSorter;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() throws Exception {
|
||||
when(agentRegistry.getAgent(eq(AgentKeyImpl.parse("fqn1")))).thenReturn(agent1);
|
||||
when(agentRegistry.getAgent(eq(AgentKeyImpl.parse("fqn2")))).thenReturn(agent2);
|
||||
when(agentRegistry.getAgent(eq(AgentKeyImpl.parse("fqn3")))).thenReturn(agent3);
|
||||
when(agentRegistry.getAgent(eq(AgentKeyImpl.parse("fqn4")))).thenThrow(new AgentNotFoundException("Agent not found"));
|
||||
|
||||
when(agent1.getDependencies()).thenReturn(singletonList("fqn3"));
|
||||
when(agent1.getName()).thenReturn("fqn1");
|
||||
|
||||
when(agent2.getDependencies()).thenReturn(singletonList("fqn3"));
|
||||
when(agent2.getName()).thenReturn("fqn2");
|
||||
|
||||
when(agent3.getName()).thenReturn("fqn3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotCreateNewAgentsIfDependenciesExist() throws Exception {
|
||||
List<AgentKey> sorted = agentSorter.sort(Collections.singletonList("fqn1"));
|
||||
|
||||
assertEquals(sorted.size(), 1);
|
||||
assertEquals(sorted.get(0).getName(), "fqn1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sortAgentsRespectingDependencies() throws Exception {
|
||||
List<AgentKey> sorted = agentSorter.sort(Arrays.asList("fqn1", "fqn2", "fqn3"));
|
||||
|
||||
assertEquals(sorted.size(), 3);
|
||||
assertEquals(sorted.get(0).getName(), "fqn3");
|
||||
assertEquals(sorted.get(1).getName(), "fqn1");
|
||||
assertEquals(sorted.get(2).getName(), "fqn2");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AgentException.class)
|
||||
public void sortingShouldFailIfCircularDependenciesFound() throws Exception {
|
||||
when(agent1.getDependencies()).thenReturn(singletonList("fqn2"));
|
||||
when(agent2.getDependencies()).thenReturn(singletonList("fqn1"));
|
||||
|
||||
agentSorter.sort(Arrays.asList("fqn1", "fqn2"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AgentNotFoundException.class)
|
||||
public void sortingShouldFailIfAgentNotFound() throws Exception {
|
||||
agentSorter.sort(singletonList("fqn4"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.impl;
|
||||
|
||||
import org.everrest.assured.EverrestJetty;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.AssertJUnit.assertFalse;
|
||||
|
||||
/**
|
||||
* @author Anatoliy Bazko
|
||||
*/
|
||||
@Listeners(value = {EverrestJetty.class, MockitoTestNGListener.class})
|
||||
public class LocalAgentRegistryImplTest {
|
||||
|
||||
@InjectMocks
|
||||
private LocalAgentRegistryImpl agentRegistry;
|
||||
|
||||
@Test
|
||||
public void testInitializeAgents() throws Exception {
|
||||
List<String> agents = agentRegistry.getAgents();
|
||||
assertFalse(agents.isEmpty());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.launcher;
|
||||
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.core.model.machine.Command;
|
||||
import org.eclipse.che.api.core.util.LineConsumer;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.eclipse.che.api.machine.server.spi.InstanceProcess;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.isNull;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
@Listeners(value = {MockitoTestNGListener.class})
|
||||
public class DefaultAgentLauncherTest {
|
||||
|
||||
@Mock
|
||||
private Instance machine;
|
||||
@Mock
|
||||
private Agent agent;
|
||||
@Mock
|
||||
private LineConsumer lineConsumer;
|
||||
@Mock
|
||||
private InstanceProcess instanceProcess;
|
||||
|
||||
private AgentLauncher agentLauncher;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() throws Exception {
|
||||
agentLauncher = new DefaultAgentLauncher(120000, 10);
|
||||
|
||||
when(machine.createProcess(any(), any())).thenReturn(instanceProcess);
|
||||
when(machine.getLogger()).thenReturn(lineConsumer);
|
||||
when(agent.getScript()).thenReturn("script1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldLaunchAgent() throws Exception {
|
||||
ArgumentCaptor<Command> commandCaptor = ArgumentCaptor.forClass(Command.class);
|
||||
|
||||
agentLauncher.launch(machine, agent);
|
||||
|
||||
verify(machine).createProcess(commandCaptor.capture(), (String)isNull());
|
||||
|
||||
Command command = commandCaptor.getValue();
|
||||
assertEquals(command.getCommandLine(), "script1");
|
||||
|
||||
verify(instanceProcess).start(any());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
# 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:
|
||||
# Codenvy, S.A. - initial API and implementation
|
||||
#
|
||||
|
||||
CHE_PATH=/home/tolusha/java/env-projects/che/assembly/assembly-main/target/eclipse-che-4.8.0-SNAPSHOT/eclipse-che-4.8.0-SNAPSHOT/bin
|
||||
HOST_URL=localhost:8080
|
||||
TEST_LOG="agents-test.log"
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
# 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:
|
||||
# Codenvy, S.A. - initial API and implementation
|
||||
#
|
||||
|
||||
. ./config.sh
|
||||
|
||||
trap cleanUp EXIT
|
||||
|
||||
cleanUp() {
|
||||
${CHE_PATH}/che.sh stop
|
||||
}
|
||||
|
||||
printAndLog() {
|
||||
echo $@
|
||||
log $@
|
||||
}
|
||||
|
||||
logStartCommand() {
|
||||
log
|
||||
log "=== [ "`date`" ] COMMAND STARTED: "$@
|
||||
}
|
||||
|
||||
logEndCommand() {
|
||||
log "=================================== COMMAND COMPLETED: "$@
|
||||
log
|
||||
}
|
||||
|
||||
log() {
|
||||
echo "TEST: "$@ >> ${TEST_LOG}
|
||||
}
|
||||
|
||||
fetchJsonParameter() {
|
||||
OUTPUT=`echo ${OUTPUT} | sed 's/.*"'$1'"\s*:\s*"\([^"]*\)*".*/\1/'`
|
||||
}
|
||||
|
||||
# --method={POST|GET|...}
|
||||
# --content-type=...
|
||||
# --cookie=...
|
||||
# --body=...
|
||||
# --url=...
|
||||
# --output-http-code
|
||||
# --verbose
|
||||
doHttpRequest() {
|
||||
for var in "$@"; do
|
||||
if [[ "$var" =~ --content-type=.+ ]]; then
|
||||
CONTENT_TYPE_OPTION=`echo "-H \"Content-Type: $var\"" | sed -e "s/--content-type=//g"`
|
||||
|
||||
elif [[ "$var" =~ --body=.+ ]]; then
|
||||
local BODY_OPTION=`echo "-d '$var'" | sed -e "s/--body=//g"`
|
||||
|
||||
elif [[ "$var" =~ --url=.+ ]]; then
|
||||
local URL=`echo "'$var'" | sed -e "s/--url=//g"`
|
||||
|
||||
elif [[ "$var" =~ --method=.+ ]]; then
|
||||
local METHOD_OPTION=`echo "-X $var" | sed -e "s/--method=//g"`
|
||||
|
||||
elif [[ "$var" == "--output-http-code" ]]; then
|
||||
local OUTPUT_HTTP_CODE_OPTION="-o /dev/null -w \"%{http_code}\""
|
||||
|
||||
elif [[ "$var" == "--verbose" ]]; then
|
||||
local VERBOSE_OPTION="-v"
|
||||
|
||||
elif [[ "$var" =~ --cookie=.+ ]]; then
|
||||
local COOKIE_OPTION=$(echo "-H \"Cookie: session-access-key=$var\"" | sed -e "s/--cookie=//g")
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
local COMMAND="curl -s $VERBOSE_OPTION $OUTPUT_HTTP_CODE_OPTION $CONTENT_TYPE_OPTION $COOKIE_OPTION $BODY_OPTION $METHOD_OPTION $URL"
|
||||
|
||||
logStartCommand $COMMAND
|
||||
|
||||
OUTPUT=$(eval $COMMAND)
|
||||
EXIT_CODE=$?
|
||||
log ${OUTPUT}
|
||||
|
||||
logEndCommand "curl"
|
||||
}
|
||||
|
||||
doPost() {
|
||||
doHttpRequest --method=POST \
|
||||
--content-type=$1 \
|
||||
--body="$2" \
|
||||
--url=$3 \
|
||||
--cookie=$4
|
||||
}
|
||||
|
||||
doGet() {
|
||||
doHttpRequest --method=GET \
|
||||
--url=$1
|
||||
}
|
||||
|
||||
doDelete() {
|
||||
doHttpRequest --method=DELETE \
|
||||
--url=$1
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
# 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:
|
||||
# Codenvy, S.A. - initial API and implementation
|
||||
#
|
||||
|
||||
. ./lib.sh
|
||||
|
||||
|
||||
${CHE_PATH}/che.sh --debug start
|
||||
sleep 20s
|
||||
|
||||
DOCKER_CONTENT=("FROM fedora:23\nCMD tail -f /dev/null"
|
||||
"FROM ubuntu:16.04\nCMD tail -f /dev/null"
|
||||
"FROM ubuntu:14.04\nCMD tail -f /dev/null"
|
||||
"FROM centos:7\nCMD tail -f /dev/null"
|
||||
"FROM opensuse:13.2\nCMD tail -f /dev/null"
|
||||
"FROM debian:8\nCMD tail -f /dev/null");
|
||||
|
||||
waitStatus() {
|
||||
WORKSPACE_ID=$1
|
||||
STATUS=$2
|
||||
ATTEMPTS=200
|
||||
|
||||
for ((j = 0; j < ${ATTEMPTS}; j++))
|
||||
do
|
||||
doGet "http://"${HOST_URL}"/api/workspace/"${WORKSPACE_ID}
|
||||
if echo ${OUTPUT} | grep -qi "\"id\":\"${WORKSPACE_ID}\",\"status\":\"${STATUS}\""; then
|
||||
echo ${STATUS}
|
||||
break
|
||||
fi
|
||||
sleep 5s
|
||||
done
|
||||
}
|
||||
|
||||
validateRunningProcess() {
|
||||
WORKSPACE_ID=$1
|
||||
PROCESS=$2
|
||||
|
||||
CONTAINER_ID=$(docker ps -aqf "name="${WORKSPACE_ID})
|
||||
printAndLog "Container ID "${CONTAINER_ID}" validate "${PROCESS}
|
||||
|
||||
PID=$(docker exec -ti ${CONTAINER_ID} ps -fC ${PROCESS})
|
||||
if [ "${PID}" = "" ]; then
|
||||
printAndLog "RESULT: FAILED. Process "${PROCESS}" not found"
|
||||
fi
|
||||
}
|
||||
|
||||
deleteWorkspace() {
|
||||
WORKSPACE_ID=$1
|
||||
|
||||
doDelete "http://"${HOST_URL}"/api/workspace/"${WORKSPACE_ID}"/runtime"
|
||||
STATUS=$(waitStatus ${WORKSPACE_ID} "STOPPED")
|
||||
if echo ${STATUS} | grep -qi "STOPPED"; then
|
||||
doDelete "http://"${HOST_URL}"/api/workspace/"${WORKSPACE_ID}
|
||||
sleep 1m
|
||||
else
|
||||
printAndLog "ERROR. Workspace "${WORKSPACE_ID}" can't be stopped"
|
||||
fi
|
||||
}
|
||||
|
||||
for ((i = 0; i < ${#DOCKER_CONTENT[@]}; i++))
|
||||
do
|
||||
CONTENT="${DOCKER_CONTENT[$i]}"
|
||||
printAndLog
|
||||
printAndLog "####################################################################"
|
||||
printAndLog "Creating workspace with recipe: \""${CONTENT}"\""
|
||||
printAndLog "####################################################################"
|
||||
|
||||
NAME=$(date +%s | sha256sum | base64 | head -c 5)
|
||||
doPost "application/json" "{\"name\":\"${NAME}\",\"projects\":[],\"defaultEnv\":\"${NAME}\",\"description\":null,\"environments\":[{\"name\":\"${NAME}\",\"recipe\":null,\"machineConfigs\":[{\"name\":\"ws-machine\",\"limits\":{\"ram\":1000},\"type\":\"docker\",\"source\":{\"type\":\"dockerfile\",\"content\":\"${CONTENT}\"},\"dev\":true}]}]}" "http://"${HOST_URL}"/api/workspace?account="
|
||||
fetchJsonParameter "id"
|
||||
WORKSPACE_ID=${OUTPUT}
|
||||
|
||||
printAndLog "Starting workspace: "${WORKSPACE_ID}
|
||||
doPost "application/json" "{}" "http://"${HOST_URL}"/api/workspace/"${WORKSPACE_ID}"/runtime?environment="${NAME}
|
||||
|
||||
STATUS=$(waitStatus ${WORKSPACE_ID} "RUNNING")
|
||||
if echo ${STATUS} | grep -qi "RUNNING"; then
|
||||
validateRunningProcess ${WORKSPACE_ID} "che-websocket-terminal"
|
||||
validateRunningProcess ${WORKSPACE_ID} "java"
|
||||
validateRunningProcess ${WORKSPACE_ID} "sshd"
|
||||
else
|
||||
printAndLog "RESULT: FAILED. Workspace not started."
|
||||
fi
|
||||
|
||||
deleteWorkspace ${WORKSPACE_ID}
|
||||
done
|
||||
|
|
@ -181,7 +181,7 @@ public class FactoryBuilderTest {
|
|||
.withContentType("application/x-yaml")
|
||||
.withContent("some content"))
|
||||
.withMachines(singletonMap("devmachine",
|
||||
newDto(ExtendedMachineDto.class).withAgents(singletonList("ws-agent"))
|
||||
newDto(ExtendedMachineDto.class).withAgents(singletonList("org.eclipse.che.ws-agent"))
|
||||
.withAttributes(singletonMap("memoryLimitBytes", "" + 512L * 1024L * 1024L))));
|
||||
|
||||
WorkspaceConfigDto workspaceConfig = dto.createDto(WorkspaceConfigDto.class)
|
||||
|
|
|
|||
|
|
@ -73,6 +73,18 @@
|
|||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-agent</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-agent-shared</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-agent-shared</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-core</artifactId>
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.terminal;
|
||||
|
||||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
|
||||
/**
|
||||
* Machine implementation specific launcher of websocket terminal.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
public interface MachineImplSpecificTerminalLauncher {
|
||||
/**
|
||||
* Type of machine implementation this terminal fits.
|
||||
*/
|
||||
String getMachineType();
|
||||
|
||||
/**
|
||||
* Starts websocket terminal inside of machine.
|
||||
*/
|
||||
void launchTerminal(Instance machine) throws MachineException;
|
||||
}
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.terminal;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.api.core.notification.EventSubscriber;
|
||||
import org.eclipse.che.api.environment.server.CheEnvironmentEngine;
|
||||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.eclipse.che.api.machine.shared.dto.event.MachineStatusEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
|
||||
/**
|
||||
* Starts websocket terminal in the machine after its start.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
@Singleton
|
||||
public class MachineTerminalLauncher {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MachineTerminalLauncher.class);
|
||||
|
||||
private final EventService eventService;
|
||||
// TODO replace with WorkspaceManager
|
||||
private final CheEnvironmentEngine cheEnvironmentEngine;
|
||||
private final Map<String, MachineImplSpecificTerminalLauncher> terminalLaunchers;
|
||||
private final ExecutorService executor;
|
||||
|
||||
@Inject
|
||||
public MachineTerminalLauncher(EventService eventService,
|
||||
Set<MachineImplSpecificTerminalLauncher> machineImplLaunchers,
|
||||
CheEnvironmentEngine cheEnvironmentEngine) {
|
||||
this.eventService = eventService;
|
||||
this.terminalLaunchers = machineImplLaunchers.stream()
|
||||
.collect(toMap(MachineImplSpecificTerminalLauncher::getMachineType,
|
||||
Function.identity()));
|
||||
this.cheEnvironmentEngine = cheEnvironmentEngine;
|
||||
this.executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("MachineTerminalLauncher-%d")
|
||||
.setDaemon(true)
|
||||
.build());
|
||||
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
eventService.subscribe(new EventSubscriber<MachineStatusEvent>() {
|
||||
@Override
|
||||
public void onEvent(MachineStatusEvent event) {
|
||||
if (event.getEventType() == MachineStatusEvent.EventType.RUNNING) {
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
final Instance machine = cheEnvironmentEngine.getMachine(event.getWorkspaceId(),
|
||||
event.getMachineId());
|
||||
|
||||
MachineImplSpecificTerminalLauncher terminalLauncher =
|
||||
terminalLaunchers.get(machine.getConfig().getType());
|
||||
if (terminalLauncher == null) {
|
||||
LOG.warn("Terminal launcher implementation was not found for machine {} with type {}.",
|
||||
machine.getId(),
|
||||
machine.getConfig().getType());
|
||||
} else {
|
||||
terminalLauncher.launchTerminal(machine);
|
||||
}
|
||||
} catch (MachineException | NotFoundException e) {
|
||||
LOG.error(e.getLocalizedMessage(), e);
|
||||
// TODO send event that terminal is unavailable
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.environment.server;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.agent.server.AgentRegistry;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentException;
|
||||
import org.eclipse.che.api.agent.server.impl.AgentSorter;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.agent.shared.model.AgentKey;
|
||||
import org.eclipse.che.api.core.model.workspace.compose.ComposeService;
|
||||
import org.eclipse.che.api.environment.server.compose.model.ComposeServiceImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.lang.String.format;
|
||||
import static org.eclipse.che.api.environment.server.AgentConfigApplier.PROPERTIES.ENVIRONMENT;
|
||||
import static org.eclipse.che.api.environment.server.AgentConfigApplier.PROPERTIES.PORTS;
|
||||
|
||||
/**
|
||||
* Applies docker specific properties of the agents over {@link ComposeService}.
|
||||
* Dependencies between agents are respected.
|
||||
* Docker instance must't be started, otherwise changing configuration has no effect.
|
||||
*
|
||||
* The list of supported properties are:
|
||||
* <li>ports</li>
|
||||
* <li>environment</li>
|
||||
*
|
||||
* The {@code ports} property contains comma separated ports to expose respecting
|
||||
* the following format: "label:port/protocol" or "port/protocol.
|
||||
*
|
||||
* The {@code environment} property contains command separated environment variables to set
|
||||
* respecting the following format: "name=value".
|
||||
*
|
||||
* @see Agent#getProperties()
|
||||
* @see ComposeService#getEnvironment()
|
||||
* @see ComposeService#getPorts()
|
||||
*
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
@Singleton
|
||||
public class AgentConfigApplier {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AgentConfigApplier.class);
|
||||
|
||||
private final AgentSorter sorter;
|
||||
private final AgentRegistry agentRegistry;
|
||||
|
||||
@Inject
|
||||
public AgentConfigApplier(AgentSorter sorter, AgentRegistry agentRegistry) {
|
||||
this.sorter = sorter;
|
||||
this.agentRegistry = agentRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies docker specific properties.
|
||||
*
|
||||
* @param composeService
|
||||
* the compose service
|
||||
* @param agentKeys
|
||||
* the list of injected agents into machine
|
||||
*
|
||||
* @throws AgentException
|
||||
*/
|
||||
public void modify(ComposeServiceImpl composeService, List<String> agentKeys) throws AgentException {
|
||||
for (AgentKey agentKey : sorter.sort(agentKeys)) {
|
||||
Agent agent = agentRegistry.getAgent(agentKey);
|
||||
addEnv(composeService, agent.getProperties());
|
||||
addExposedPorts(composeService, agent.getProperties());
|
||||
}
|
||||
}
|
||||
|
||||
private void addEnv(ComposeServiceImpl composeService, Map<String, String> properties) {
|
||||
String environment = properties.get(ENVIRONMENT.toString());
|
||||
if (isNullOrEmpty(environment)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, String> newEnv = new HashMap<>();
|
||||
if (composeService.getEnvironment() != null) {
|
||||
newEnv.putAll(composeService.getEnvironment());
|
||||
}
|
||||
|
||||
for (String env : environment.split(",")) {
|
||||
String[] items = env.split("=");
|
||||
if (items.length != 2) {
|
||||
LOG.warn(format("Illegal environment variable '%s' format", env));
|
||||
continue;
|
||||
}
|
||||
String var = items[0];
|
||||
String name = items[1];
|
||||
|
||||
newEnv.put(var, name);
|
||||
}
|
||||
|
||||
composeService.setEnvironment(newEnv);
|
||||
}
|
||||
|
||||
private void addExposedPorts(ComposeServiceImpl composeService, Map<String, String> properties) {
|
||||
String ports = properties.get(PORTS.toString());
|
||||
if (isNullOrEmpty(ports)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String port : ports.split(",")) {
|
||||
String[] items = port.split(":"); // ref:port
|
||||
if (items.length == 1) {
|
||||
composeService.getExpose().add(items[0]);
|
||||
} else {
|
||||
composeService.getExpose().add(items[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum PROPERTIES {
|
||||
PORTS("ports"),
|
||||
ENVIRONMENT("environment");
|
||||
|
||||
private final String value;
|
||||
|
||||
PROPERTIES(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -13,6 +13,7 @@ package org.eclipse.che.api.environment.server;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import org.eclipse.che.api.agent.server.exception.AgentException;
|
||||
import org.eclipse.che.api.core.ApiException;
|
||||
import org.eclipse.che.api.core.ConflictException;
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
|
|
@ -100,6 +101,7 @@ public class CheEnvironmentEngine {
|
|||
private final EnvironmentParser environmentParser;
|
||||
private final ComposeServicesStartStrategy startStrategy;
|
||||
private final ComposeMachineInstanceProvider composeProvider;
|
||||
private final AgentConfigApplier agentConfigApplier;
|
||||
|
||||
private volatile boolean isPreDestroyInvoked;
|
||||
|
||||
|
|
@ -111,12 +113,14 @@ public class CheEnvironmentEngine {
|
|||
EventService eventService,
|
||||
EnvironmentParser environmentParser,
|
||||
ComposeServicesStartStrategy startStrategy,
|
||||
ComposeMachineInstanceProvider composeProvider) {
|
||||
ComposeMachineInstanceProvider composeProvider,
|
||||
AgentConfigApplier agentConfigApplier) {
|
||||
this.snapshotDao = snapshotDao;
|
||||
this.eventService = eventService;
|
||||
this.environmentParser = environmentParser;
|
||||
this.startStrategy = startStrategy;
|
||||
this.composeProvider = composeProvider;
|
||||
this.agentConfigApplier = agentConfigApplier;
|
||||
this.environments = new ConcurrentHashMap<>();
|
||||
this.machineInstanceProviders = machineInstanceProviders;
|
||||
this.machineLogsDir = new File(machineLogsDir);
|
||||
|
|
@ -487,6 +491,7 @@ public class CheEnvironmentEngine {
|
|||
ConflictException {
|
||||
|
||||
ComposeEnvironmentImpl composeEnvironment = environmentParser.parse(env);
|
||||
applyAgents(env, composeEnvironment);
|
||||
|
||||
normalizeEnvironment(composeEnvironment);
|
||||
|
||||
|
|
@ -506,6 +511,21 @@ public class CheEnvironmentEngine {
|
|||
}
|
||||
}
|
||||
|
||||
private void applyAgents(Environment env, ComposeEnvironmentImpl composeEnvironment) throws ServerException {
|
||||
for (Map.Entry<String, ComposeServiceImpl> entry : composeEnvironment.getServices().entrySet()) {
|
||||
String machineName = entry.getKey();
|
||||
ComposeServiceImpl composeService = entry.getValue();
|
||||
|
||||
List<String> agents = env.getMachines().get(machineName).getAgents();
|
||||
|
||||
try {
|
||||
agentConfigApplier.modify(composeService, agents);
|
||||
} catch (AgentException e) {
|
||||
throw new ServerException("Can't apply agent config", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void normalizeEnvironment(ComposeEnvironmentImpl composeEnvironment) {
|
||||
for (Map.Entry<String, ComposeServiceImpl> serviceEntry : composeEnvironment.getServices()
|
||||
.entrySet()) {
|
||||
|
|
@ -521,10 +541,12 @@ public class CheEnvironmentEngine {
|
|||
.stream()
|
||||
.filter(entry -> entry.getValue()
|
||||
.getAgents()
|
||||
.contains("ws-agent"))
|
||||
.stream()
|
||||
.filter(agent -> agent.contains("org.eclipse.che.ws-agent"))
|
||||
.findAny()
|
||||
.isPresent())
|
||||
.findAny()
|
||||
.orElseThrow(
|
||||
() -> new ServerException("Agent 'ws-agent' is not found in any of environment machines"))
|
||||
.orElseThrow(() -> new ServerException("Agent 'org.eclipse.che.ws-agent' is not found in any of environment machines"))
|
||||
.getKey();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ public class CheEnvironmentValidator {
|
|||
envName);
|
||||
|
||||
checkArgument(env.getMachines() != null && !env.getMachines().isEmpty(),
|
||||
"Environment '%s' doesn't contain machine with 'ws-agent' agent",
|
||||
"Environment '%s' doesn't contain machine with 'org.eclipse.che.ws-agent' agent",
|
||||
envName);
|
||||
|
||||
List<String> missingServices = env.getMachines()
|
||||
|
|
@ -138,12 +138,12 @@ public class CheEnvironmentValidator {
|
|||
.stream()
|
||||
.filter(entry -> entry.getValue()
|
||||
.getAgents()
|
||||
.contains("ws-agent"))
|
||||
.contains("org.eclipse.che.ws-agent"))
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(toList());
|
||||
|
||||
checkArgument(devMachines.size() == 1,
|
||||
"Environment '%s' should contain exactly 1 machine with ws-agent, but contains '%s'. " +
|
||||
"Environment '%s' should contain exactly 1 machine with org.eclipse.che.ws-agent, but contains '%s'. " +
|
||||
"All machines with this agent: %s",
|
||||
envName, devMachines.size(), Joiner.on(", ").join(devMachines));
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import static java.lang.String.format;
|
|||
* "type": "dockerfile"
|
||||
* },
|
||||
* "type": "docker", <- will be defined by environment recipe type
|
||||
* "dev": true, <- if agents contain 'ws-agent'
|
||||
* "dev": true, <- if agents contain 'org.eclipse.che.ws-agent'
|
||||
* "envVariables" : {
|
||||
* "env1" : "value1",
|
||||
* "env2" : "value2
|
||||
|
|
@ -78,7 +78,7 @@ import static java.lang.String.format;
|
|||
* },
|
||||
* "machines" : {
|
||||
* "dev-machine" : {
|
||||
* "agents" : [ "exec-agent", "ws-agent" ],
|
||||
* "agents" : [ "exec-agent", "org.eclipse.che.ws-agent" ],
|
||||
* "servers" : {
|
||||
* "some_reference" : {
|
||||
* "port" : "9090/udp",
|
||||
|
|
@ -151,7 +151,7 @@ public class WorkspaceConfigJsonAdapter {
|
|||
|
||||
// dev-machine agents
|
||||
final JsonArray agents = new JsonArray();
|
||||
agents.add(new JsonPrimitive("ws-agent"));
|
||||
agents.add(new JsonPrimitive("org.eclipse.che.ws-agent"));
|
||||
newMachine.add("agents", agents);
|
||||
|
||||
// dev-machine ram
|
||||
|
|
|
|||
|
|
@ -13,7 +13,13 @@ package org.eclipse.che.api.workspace.server;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import org.eclipse.che.api.agent.server.wsagent.WsAgentLauncher;
|
||||
import org.eclipse.che.api.agent.server.AgentRegistry;
|
||||
import org.eclipse.che.api.agent.server.exception.AgentException;
|
||||
import org.eclipse.che.api.agent.server.impl.AgentSorter;
|
||||
import org.eclipse.che.api.agent.server.launcher.AgentLauncher;
|
||||
import org.eclipse.che.api.agent.server.launcher.AgentLauncherFactory;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.agent.shared.model.AgentKey;
|
||||
import org.eclipse.che.api.core.ApiException;
|
||||
import org.eclipse.che.api.core.ConflictException;
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
|
|
@ -22,6 +28,7 @@ import org.eclipse.che.api.core.model.machine.MachineConfig;
|
|||
import org.eclipse.che.api.core.model.machine.MachineLogMessage;
|
||||
import org.eclipse.che.api.core.model.machine.MachineStatus;
|
||||
import org.eclipse.che.api.core.model.workspace.Environment;
|
||||
import org.eclipse.che.api.core.model.workspace.ExtendedMachine;
|
||||
import org.eclipse.che.api.core.model.workspace.WorkspaceRuntime;
|
||||
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
|
|
@ -30,9 +37,11 @@ import org.eclipse.che.api.core.util.MessageConsumer;
|
|||
import org.eclipse.che.api.core.util.WebsocketMessageConsumer;
|
||||
import org.eclipse.che.api.environment.server.CheEnvironmentEngine;
|
||||
import org.eclipse.che.api.environment.server.exception.EnvironmentNotRunningException;
|
||||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.model.impl.SnapshotImpl;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.ExtendedMachineImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceRuntimeImpl;
|
||||
import org.eclipse.che.api.workspace.shared.dto.event.WorkspaceStatusEvent;
|
||||
|
|
@ -89,17 +98,23 @@ public class WorkspaceRuntimes {
|
|||
private final EventService eventService;
|
||||
private final StripedLocks stripedLocks;
|
||||
private final CheEnvironmentEngine environmentEngine;
|
||||
private final WsAgentLauncher wsAgentLauncher;
|
||||
private final AgentSorter agentSorter;
|
||||
private final AgentLauncherFactory launcherFactory;
|
||||
private final AgentRegistry agentRegistry;
|
||||
|
||||
private volatile boolean isPreDestroyInvoked;
|
||||
|
||||
@Inject
|
||||
public WorkspaceRuntimes(EventService eventService,
|
||||
CheEnvironmentEngine environmentEngine,
|
||||
WsAgentLauncher wsAgentLauncher) {
|
||||
AgentSorter agentSorter,
|
||||
AgentLauncherFactory launcherFactory,
|
||||
AgentRegistry agentRegistry) {
|
||||
this.eventService = eventService;
|
||||
this.environmentEngine = environmentEngine;
|
||||
this.wsAgentLauncher = wsAgentLauncher;
|
||||
this.agentSorter = agentSorter;
|
||||
this.launcherFactory = launcherFactory;
|
||||
this.agentRegistry = agentRegistry;
|
||||
this.workspaces = new HashMap<>();
|
||||
// 16 - experimental value for stripes count, it comes from default hash map size
|
||||
this.stripedLocks = new StripedLocks(16);
|
||||
|
|
@ -233,9 +248,7 @@ public class WorkspaceRuntimes {
|
|||
environmentCopy,
|
||||
recover,
|
||||
getEnvironmentLogger(workspaceId));
|
||||
Instance devMachine = getDevMachine(machines);
|
||||
|
||||
wsAgentLauncher.startWsAgent(devMachine);
|
||||
launchAgents(environment, machines);
|
||||
|
||||
try (StripedLocks.WriteLock lock = stripedLocks.acquireWriteLock(workspaceId)) {
|
||||
WorkspaceState workspaceState = workspaces.get(workspaceId);
|
||||
|
|
@ -265,6 +278,19 @@ public class WorkspaceRuntimes {
|
|||
}
|
||||
}
|
||||
|
||||
private void launchAgents(EnvironmentImpl environment, List<Instance> machines) throws ServerException {
|
||||
for (Instance instance : machines) {
|
||||
Map<String, ExtendedMachineImpl> envMachines = environment.getMachines();
|
||||
if (envMachines != null) {
|
||||
ExtendedMachine extendedMachine = envMachines.get(instance.getConfig().getName());
|
||||
if (extendedMachine != null) {
|
||||
List<String> agents = extendedMachine.getAgents();
|
||||
launchAgents(instance, agents);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops running workspace runtime.
|
||||
*
|
||||
|
|
@ -382,6 +408,7 @@ public class WorkspaceRuntimes {
|
|||
}
|
||||
|
||||
Instance instance = environmentEngine.startMachine(workspaceId, machineConfig);
|
||||
launchAgents(instance, Collections.singletonList("org.eclipse.che.terminal"));
|
||||
|
||||
try (StripedLocks.WriteLock lock = stripedLocks.acquireWriteLock(workspaceId)) {
|
||||
WorkspaceState workspaceState = workspaces.get(workspaceId);
|
||||
|
|
@ -574,6 +601,20 @@ public class WorkspaceRuntimes {
|
|||
}
|
||||
}
|
||||
|
||||
protected void launchAgents(Instance instance, List<String> agents) throws ServerException {
|
||||
try {
|
||||
for (AgentKey agentKey : agentSorter.sort(agents)) {
|
||||
LOG.info("Launching '{}' agent", agentKey.getName());
|
||||
|
||||
Agent agent = agentRegistry.getAgent(agentKey);
|
||||
AgentLauncher launcher = launcherFactory.find(agentKey.getName(), instance.getConfig().getType());
|
||||
launcher.launch(instance, agent);
|
||||
}
|
||||
} catch (AgentException e) {
|
||||
throw new MachineException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static class WorkspaceState {
|
||||
private WorkspaceStatus status;
|
||||
private String activeEnv;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.workspace.server.launcher;
|
||||
|
||||
import org.eclipse.che.api.agent.server.launcher.AbstractAgentLauncher;
|
||||
import org.eclipse.che.api.agent.server.launcher.ProcessIsLaunchedChecker;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Starts terminal agent.
|
||||
*
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
@Singleton
|
||||
public class SshAgentLauncherImpl extends AbstractAgentLauncher {
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(SshAgentLauncherImpl.class);
|
||||
|
||||
@Inject
|
||||
public SshAgentLauncherImpl(@Named("machine.agent.max_start_time_ms") long agentMaxStartTimeMs,
|
||||
@Named("machine.agent.ping_delay_ms") long agentPingDelayMs) {
|
||||
super(agentMaxStartTimeMs, agentPingDelayMs, new ProcessIsLaunchedChecker("sshd"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMachineType() {
|
||||
return "docker";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAgentName() {
|
||||
return "org.eclipse.che.ssh";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.workspace.server.launcher;
|
||||
|
||||
import org.eclipse.che.api.agent.server.launcher.AbstractAgentLauncher;
|
||||
import org.eclipse.che.api.agent.server.launcher.ProcessIsLaunchedChecker;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
/**
|
||||
* Starts terminal agent.
|
||||
*
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
@Singleton
|
||||
public class TerminalAgentLauncherImpl extends AbstractAgentLauncher {
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(TerminalAgentLauncherImpl.class);
|
||||
|
||||
@Inject
|
||||
public TerminalAgentLauncherImpl(@Named("machine.agent.max_start_time_ms") long agentMaxStartTimeMs,
|
||||
@Named("machine.agent.ping_delay_ms") long agentPingDelayMs) {
|
||||
super(agentMaxStartTimeMs, agentPingDelayMs, new ProcessIsLaunchedChecker("che-websocket-terminal"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMachineType() {
|
||||
return "docker";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAgentName() {
|
||||
return "org.eclipse.che.terminal";
|
||||
}
|
||||
}
|
||||
|
|
@ -8,20 +8,24 @@
|
|||
* Contributors:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.wsagent;
|
||||
package org.eclipse.che.api.workspace.server.launcher;
|
||||
|
||||
import org.eclipse.che.api.agent.server.launcher.AgentLauncher;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.core.ApiException;
|
||||
import org.eclipse.che.api.core.BadRequestException;
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
import org.eclipse.che.api.core.model.machine.Machine;
|
||||
import org.eclipse.che.api.core.model.machine.Server;
|
||||
import org.eclipse.che.api.core.rest.HttpJsonRequest;
|
||||
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
|
||||
import org.eclipse.che.api.core.rest.HttpJsonResponse;
|
||||
import org.eclipse.che.api.environment.server.MachineProcessManager;
|
||||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.model.impl.CommandImpl;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.eclipse.che.api.machine.shared.Constants;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
|
@ -34,68 +38,85 @@ import java.io.IOException;
|
|||
import java.net.HttpURLConnection;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.MoreObjects.firstNonNull;
|
||||
import static org.eclipse.che.api.workspace.shared.Constants.WS_AGENT_PROCESS_NAME;
|
||||
|
||||
/**
|
||||
* Starts ws agent in the machine and waits until ws agent sends notification about its start
|
||||
* Starts ws agent in the machine and waits until ws agent sends notification about its start.
|
||||
*
|
||||
* @author Alexander Garagatyi
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
@Singleton
|
||||
public class WsAgentLauncherImpl implements WsAgentLauncher {
|
||||
public static final String WS_AGENT_PROCESS_START_COMMAND = "machine.ws_agent.run_command";
|
||||
|
||||
public class WsAgentLauncherImpl implements AgentLauncher {
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(WsAgentLauncherImpl.class);
|
||||
|
||||
private static final String WS_AGENT_PROCESS_OUTPUT_CHANNEL = "workspace:%s:ext-server:output";
|
||||
private static final String WS_AGENT_SERVER_NOT_FOUND_ERROR = "Workspace agent server not found in dev machine.";
|
||||
|
||||
protected static final String DEFAULT_WS_AGENT_RUN_COMMAND = "~/che/ws-agent/bin/catalina.sh run";
|
||||
|
||||
private final Provider<MachineProcessManager> machineProcessManagerProvider;
|
||||
private final HttpJsonRequestFactory httpJsonRequestFactory;
|
||||
private final String wsAgentStartCommandLine;
|
||||
private final long wsAgentMaxStartTimeMs;
|
||||
private final long wsAgentPingDelayMs;
|
||||
private final int wsAgentPingConnectionTimeoutMs;
|
||||
private final String pingTimedOutErrorMessage;
|
||||
private final String wsAgentRunCommand;
|
||||
|
||||
@Inject
|
||||
public WsAgentLauncherImpl(Provider<MachineProcessManager> machineProcessManagerProvider,
|
||||
HttpJsonRequestFactory httpJsonRequestFactory,
|
||||
@Named(WS_AGENT_PROCESS_START_COMMAND) String wsAgentStartCommandLine,
|
||||
@Nullable @Named("machine.ws_agent.run_command") String wsAgentRunCommand,
|
||||
@Named("machine.ws_agent.max_start_time_ms") long wsAgentMaxStartTimeMs,
|
||||
@Named("machine.ws_agent.ping_delay_ms") long wsAgentPingDelayMs,
|
||||
@Named("machine.ws_agent.ping_conn_timeout_ms") int wsAgentPingConnectionTimeoutMs,
|
||||
@Named("machine.ws_agent.ping_timed_out_error_msg") String pingTimedOutErrorMessage) {
|
||||
this.machineProcessManagerProvider = machineProcessManagerProvider;
|
||||
this.httpJsonRequestFactory = httpJsonRequestFactory;
|
||||
this.wsAgentStartCommandLine = wsAgentStartCommandLine;
|
||||
this.wsAgentMaxStartTimeMs = wsAgentMaxStartTimeMs;
|
||||
this.wsAgentPingDelayMs = wsAgentPingDelayMs;
|
||||
this.wsAgentPingConnectionTimeoutMs = wsAgentPingConnectionTimeoutMs;
|
||||
this.pingTimedOutErrorMessage = pingTimedOutErrorMessage;
|
||||
}
|
||||
|
||||
public static String getWsAgentProcessOutputChannel(String workspaceId) {
|
||||
return String.format(WS_AGENT_PROCESS_OUTPUT_CHANNEL, workspaceId);
|
||||
this.wsAgentRunCommand = wsAgentRunCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startWsAgent(Machine devMachine) throws NotFoundException,
|
||||
ServerException {
|
||||
final HttpJsonRequest wsAgentPingRequest = createPingRequest(devMachine);
|
||||
public String getAgentName() {
|
||||
return "org.eclipse.che.ws-agent";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMachineType() {
|
||||
return "docker";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch(Instance machine, Agent agent) throws ServerException {
|
||||
final HttpJsonRequest wsAgentPingRequest;
|
||||
try {
|
||||
wsAgentPingRequest = createPingRequest(machine);
|
||||
} catch (ServerException e) {
|
||||
throw new MachineException(e.getServiceError());
|
||||
}
|
||||
|
||||
String script = agent.getScript() + "\n" + firstNonNull(wsAgentRunCommand, DEFAULT_WS_AGENT_RUN_COMMAND);
|
||||
|
||||
final String wsAgentPingUrl = wsAgentPingRequest.getUrl();
|
||||
try {
|
||||
machineProcessManagerProvider.get().exec(devMachine.getWorkspaceId(),
|
||||
devMachine.getId(),
|
||||
new CommandImpl(WS_AGENT_PROCESS_NAME,
|
||||
wsAgentStartCommandLine,
|
||||
WS_AGENT_PROCESS_NAME), //for server side type of command mean nothing
|
||||
//but we will use it as marker on
|
||||
//client side for track this command
|
||||
getWsAgentProcessOutputChannel(devMachine.getWorkspaceId()));
|
||||
// for server side type of command mean nothing
|
||||
// but we will use it as marker on
|
||||
// client side for track this command
|
||||
CommandImpl command = new CommandImpl(getAgentName(), script, WS_AGENT_PROCESS_NAME);
|
||||
|
||||
machineProcessManagerProvider.get().exec(machine.getWorkspaceId(),
|
||||
machine.getId(),
|
||||
command,
|
||||
getWsAgentProcessOutputChannel(machine.getWorkspaceId()));
|
||||
|
||||
final long pingStartTimestamp = System.currentTimeMillis();
|
||||
LOG.debug("Starts pinging ws agent. Workspace ID:{}. Url:{}. Timestamp:{}",
|
||||
devMachine.getWorkspaceId(),
|
||||
machine.getWorkspaceId(),
|
||||
wsAgentPingUrl,
|
||||
pingStartTimestamp);
|
||||
|
||||
|
|
@ -106,18 +127,22 @@ public class WsAgentLauncherImpl implements WsAgentLauncher {
|
|||
Thread.sleep(wsAgentPingDelayMs);
|
||||
}
|
||||
}
|
||||
} catch (BadRequestException wsAgentLaunchingExc) {
|
||||
throw new ServerException(wsAgentLaunchingExc.getLocalizedMessage(), wsAgentLaunchingExc);
|
||||
} catch (BadRequestException | ServerException | NotFoundException e) {
|
||||
throw new ServerException(e.getServiceError());
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new ServerException("Ws agent pinging is interrupted");
|
||||
}
|
||||
LOG.error("Fail pinging ws agent. Workspace ID:{}. Url:{}. Timestamp:{}", devMachine.getWorkspaceId(), wsAgentPingUrl);
|
||||
LOG.error("Fail pinging ws agent. Workspace ID:{}. Url:{}. Timestamp:{}", machine.getWorkspaceId(), wsAgentPingUrl);
|
||||
throw new ServerException(pingTimedOutErrorMessage);
|
||||
}
|
||||
|
||||
public static String getWsAgentProcessOutputChannel(String workspaceId) {
|
||||
return String.format(WS_AGENT_PROCESS_OUTPUT_CHANNEL, workspaceId);
|
||||
}
|
||||
|
||||
// forms the ping request based on information about the machine.
|
||||
protected HttpJsonRequest createPingRequest(Machine machine) throws ServerException {
|
||||
protected HttpJsonRequest createPingRequest(Instance machine) throws ServerException {
|
||||
Map<String, ? extends Server> servers = machine.getRuntime().getServers();
|
||||
Server wsAgentServer = servers.get(Constants.WS_AGENT_PORT);
|
||||
if (wsAgentServer == null) {
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.environment.server;
|
||||
|
||||
import org.eclipse.che.api.agent.server.AgentRegistry;
|
||||
import org.eclipse.che.api.agent.server.impl.AgentSorter;
|
||||
import org.eclipse.che.api.agent.server.launcher.AgentLauncherFactory;
|
||||
import org.eclipse.che.api.agent.server.model.impl.AgentKeyImpl;
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.environment.server.compose.model.ComposeServiceImpl;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Anatolii Bazko
|
||||
*/
|
||||
@Listeners(value = {MockitoTestNGListener.class})
|
||||
public class AgentConfigApplierTest {
|
||||
|
||||
@Mock
|
||||
private AgentSorter sorter;
|
||||
@Mock
|
||||
private Instance machine;
|
||||
@Mock
|
||||
private Agent agent1;
|
||||
@Mock
|
||||
private Agent agent2;
|
||||
@Mock
|
||||
private Agent agent3;
|
||||
@Mock
|
||||
private AgentLauncherFactory agentLauncher;
|
||||
@Mock
|
||||
private AgentRegistry agentRegistry;
|
||||
|
||||
private AgentConfigApplier agentConfigApplier;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() throws Exception {
|
||||
agentConfigApplier = new AgentConfigApplier(sorter, agentRegistry);
|
||||
when(agentRegistry.getAgent(AgentKeyImpl.parse("agent1"))).thenReturn(agent1);
|
||||
when(agentRegistry.getAgent(AgentKeyImpl.parse("agent2"))).thenReturn(agent2);
|
||||
when(agentRegistry.getAgent(AgentKeyImpl.parse("agent3"))).thenReturn(agent3);
|
||||
|
||||
when(agent1.getScript()).thenReturn("script1");
|
||||
when(agent1.getDependencies()).thenReturn(singletonList("fqn3"));
|
||||
|
||||
when(agent2.getScript()).thenReturn("script2");
|
||||
when(agent2.getDependencies()).thenReturn(singletonList("fqn3"));
|
||||
|
||||
when(agent3.getScript()).thenReturn("script3");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAddExposedPorts() throws Exception {
|
||||
when(sorter.sort(any()))
|
||||
.thenReturn(Arrays.asList(AgentKeyImpl.parse("agent1"), AgentKeyImpl.parse("agent2"), AgentKeyImpl.parse("agent3")));
|
||||
when(agent1.getProperties()).thenReturn(singletonMap("ports", "terminal:1111/udp,terminal:2222/tcp"));
|
||||
when(agent2.getProperties()).thenReturn(singletonMap("ports", "3333/udp"));
|
||||
ComposeServiceImpl composeService = new ComposeServiceImpl();
|
||||
|
||||
agentConfigApplier.modify(composeService, Arrays.asList("agent1", "agent2", "agent3"));
|
||||
|
||||
List<String> exposedPorts = composeService.getExpose();
|
||||
assertTrue(exposedPorts.contains("1111/udp"));
|
||||
assertTrue(exposedPorts.contains("2222/tcp"));
|
||||
assertTrue(exposedPorts.contains("3333/udp"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAddEnvVariables() throws Exception {
|
||||
when(sorter.sort(any())).thenReturn(Arrays.asList(AgentKeyImpl.parse("agent1"), AgentKeyImpl.parse("agent2")));
|
||||
when(agent1.getProperties()).thenReturn(singletonMap("environment", "p1=v1,p2=v2"));
|
||||
when(agent2.getProperties()).thenReturn(singletonMap("environment", "p3=v3"));
|
||||
ComposeServiceImpl composeService = new ComposeServiceImpl();
|
||||
|
||||
agentConfigApplier.modify(composeService, Arrays.asList("agent1", "agent2"));
|
||||
|
||||
Map<String, String> env = composeService.getEnvironment();
|
||||
assertEquals(env.size(), 3);
|
||||
assertEquals(env.get("p1"), "v1");
|
||||
assertEquals(env.get("p2"), "v2");
|
||||
assertEquals(env.get("p3"), "v3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreEnvironmentIfIllegalFormat() throws Exception {
|
||||
when(sorter.sort(any())).thenReturn(Arrays.asList(AgentKeyImpl.parse("agent1")));
|
||||
when(agent1.getProperties()).thenReturn(singletonMap("environment", "p1"));
|
||||
ComposeServiceImpl composeService = new ComposeServiceImpl();
|
||||
|
||||
agentConfigApplier.modify(composeService, Collections.singletonList("agent1"));
|
||||
|
||||
Map<String, String> env = composeService.getEnvironment();
|
||||
assertEquals(env.size(), 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -99,6 +99,8 @@ public class CheEnvironmentEngineTest {
|
|||
SnapshotDao snapshotDao;
|
||||
@Mock
|
||||
RecipeDownloader recipeDownloader;
|
||||
@Mock
|
||||
AgentConfigApplier agentConfigApplier;
|
||||
|
||||
EnvironmentParser environmentParser = new EnvironmentParser(new ComposeFileParser(), recipeDownloader);
|
||||
|
||||
|
|
@ -113,7 +115,8 @@ public class CheEnvironmentEngineTest {
|
|||
eventService,
|
||||
environmentParser,
|
||||
new ComposeServicesStartStrategy(),
|
||||
composeProvider));
|
||||
composeProvider,
|
||||
agentConfigApplier));
|
||||
|
||||
when(machineInstanceProviders.getProvider("docker")).thenReturn(instanceProvider);
|
||||
when(instanceProvider.getRecipeTypes()).thenReturn(Collections.singleton("dockerfile"));
|
||||
|
|
@ -609,7 +612,7 @@ public class CheEnvironmentEngineTest {
|
|||
new HashMap<>(singletonMap("prop1", "propValue"))));
|
||||
servers.put("ref2", new ServerConf2Impl("8080/udp", "proto1", null));
|
||||
servers.put("ref3", new ServerConf2Impl("9090", "proto1", null));
|
||||
machines.put("dev-machine", new ExtendedMachineImpl(new ArrayList<>(asList("ws-agent", "someAgent")),
|
||||
machines.put("dev-machine", new ExtendedMachineImpl(new ArrayList<>(asList("org.eclipse.che.ws-agent", "someAgent")),
|
||||
servers,
|
||||
new HashMap<>(singletonMap("memoryLimitBytes", "10000"))));
|
||||
machines.put("machine2", new ExtendedMachineImpl(new ArrayList<>(asList("someAgent2", "someAgent3")),
|
||||
|
|
|
|||
|
|
@ -186,20 +186,20 @@ public class CheEnvironmentValidatorTest {
|
|||
|
||||
env = createEnv();
|
||||
env.setMachines(null);
|
||||
data.add(asList(env, "Environment 'env' doesn't contain machine with 'ws-agent' agent"));
|
||||
data.add(asList(env, "Environment 'env' doesn't contain machine with 'org.eclipse.che.ws-agent' agent"));
|
||||
|
||||
env = createEnv();
|
||||
env.setMachines(emptyMap());
|
||||
data.add(asList(env, "Environment 'env' doesn't contain machine with 'ws-agent' agent"));
|
||||
data.add(asList(env, "Environment 'env' doesn't contain machine with 'org.eclipse.che.ws-agent' agent"));
|
||||
|
||||
env = createEnv();
|
||||
env.getMachines().put("missingInComposeEnvMachine",
|
||||
newDto(ExtendedMachineDto.class).withAgents(singletonList("ws-agent")));
|
||||
newDto(ExtendedMachineDto.class).withAgents(singletonList("org.eclipse.che.ws-agent")));
|
||||
data.add(asList(env, "Environment 'env' contains machines that are missing in environment recipe: missingInComposeEnvMachine"));
|
||||
|
||||
env = createEnv();
|
||||
env.getMachines().entrySet().forEach(entry -> entry.getValue().getAgents().add("ws-agent"));
|
||||
data.add(asList(env, "Environment 'env' should contain exactly 1 machine with ws-agent, but contains '" +
|
||||
env.getMachines().entrySet().forEach(entry -> entry.getValue().getAgents().add("org.eclipse.che.ws-agent"));
|
||||
data.add(asList(env, "Environment 'env' should contain exactly 1 machine with org.eclipse.che.ws-agent, but contains '" +
|
||||
env.getMachines().size() + "'. " + "All machines with this agent: " +
|
||||
Joiner.on(", ").join(env.getMachines().keySet())));
|
||||
|
||||
|
|
@ -537,7 +537,7 @@ public class CheEnvironmentValidatorTest {
|
|||
new HashMap<>(singletonMap("prop1", "propValue"))));
|
||||
servers.put("ref2", new ServerConf2Impl("8080/udp", "proto1", null));
|
||||
servers.put("ref3", new ServerConf2Impl("9090", "proto1", null));
|
||||
machines.put("dev-machine", new ExtendedMachineImpl(new ArrayList<>(asList("ws-agent", "someAgent")),
|
||||
machines.put("dev-machine", new ExtendedMachineImpl(new ArrayList<>(asList("org.eclipse.che.ws-agent", "someAgent")),
|
||||
servers,
|
||||
new HashMap<>(singletonMap("memoryLimitBytes", "10000"))));
|
||||
machines.put("machine2", new ExtendedMachineImpl(new ArrayList<>(asList("someAgent2", "someAgent3")),
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ public class DefaultWorkspaceValidatorTest {
|
|||
.withDefaultEnv("dev-env");
|
||||
|
||||
ExtendedMachineDto extendedMachine =
|
||||
newDto(ExtendedMachineDto.class).withAgents(singletonList("ws-agent"))
|
||||
newDto(ExtendedMachineDto.class).withAgents(singletonList("org.eclipse.che.ws-agent"))
|
||||
.withServers(singletonMap("ref1",
|
||||
newDto(ServerConf2Dto.class).withPort("8080/tcp")
|
||||
.withProtocol("https")
|
||||
|
|
|
|||
|
|
@ -885,7 +885,7 @@ public class WorkspaceManagerTest {
|
|||
"content",
|
||||
null),
|
||||
singletonMap("dev-machine",
|
||||
new ExtendedMachineImpl(singletonList("ws-agent"),
|
||||
new ExtendedMachineImpl(singletonList("org.eclipse.che.ws-agent"),
|
||||
null,
|
||||
new HashMap<>(singletonMap("memoryLimitBytes", "10000")))));
|
||||
return WorkspaceConfigImpl.builder()
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.api.workspace.server;
|
||||
|
||||
import org.eclipse.che.api.agent.server.wsagent.WsAgentLauncher;
|
||||
import org.eclipse.che.api.agent.server.AgentRegistry;
|
||||
import org.eclipse.che.api.agent.server.impl.AgentSorter;
|
||||
import org.eclipse.che.api.agent.server.launcher.AgentLauncherFactory;
|
||||
import org.eclipse.che.api.core.ConflictException;
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
|
|
@ -21,9 +23,9 @@ import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
|
|||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.api.environment.server.CheEnvironmentEngine;
|
||||
import org.eclipse.che.api.environment.server.NoOpMachineInstance;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineLimitsImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineConfigImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineLimitsImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineRuntimeInfoImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineSourceImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.SnapshotImpl;
|
||||
|
|
@ -82,13 +84,17 @@ public class WorkspaceRuntimesTest {
|
|||
private CheEnvironmentEngine environmentEngine;
|
||||
|
||||
@Mock
|
||||
private WsAgentLauncher wsAgentLauncher;
|
||||
private AgentSorter agentSorter;
|
||||
@Mock
|
||||
private AgentLauncherFactory launcherFactory;
|
||||
@Mock
|
||||
private AgentRegistry agentRegistry;
|
||||
|
||||
private WorkspaceRuntimes runtimes;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp(Method method) throws Exception {
|
||||
runtimes = spy(new WorkspaceRuntimes(eventService, environmentEngine, wsAgentLauncher));
|
||||
runtimes = spy(new WorkspaceRuntimes(eventService, environmentEngine, agentSorter, launcherFactory, agentRegistry));
|
||||
|
||||
List<Instance> machines = asList(createMachine(true), createMachine(false));
|
||||
when(environmentEngine.start(anyString(),
|
||||
|
|
|
|||
|
|
@ -816,7 +816,7 @@ public class WorkspaceServiceTest {
|
|||
}
|
||||
|
||||
private static EnvironmentDto createEnvDto() {
|
||||
ExtendedMachineImpl devMachine = new ExtendedMachineImpl(singletonList("ws-agent"),
|
||||
ExtendedMachineImpl devMachine = new ExtendedMachineImpl(singletonList("org.eclipse.che.ws-agent"),
|
||||
null,
|
||||
new HashMap<>(singletonMap("memoryLimitBytes", "10000")));
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@
|
|||
* Contributors:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.api.agent.server.wsagent;
|
||||
package org.eclipse.che.api.workspace.server.launcher;
|
||||
|
||||
import org.eclipse.che.api.agent.shared.model.Agent;
|
||||
import org.eclipse.che.api.core.BadRequestException;
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
|
|
@ -21,9 +22,9 @@ import org.eclipse.che.api.core.rest.HttpJsonResponse;
|
|||
import org.eclipse.che.api.environment.server.MachineProcessManager;
|
||||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.model.impl.CommandImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineRuntimeInfoImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.ServerImpl;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.eclipse.che.api.machine.shared.Constants;
|
||||
import org.eclipse.che.commons.test.mockito.answer.SelfReturningAnswer;
|
||||
import org.mockito.Mock;
|
||||
|
|
@ -50,32 +51,33 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class WsAgentLauncherImplTest {
|
||||
private static final String MACHINE_ID = "machineId";
|
||||
private static final String WORKSPACE_ID = "testWorkspaceId";
|
||||
private static final String WS_AGENT_START_CMD_LINE = "cmdLine";
|
||||
private static final String WS_AGENT_PORT = Constants.WS_AGENT_PORT;
|
||||
private static final long WS_AGENT_MAX_START_TIME_MS = 1000;
|
||||
private static final long WS_AGENT_PING_DELAY_MS = 1;
|
||||
private static final int WS_AGENT_PING_CONN_TIMEOUT_MS = 1;
|
||||
private static final String WS_AGENT_SERVER_LOCATION = "ws-agent.com:456789/";
|
||||
private static final String WS_AGENT_SERVER_URL = "http://" + WS_AGENT_SERVER_LOCATION;
|
||||
private static final String MACHINE_ID = "machineId";
|
||||
private static final String WORKSPACE_ID = "testWorkspaceId";
|
||||
private static final String WS_AGENT_PORT = Constants.WS_AGENT_PORT;
|
||||
private static final long WS_AGENT_MAX_START_TIME_MS = 1000;
|
||||
private static final long WS_AGENT_PING_DELAY_MS = 1;
|
||||
private static final int WS_AGENT_PING_CONN_TIMEOUT_MS = 1;
|
||||
private static final String WS_AGENT_SERVER_LOCATION = "ws-agent.com:456789/";
|
||||
private static final String WS_AGENT_SERVER_URL = "http://" + WS_AGENT_SERVER_LOCATION;
|
||||
private static final ServerImpl SERVER = new ServerImpl("ref",
|
||||
"http",
|
||||
WS_AGENT_SERVER_LOCATION,
|
||||
null,
|
||||
WS_AGENT_SERVER_URL);
|
||||
private static final String WS_AGENT_TIMED_OUT_MESSAGE = "timeout error message";
|
||||
private static final String WS_AGENT_TIMED_OUT_MESSAGE = "timeout error message";
|
||||
|
||||
@Mock
|
||||
private MachineProcessManager machineProcessManager;
|
||||
@Mock
|
||||
private HttpJsonRequestFactory requestFactory;
|
||||
@Mock
|
||||
private MachineImpl machine;
|
||||
private Instance machine;
|
||||
@Mock
|
||||
private HttpJsonResponse pingResponse;
|
||||
@Mock
|
||||
private MachineRuntimeInfoImpl machineRuntime;
|
||||
@Mock
|
||||
private Agent agent;
|
||||
|
||||
private HttpJsonRequest pingRequest;
|
||||
private WsAgentLauncherImpl wsAgentLauncher;
|
||||
|
|
@ -83,13 +85,14 @@ public class WsAgentLauncherImplTest {
|
|||
@BeforeMethod
|
||||
public void setUp() throws Exception {
|
||||
wsAgentLauncher = new WsAgentLauncherImpl(() -> machineProcessManager,
|
||||
requestFactory,
|
||||
WS_AGENT_START_CMD_LINE,
|
||||
requestFactory, null,
|
||||
WS_AGENT_MAX_START_TIME_MS,
|
||||
WS_AGENT_PING_DELAY_MS,
|
||||
WS_AGENT_PING_CONN_TIMEOUT_MS,
|
||||
WS_AGENT_TIMED_OUT_MESSAGE);
|
||||
WS_AGENT_TIMED_OUT_MESSAGE
|
||||
);
|
||||
pingRequest = Mockito.mock(HttpJsonRequest.class, new SelfReturningAnswer());
|
||||
when(agent.getScript()).thenReturn("script");
|
||||
when(machine.getId()).thenReturn(MACHINE_ID);
|
||||
when(machine.getWorkspaceId()).thenReturn(WORKSPACE_ID);
|
||||
when(machine.getRuntime()).thenReturn(machineRuntime);
|
||||
|
|
@ -101,12 +104,12 @@ public class WsAgentLauncherImplTest {
|
|||
|
||||
@Test
|
||||
public void shouldStartWsAgentUsingMachineExec() throws Exception {
|
||||
wsAgentLauncher.startWsAgent(machine);
|
||||
wsAgentLauncher.launch(machine, agent);
|
||||
|
||||
verify(machineProcessManager).exec(eq(WORKSPACE_ID),
|
||||
eq(MACHINE_ID),
|
||||
eq(new CommandImpl(WS_AGENT_PROCESS_NAME,
|
||||
WS_AGENT_START_CMD_LINE,
|
||||
eq(new CommandImpl("org.eclipse.che.ws-agent",
|
||||
"script\n" + WsAgentLauncherImpl.DEFAULT_WS_AGENT_RUN_COMMAND,
|
||||
WS_AGENT_PROCESS_NAME)),
|
||||
eq(WsAgentLauncherImpl.getWsAgentProcessOutputChannel(WORKSPACE_ID)));
|
||||
|
||||
|
|
@ -114,7 +117,7 @@ public class WsAgentLauncherImplTest {
|
|||
|
||||
@Test
|
||||
public void shouldPingWsAgentAfterStart() throws Exception {
|
||||
wsAgentLauncher.startWsAgent(machine);
|
||||
wsAgentLauncher.launch(machine, agent);
|
||||
|
||||
verify(requestFactory).fromUrl(UriBuilder.fromUri(WS_AGENT_SERVER_URL)
|
||||
.build()
|
||||
|
|
@ -132,7 +135,7 @@ public class WsAgentLauncherImplTest {
|
|||
new IOException())
|
||||
.thenReturn(pingResponse);
|
||||
|
||||
wsAgentLauncher.startWsAgent(machine);
|
||||
wsAgentLauncher.launch(machine, agent);
|
||||
|
||||
verify(requestFactory).fromUrl(WS_AGENT_SERVER_URL);
|
||||
verify(pingRequest).setMethod(HttpMethod.GET);
|
||||
|
|
@ -147,7 +150,7 @@ public class WsAgentLauncherImplTest {
|
|||
HttpURLConnection.HTTP_NO_CONTENT,
|
||||
HttpURLConnection.HTTP_OK);
|
||||
|
||||
wsAgentLauncher.startWsAgent(machine);
|
||||
wsAgentLauncher.launch(machine, agent);
|
||||
|
||||
verify(requestFactory).fromUrl(WS_AGENT_SERVER_URL);
|
||||
verify(pingRequest).setMethod(HttpMethod.GET);
|
||||
|
|
@ -161,21 +164,21 @@ public class WsAgentLauncherImplTest {
|
|||
when(pingRequest.request()).thenThrow(new ServerException(""))
|
||||
.thenReturn(pingResponse);
|
||||
|
||||
wsAgentLauncher.startWsAgent(machine);
|
||||
wsAgentLauncher.launch(machine, agent);
|
||||
|
||||
verify(pingRequest, times(2)).request();
|
||||
verify(pingResponse).getResponseCode();
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NotFoundException.class, expectedExceptionsMessageRegExp = "Test exception")
|
||||
public void shouldThrowNotFoundExceptionIfMachineManagerExecInDevMachineThrowsNotFoundException() throws Exception {
|
||||
@Test(expectedExceptions = ServerException.class, expectedExceptionsMessageRegExp = "Test exception")
|
||||
public void shouldThrowMachineExceptionIfMachineManagerExecInDevMachineThrowsNotFoundException() throws Exception {
|
||||
when(machineProcessManager.exec(anyString(),
|
||||
anyString(),
|
||||
any(Command.class),
|
||||
anyString()))
|
||||
.thenThrow(new NotFoundException("Test exception"));
|
||||
|
||||
wsAgentLauncher.startWsAgent(machine);
|
||||
wsAgentLauncher.launch(machine, agent);
|
||||
|
||||
verify(machineProcessManager).exec(anyString(),
|
||||
anyString(),
|
||||
|
|
@ -183,7 +186,7 @@ public class WsAgentLauncherImplTest {
|
|||
anyString());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = MachineException.class, expectedExceptionsMessageRegExp = "Test exception")
|
||||
@Test(expectedExceptions = ServerException.class, expectedExceptionsMessageRegExp = "Test exception")
|
||||
public void shouldThrowMachineExceptionIfMachineManagerExecInDevMachineThrowsMachineException() throws Exception {
|
||||
when(machineProcessManager.exec(anyString(),
|
||||
anyString(),
|
||||
|
|
@ -191,7 +194,7 @@ public class WsAgentLauncherImplTest {
|
|||
anyString()))
|
||||
.thenThrow(new MachineException("Test exception"));
|
||||
|
||||
wsAgentLauncher.startWsAgent(machine);
|
||||
wsAgentLauncher.launch(machine, agent);
|
||||
|
||||
verify(machineProcessManager).exec(anyString(),
|
||||
anyString(),
|
||||
|
|
@ -207,7 +210,7 @@ public class WsAgentLauncherImplTest {
|
|||
anyString()))
|
||||
.thenThrow(new BadRequestException("Test exception"));
|
||||
|
||||
wsAgentLauncher.startWsAgent(machine);
|
||||
wsAgentLauncher.launch(machine, agent);
|
||||
|
||||
verify(machineProcessManager).exec(anyString(),
|
||||
anyString(),
|
||||
|
|
@ -220,7 +223,7 @@ public class WsAgentLauncherImplTest {
|
|||
public void shouldThrowMachineExceptionIfPingsWereUnsuccessfulTooLong() throws Exception {
|
||||
when(pingRequest.request()).thenThrow(new ServerException(""));
|
||||
|
||||
wsAgentLauncher.startWsAgent(machine);
|
||||
wsAgentLauncher.launch(machine, agent);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = ServerException.class,
|
||||
|
|
@ -228,6 +231,6 @@ public class WsAgentLauncherImplTest {
|
|||
public void shouldThrowExceptionIfWsAgentNotFound() throws Exception {
|
||||
doReturn(Collections.emptyMap()).when(machineRuntime).getServers();
|
||||
|
||||
wsAgentLauncher.startWsAgent(machine);
|
||||
wsAgentLauncher.launch(machine, agent);
|
||||
}
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
"machines": {
|
||||
"devmachine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.ws-agent"
|
||||
],
|
||||
"attributes" : {
|
||||
"memoryLimitBytes": "2147483648"
|
||||
|
|
@ -129,7 +129,7 @@
|
|||
"machines": {
|
||||
"devmachine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.ws-agent"
|
||||
],
|
||||
"attributes" : {
|
||||
"memoryLimitBytes": "2147483648"
|
||||
|
|
@ -217,7 +217,7 @@
|
|||
"machines": {
|
||||
"devmachine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.ws-agent"
|
||||
],
|
||||
"attributes" : {
|
||||
"memoryLimitBytes": "2147483648"
|
||||
|
|
@ -305,7 +305,7 @@
|
|||
"machines": {
|
||||
"devmachine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.ws-agent"
|
||||
],
|
||||
"attributes" : {
|
||||
"memoryLimitBytes": "2147483648"
|
||||
|
|
@ -393,7 +393,7 @@
|
|||
"machines": {
|
||||
"devmachine": {
|
||||
"agents": [
|
||||
"ws-agent"
|
||||
"org.eclipse.che.ws-agent"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
<module>che-core-api-factory</module>
|
||||
<module>che-core-api-ssh</module>
|
||||
<module>che-core-api-ssh-shared</module>
|
||||
<module>che-core-api-agent</module>
|
||||
<module>che-core-api-agent-shared</module>
|
||||
<module>wsmaster-local</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import org.eclipse.che.api.workspace.server.model.impl.ServerConf2Impl;
|
|||
import org.eclipse.che.api.workspace.server.model.impl.SourceStorageImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
|
||||
import org.mockito.Mockito;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
|
@ -46,7 +45,6 @@ import static org.eclipse.che.commons.lang.NameGenerator.generate;
|
|||
import static org.mockito.Mockito.mock;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Eugene Voevodin
|
||||
|
|
@ -127,7 +125,7 @@ public class LocalWorkspaceDaoTest {
|
|||
properties.put("prop4", "value4");
|
||||
servers.put("ref2", new ServerConf2Impl("port2", "proto2", properties));
|
||||
machines = new HashMap<>();
|
||||
machines.put("machine1", new ExtendedMachineImpl(asList("ws-agent", "someAgent"),
|
||||
machines.put("machine1", new ExtendedMachineImpl(asList("org.eclipse.che.ws-agent", "someAgent"),
|
||||
servers,
|
||||
new HashMap<>(singletonMap("memoryLimitBytes", "10000"))));
|
||||
servers = new HashMap<>();
|
||||
|
|
|
|||
Loading…
Reference in New Issue