/******************************************************************************* * Copyright 2012 Urbancode, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.urbancode.terraform.tasks.aws; import java.io.File; import java.io.IOException; import java.rmi.RemoteException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.apache.log4j.Logger; import com.jcraft.jsch.ChannelExec; import com.jcraft.jsch.JSchException; import com.urbancode.terraform.tasks.aws.helpers.SshConnection; import com.urbancode.terraform.tasks.aws.helpers.SshHelper; import com.urbancode.terraform.tasks.common.TerraformContext; import com.urbancode.terraform.tasks.common.exceptions.PostCreateException; public class SshTask extends PostCreateActionTask { //********************************************************************************************** // CLASS //********************************************************************************************** final static private Logger log = Logger.getLogger(SshTask.class); //********************************************************************************************** // INSTANCE //********************************************************************************************** private String cmds; private SshHelper sshHelper = new SshHelper(); private SshConnection ssh = null; //---------------------------------------------------------------------------------------------- public SshTask(TerraformContext context) { super(context); } //---------------------------------------------------------------------------------------------- public void setCmds(String cmds) { this.cmds = cmds; } //---------------------------------------------------------------------------------------------- public String getCmds() { return cmds; } //---------------------------------------------------------------------------------------------- private SshConnection startSshConnection() throws PostCreateException, JSchException { SshConnection result = null; if (host == null || host.isEmpty()) { String msg = "No host specified to connect to"; log.error(msg); throw new PostCreateException(msg); } if (user == null || user.isEmpty()) { String msg = "No user specified to connect as for instance " + host; log.error(msg); throw new PostCreateException(msg); } // are we connecting with a id-file? if (idFilePath != null && !idFilePath.isEmpty()) { File idFile = new File(idFilePath); if (idFile.exists() && idFile.isFile() && idFile.canRead()) { result = new SshConnection(host, user, idFile); } else { log.error("Unable to read file: " + idFile); } } // or are we connecting with a password? else if (pass != null && !pass.isEmpty()) { result = new SshConnection(host, user, pass); } // we can't connect without either an id-file or password else { log.error("No id file or password specifed. No way to connect to instance " + host); } return result; } //---------------------------------------------------------------------------------------------- private void runCmds() throws JSchException, IOException, InterruptedException, ExecutionException { ChannelExec channel = ssh.run(cmds); channel.getOutputStream().close(); Future<String> output = sshHelper.getOutputString(channel); Future<String> error = sshHelper.getErrorString(channel); String outputText = output.get(); String errorText = error.get(); while (true) { if (channel.isClosed()) { int exitCode = channel.getExitStatus(); if (exitCode != 0) { throw new IOException("Command failed with code " + exitCode + " : " + errorText); } break; } Thread.sleep(1000); } log.debug("Command out: " + outputText); log.debug("Command err: " + errorText); } //---------------------------------------------------------------------------------------------- @Override public void create() throws PostCreateException { try { ssh = startSshConnection(); // see if we made a connection if (ssh == null) { log.error("Attempted SSH connection: " + user + "@" + host + " || password: " + pass + " || id-file: " + idFilePath); throw new PostCreateException("Could not make SSH connection!"); } cmds = context.resolve(cmds); SshHelper.waitForPort(host, port); runCmds(); } catch (RemoteException e) { log.error("Timeout while waiting for port: " + port + " on host: " + host, e); throw new PostCreateException(e); } catch (JSchException e) { log.error("JSch unable to make SshConnection on port: " + port + " on host: " + host, e); throw new PostCreateException(e); } catch (IOException e) { log.error("Failed commands! Tried to run: " + cmds, e); throw new PostCreateException(e); } catch (InterruptedException e) { log.error("Thread Inturrupted!", e); throw new PostCreateException(e); } catch (ExecutionException e) { throw new PostCreateException(e); } finally { if (ssh != null) { ssh.close(); } } } //---------------------------------------------------------------------------------------------- @Override public void destroy() { //not needed for this task } }