/*******************************************************************************
* Copyright (c) 2012-2017 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.machine.ssh;
import com.google.gson.Gson;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.model.machine.Machine;
import org.eclipse.che.api.core.model.machine.MachineConfig;
import org.eclipse.che.api.core.model.machine.MachineSource;
import org.eclipse.che.api.core.model.machine.MachineStatus;
import org.eclipse.che.api.core.model.machine.Recipe;
import org.eclipse.che.api.core.util.LineConsumer;
import org.eclipse.che.api.machine.server.exception.InvalidRecipeException;
import org.eclipse.che.api.machine.server.exception.MachineException;
import org.eclipse.che.api.machine.server.exception.UnsupportedRecipeException;
import org.eclipse.che.api.machine.server.util.RecipeDownloader;
import javax.inject.Inject;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
import static java.util.Objects.requireNonNull;
/**
* Instance provider based on communication with machine over ssh protocol.
*
* <p>Ssh machine can't be actually created and exists somewhere outside of the control.<br>
* So this implementation just performs command execution in such machines.<br>
* This implementation ignores machine limits {@link MachineConfig#getLimits()}.
*
* @author Alexander Garagatyi
*/
// todo tests
public class SshMachineInstanceProvider {
private static final Gson GSON = new Gson();
private final Set<String> supportedRecipeTypes;
private final SshMachineFactory sshMachineFactory;
private final RecipeDownloader recipeDownloader;
@Inject
public SshMachineInstanceProvider(SshMachineFactory sshMachineFactory, RecipeDownloader recipeDownloader) throws IOException {
this.sshMachineFactory = sshMachineFactory;
this.recipeDownloader = recipeDownloader;
this.supportedRecipeTypes = Collections.singleton("ssh-config");
}
public String getType() {
return "ssh";
}
public Set<String> getRecipeTypes() {
return supportedRecipeTypes;
}
/**
* Creates instance from scratch or by reusing a previously one by using specified {@link MachineSource}
* data in {@link MachineConfig}.
*
* @param machine
* machine description
* @param lineConsumer
* output for instance creation logs
* @return newly created {@link SshMachineInstance}
* @throws UnsupportedRecipeException
* if specified {@code recipe} is not supported
* @throws InvalidRecipeException
* if {@code recipe} is invalid
* @throws NotFoundException
* if instance described by {@link MachineSource} doesn't exists
* @throws MachineException
* if other error occurs
*/
public SshMachineInstance createInstance(Machine machine, LineConsumer lineConsumer) throws NotFoundException, MachineException {
requireNonNull(machine, "Non null machine required");
requireNonNull(lineConsumer, "Non null logs consumer required");
requireNonNull(machine.getConfig().getSource().getLocation(), "Location in machine source is required");
if (machine.getConfig().isDev()) {
throw new MachineException("Dev machine is not supported for Ssh machine implementation");
}
Recipe recipe = recipeDownloader.getRecipe(machine.getConfig());
SshMachineRecipe sshMachineRecipe = GSON.fromJson(recipe.getScript(), SshMachineRecipe.class);
SshClient sshClient = sshMachineFactory.createSshClient(sshMachineRecipe,
machine.getConfig().getEnvVariables());
sshClient.start();
SshMachineInstance instance = sshMachineFactory.createInstance(machine,
sshClient,
lineConsumer);
instance.setStatus(MachineStatus.RUNNING);
return instance;
}
}