Skip to content

Commit

Permalink
Merge branch 'master' into CHE-1002
Browse files Browse the repository at this point in the history
  • Loading branch information
Vitaliy Guliy committed Apr 25, 2016
2 parents fd1e534 + 34b9a99 commit 390f9ed
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 15 deletions.
2 changes: 1 addition & 1 deletion CUSTOMIZING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A command is a process that is injected into your workspace. It's outputs are st

#### Templates
A template is a packaged set of sample code that is launched in the workspace when a user creates a new project. Users can select from a template while using the user dashboard. Templates have both sample code and a default set of commands associated with them. Templates are loaded based upon the type of stack selected. You can add your own templates to the default Che distribution.
* TODO: Reference Template Docs
* [Create Templates](https://eclipse-che.readme.io/docs/templates)

#### Stacks
A stack is the configuration of a runtime that can be used to power a workspace. Users choose the stack that powers a workspace within the user dashboard. Stacks have a recipe that defines how the container should be created and also meta data that defines the tags associated with the stack. Tags define how the stack is presented in the stack library and also filters out the available project templates that a user sees when creating a project.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class SshMachineImplTerminalLauncher implements MachineImplSpecificTermin
// 1. named group 'os' that contains 1+ non-space characters
// 2. space character
// 3. named group 'architecture' that contains 1+ non-space characters
private static final Pattern UNAME_OUTPUT = Pattern.compile("(?<os>[\\S]+) (?<architecture>[\\S]+)");
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";
Expand Down Expand Up @@ -95,9 +95,9 @@ private boolean isWebsocketTerminalRunning(Instance machine) throws MachineExcep
ListLineConsumer lineConsumer = new ListLineConsumer();
checkTerminalAlive.start(lineConsumer);
String checkAliveText = lineConsumer.getText();
if ("not found".equals(checkAliveText)) {
if ("[STDOUT] not found".equals(checkAliveText)) {
return false;
} else if (!"found".equals(checkAliveText)) {
} else if (!"[STDOUT] found".equals(checkAliveText)) {
LOG.error("Unexpected output of websocket terminal check. Output:" + checkAliveText);
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

import javax.inject.Inject;

import java.io.IOException;

import static java.lang.String.format;

/**
Expand Down Expand Up @@ -82,7 +84,8 @@ public void start(LineConsumer output) throws ConflictException, MachineExceptio
if (output == null) {
sshProcess.start();
} else {
sshProcess.start(output);
sshProcess.start(new PrefixingLineConsumer("[STDOUT] ", output),
new PrefixingLineConsumer("[STDERR] ", output));
}
}

Expand All @@ -101,4 +104,25 @@ public void checkAlive() throws MachineException, NotFoundException {
public void kill() throws MachineException {
sshProcess.kill();
}

private static class PrefixingLineConsumer implements LineConsumer {
private final String prefix;
private final LineConsumer lineConsumer;

public PrefixingLineConsumer(String prefix, LineConsumer lineConsumer) {
this.prefix = prefix;
this.lineConsumer = lineConsumer;
}


@Override
public void writeLine(String line) throws IOException {
lineConsumer.writeLine(prefix + line);
}

@Override
public void close() throws IOException {
lineConsumer.close();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
public interface SshProcess {
void start() throws MachineException;

void start(LineConsumer output) throws MachineException;
void start(LineConsumer outErr) throws MachineException;

void start(LineConsumer out, LineConsumer err) throws MachineException;

int getExitCode();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
* JSch implementation of {@link SshProcess}
Expand All @@ -42,25 +47,62 @@ public void start() throws MachineException {
}
}

// todo how to manage disconnections due to network failures?

@Override
public void start(LineConsumer output) throws MachineException {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(exec.getInputStream()));
try (PipedOutputStream pipedOS = new PipedOutputStream();
PipedInputStream pipedIS = new PipedInputStream(pipedOS);
BufferedReader outReader = new BufferedReader(new InputStreamReader(pipedIS))) {

exec.setOutputStream(pipedOS);
exec.setExtOutputStream(pipedOS);
exec.connect();

String outLine;
while ((outLine = outReader.readLine()) != null) {
output.writeLine(outLine);
}
} catch (IOException | JSchException e) {
throw new MachineException("Ssh machine command execution error:" + e.getLocalizedMessage());
} finally {
exec.disconnect();
}
}

@Override
public void start(LineConsumer out, LineConsumer err) throws MachineException {
try (BufferedReader outReader = new BufferedReader(new InputStreamReader(exec.getInputStream()));
BufferedReader errReader = new BufferedReader(new InputStreamReader(exec.getErrStream()))) {

exec.connect();

// read stderr in separate thread
CompletableFuture<Optional<IOException>> future = CompletableFuture.supplyAsync(() -> {
try {
String line;
while ((line = errReader.readLine()) != null) {
err.writeLine(line);
}
return Optional.empty();
} catch (IOException e) {
return Optional.of(e);
}
});

String line;
while ((line = reader.readLine()) != null) {
// todo format output as it is done in docker impl
// todo use async streams?
// todo how to manage disconnections due to network failures?
output.writeLine(line);
while ((line = outReader.readLine()) != null) {
out.writeLine(line);
}
while ((line = errReader.readLine()) != null) {
output.writeLine(line);

final Optional<IOException> excOptional = future.get();
if (excOptional.isPresent()) {
throw new MachineException("Ssh machine command execution error:" + excOptional.get().getLocalizedMessage());
}
} catch (IOException | JSchException e) {
} catch (IOException | JSchException | ExecutionException | InterruptedException e) {
throw new MachineException("Ssh machine command execution error:" + e.getLocalizedMessage());
} finally {
exec.disconnect();
}
}

Expand Down

0 comments on commit 390f9ed

Please sign in to comment.