提交 8585d3d5 编写于 作者: K kohsuke

added a hook for decorating launchers

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@16994 71c3de6d-444a-0410-be80-ed276b4c234a
上级 5ad3cf61
......@@ -28,6 +28,7 @@ import hudson.Proc.RemoteProc;
import hudson.model.Computer;
import hudson.model.Hudson;
import hudson.model.TaskListener;
import hudson.model.Node;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.Pipe;
......@@ -325,6 +326,60 @@ public abstract class Launcher {
printCommandLine(masked, workDir);
}
/**
* Returns a decorated {@link Launcher} for the given node.
*/
public final Launcher decorateFor(Node node) {
Launcher l = this;
for (LauncherDecorator d : LauncherDecorator.all())
l = d.decorate(l,node);
return l;
}
/**
* Returns a decorated {@link Launcher} that puts the given set of arguments as a prefix to any commands
* that it invokes.
*
* @since 1.299
*/
public final Launcher decorateByPrefix(final String... prefix) {
final Launcher outer = this;
return new Launcher(listener,channel) {
@Override
public Proc launch(String[] cmd, String[] env, InputStream in, OutputStream out, FilePath workDir) throws IOException {
return outer.launch(prefix(cmd),env,in,out,workDir);
}
@Override
public Proc launch(String[] cmd, boolean[] mask, String[] env, InputStream in, OutputStream out, FilePath workDir) throws IOException {
return outer.launch(prefix(cmd),prefix(mask),env,in,out,workDir);
}
@Override
public Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map<String, String> envVars) throws IOException, InterruptedException {
return outer.launchChannel(prefix(cmd),out,workDir,envVars);
}
@Override
public void kill(Map<String, String> modelEnvVars) throws IOException, InterruptedException {
outer.kill(modelEnvVars);
}
private String[] prefix(String[] args) {
String[] newArgs = new String[args.length+prefix.length];
System.arraycopy(prefix,0,newArgs,0,prefix.length);
System.arraycopy(args,0,newArgs,prefix.length,args.length);
return newArgs;
}
private boolean[] prefix(boolean[] args) {
boolean[] newArgs = new boolean[args.length+prefix.length];
System.arraycopy(args,0,newArgs,prefix.length,args.length);
return newArgs;
}
};
}
/**
* {@link Launcher} that launches process locally.
*/
......
package hudson;
import hudson.model.Hudson;
import hudson.model.Node;
import hudson.model.TaskListener;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Executor;
import hudson.tasks.BuildWrapper;
/**
* Decorates {@link Launcher} so that one can intercept executions of commands
* and alters the command being executed, such as doing this in fakeroot, sudo, pfexec, etc.
*
* @author Kohsuke Kawaguchi
* @since 1.299
* @see BuildWrapper#decorateLauncher(AbstractBuild, Launcher, BuildListener)
*/
public abstract class LauncherDecorator implements ExtensionPoint {
/**
* Called from {@link Node#createLauncher(TaskListener)} to decorate the launchers.
*
* <p>
* This method should perform node-specific decoration. For job-specific decoration,
* {@link BuildWrapper#decorateLauncher(AbstractBuild, Launcher, BuildListener)} might
* fit your needs better.
*
* <p>
* If the implementation wants to do something differently if the launcher is
* for a build, call {@link Executor#currentExecutor()}. If it returns non-null
* you can figure out the current build in progress from there. Note that
* {@link Launcher}s are also created for doing things other than builds,
* so {@link Executor#currentExecutor()} may return null. Also, for job-specific
* decoration, see {@link BuildWrapper#decorateLauncher(AbstractBuild, Launcher, BuildListener)} as well.
*
* @param launcher
* The base launcher that you can decorate. Never null.
* @param node
* Node for which this launcher is created. Never null.
* @return
* Never null. Return the 'launcher' parameter to do no-op.
* @see Launcher#decorateFor(Node)
* @see Launcher#decorateByPrefix(String[])
*/
public abstract Launcher decorate(Launcher launcher, Node node);
/**
* Returns all the registered {@link LauncherDecorator}s.
*/
public static ExtensionList<LauncherDecorator> all() {
return Hudson.getInstance().getExtensionList(LauncherDecorator.class);
}
}
......@@ -44,6 +44,7 @@ import hudson.ExtensionList;
import hudson.ExtensionPoint;
import hudson.DescriptorExtensionList;
import hudson.ExtensionListView;
import hudson.LauncherDecorator;
import hudson.logging.LogRecorderManager;
import hudson.lifecycle.Lifecycle;
import hudson.model.Descriptor.FormException;
......@@ -891,7 +892,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
}
public Launcher createLauncher(TaskListener listener) {
return new LocalLauncher(listener);
return new LocalLauncher(listener).decorateFor(this);
}
private final transient Object updateComputerLock = new Object();
......
......@@ -93,6 +93,9 @@ public abstract class Node extends AbstractModelObject implements Describable<No
/**
* Returns a {@link Launcher} for executing programs on this node.
*
* <p>
* The callee must call {@link Launcher#decorateFor(Node)} before returning to complete the decoration.
*/
public abstract Launcher createLauncher(TaskListener listener);
......
......@@ -377,7 +377,7 @@ public abstract class Slave extends Node implements Serializable {
public Launcher createLauncher(TaskListener listener) {
SlaveComputer c = getComputer();
return new RemoteLauncher(listener, c.getChannel(), c.isUnix());
return new RemoteLauncher(listener, c.getChannel(), c.isUnix()).decorateFor(this);
}
/**
......
......@@ -27,6 +27,7 @@ import hudson.ExtensionPoint;
import hudson.Launcher;
import hudson.DescriptorExtensionList;
import hudson.FileSystemProvisionerDescriptor;
import hudson.LauncherDecorator;
import hudson.model.AbstractBuild;
import hudson.model.Build;
import hudson.model.BuildListener;
......@@ -168,6 +169,7 @@ public abstract class BuildWrapper implements ExtensionPoint, Describable<BuildW
* If a fatal error is detected but the implementation handled it gracefully, throw this exception
* to suppress stack trace.
* @since 1.280
* @see LauncherDecorator
*/
public Launcher decorateLauncher(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException, RunnerAbortedException {
return launcher;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册