package org.jvnet.hudson.plugins;
import hudson.Extension;
import hudson.Launcher;
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrapperDescriptor;
import hudson.util.CopyOnWriteList;
import hudson.util.FormValidation;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import com.jcraft.jsch.JSchException;
public final class SSHBuildWrapper extends BuildWrapper {
public static final Logger LOGGER = Logger.getLogger(SSHBuildWrapper.class.getName());
private String siteName;
private String preScript;
private String postScript;
public SSHBuildWrapper() {
}
@DataBoundConstructor
public SSHBuildWrapper(String siteName, String preScript, String postScript) {
if (siteName == null) {
// defaults to the first one
SSHSite[] sites = DESCRIPTOR.getSites();
if (sites.length > 0)
siteName = sites[0].getName();
}
this.siteName = siteName;
this.preScript = preScript;
this.postScript = postScript;
}
@Override
public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
Environment env = new Environment() {
@Override
public boolean tearDown(AbstractBuild build, BuildListener listener) throws IOException, InterruptedException {
executePostBuildScript(listener.getLogger());
return super.tearDown(build, listener);
}
};
executePreBuildScript(listener.getLogger());
return env;
}
private void executePreBuildScript(PrintStream logger) {
log(logger, "executing pre build script:\n" + preScript);
SSHSite site = getSite();
if (preScript != null && !preScript.trim().equals("")) {
site.executeCommand(logger, preScript);
}
}
private void executePostBuildScript(PrintStream logger) {
log(logger, "executing post build script:\n" + postScript);
SSHSite site = getSite();
if (postScript != null && !postScript.trim().equals("")) {
site.executeCommand(logger, postScript);
}
}
public String getPreScript() {
return preScript;
}
public void setPreScript(String preScript) {
this.preScript = preScript;
}
public String getPostScript() {
return postScript;
}
public void setPostScript(String postScript) {
this.postScript = postScript;
}
public SSHSite getSite() {
SSHSite[] sites = DESCRIPTOR.getSites();
if (siteName == null && sites.length > 0)
// default
return sites[0];
for (SSHSite site : sites) {
if (site.getName().equals(siteName))
return site;
}
return null;
}
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.BUILD;
}
@Extension
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
public static final class DescriptorImpl extends BuildWrapperDescriptor {
public DescriptorImpl() {
super(SSHBuildWrapper.class);
load();
}
protected DescriptorImpl(Class<? extends BuildWrapper> clazz) {
super(clazz);
}
private final CopyOnWriteList<SSHSite> sites = new CopyOnWriteList<SSHSite>();
public String getDisplayName() {
return "Execute shell script on remote host using ssh";
}
public String getShortName() {
return "[SSH] ";
}
@Override
public String getHelpFile() {
return "/plugin/ssh/help.html";
}
@Override
public BuildWrapper newInstance(StaplerRequest req, JSONObject formData) {
SSHBuildWrapper pub = new SSHBuildWrapper();
req.bindParameters(pub, "ssh.");
return pub;
}
public SSHSite[] getSites() {
Iterator<SSHSite> it = sites.iterator();
int size = 0;
while (it.hasNext()) {
it.next();
size++;
}
return sites.toArray(new SSHSite[size]);
}
@Override
public boolean configure(StaplerRequest req, JSONObject formData) {
sites.replaceBy(req.bindParametersToList(SSHSite.class, "ssh."));
save();
return true;
}
public FormValidation doKeyfileCheck(@QueryParameter String keyfile) {
keyfile = Util.fixEmpty(keyfile);
if (keyfile != null) {
File f = new File(keyfile);
if (!f.isFile()) {
return FormValidation.error("keyfile does not exist");
}
}
return FormValidation.ok();
}
public FormValidation doLoginCheck(StaplerRequest request) {
String hostname = Util.fixEmpty(request.getParameter("hostname"));
if (hostname == null) {// hosts is not entered yet
return FormValidation.ok();
}
SSHSite site = new SSHSite(hostname, request.getParameter("port"), request.getParameter("user"), request.getParameter("pass"), request.getParameter("keyfile"));
try {
try {
site.testConnection(System.out);
}
catch (JSchException e) {
LOGGER.log(Level.SEVERE, e.getMessage());
throw new IOException("Can't connect to server");
}
}
catch (IOException e) {
LOGGER.log(Level.SEVERE, e.getMessage());
return FormValidation.error(e.getMessage());
}
return FormValidation.ok();
}
@Override
public boolean isApplicable(AbstractProject<?, ?> item) {
return true;
}
}
public String getSiteName() {
return siteName;
}
public void setSiteName(String siteName) {
this.siteName = siteName;
};
private void log(final PrintStream logger, final String message) {
logger.println(StringUtils.defaultString(DESCRIPTOR.getShortName()) + message);
}
}