Skip to content
Permalink
Browse files

[JENKINS-32624] [JENKINS-27152] Use a standardized temporary director…

…y when possible.
  • Loading branch information
jglick committed Feb 29, 2016
1 parent c4d2197 commit d2e0f53b6eda56012c2bd5d9bc553b31667462a2
@@ -25,8 +25,11 @@
package com.cloudbees.jenkins.plugins.sshagent;

import hudson.ExtensionPoint;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.model.TaskListener;
import javax.annotation.CheckForNull;

/**
* Extension point for ssh-agent providers.
@@ -48,13 +51,25 @@
*/
public abstract boolean isSupported(Launcher launcher, TaskListener listener);

@Deprecated
public RemoteAgent start(Launcher launcher, TaskListener listener) throws Throwable {
return start(launcher, listener, null);
}

/**
* Start a ssh-agent on the specified launcher.
*
* @param launcher the launcher on which to start a ssh-agent.
* @param listener a listener for any diagnostics.
* @param temp a temporary directory to use; null if unspecified
* @return the agent.
* @throws Throwable if the agent cannot be started.
*/
public abstract RemoteAgent start(Launcher launcher, TaskListener listener) throws Throwable;
public /*abstract*/ RemoteAgent start(Launcher launcher, TaskListener listener, @CheckForNull FilePath temp) throws Throwable {
if (Util.isOverridden(RemoteAgentFactory.class, getClass(), "start", Launcher.class, TaskListener.class)) {
return start(launcher, listener);
} else {
throw new AbstractMethodError("you must implement the start method");
}
}
}
@@ -32,6 +32,7 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.model.AbstractBuild;
@@ -56,6 +57,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;
@@ -243,7 +245,7 @@ public Environment setUp(AbstractBuild build, final Launcher launcher, BuildList
private SSHAgentEnvironment createSSHAgentEnvironment(AbstractBuild build, Launcher launcher, BuildListener listener)
throws IOException, InterruptedException {
try {
return new SSHAgentEnvironment(launcher, listener);
return new SSHAgentEnvironment(launcher, listener, build.getWorkspace());
} catch (IOException e) {
throw new IOException2(Messages.SSHAgentBuildWrapper_CouldNotStartAgent(), e);
} catch (InterruptedException e) {
@@ -334,6 +336,11 @@ public SSHAgentEnvironment(Launcher launcher, final BuildListener listener,
}
}

@Deprecated
public SSHAgentEnvironment(Launcher launcher, final BuildListener listener) throws Throwable {
this(launcher, listener, (FilePath) null);
}

/**
* Construct the environment and initialize on the remote node.
*
@@ -342,15 +349,15 @@ public SSHAgentEnvironment(Launcher launcher, final BuildListener listener,
* @throws Throwable if things go wrong.
* @since 1.9
*/
public SSHAgentEnvironment(Launcher launcher, final BuildListener listener) throws Throwable {
public SSHAgentEnvironment(Launcher launcher, BuildListener listener, @CheckForNull FilePath workspace) throws Throwable {
RemoteAgent agent = null;
listener.getLogger().println("[ssh-agent] Looking for ssh-agent implementation...");
Map<String, Throwable> faults = new LinkedHashMap<String, Throwable>();
for (RemoteAgentFactory factory : Jenkins.getActiveInstance().getExtensionList(RemoteAgentFactory.class)) {
if (factory.isSupported(launcher, listener)) {
try {
listener.getLogger().println("[ssh-agent] " + factory.getDisplayName());
agent = factory.start(launcher, listener);
agent = factory.start(launcher, listener, workspace != null ? SSHAgentStepExecution.tempDir(workspace) : null);
break;
} catch (Throwable t) {
faults.put(factory.getDisplayName(), t);
@@ -4,9 +4,11 @@
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.google.inject.Inject;
import hudson.EnvVars;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.slaves.WorkspaceList;
import hudson.util.Secret;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;
@@ -32,6 +34,9 @@
@StepContextParameter
private transient Launcher launcher;

@StepContextParameter
private transient FilePath workspace;

@Inject(optional = true)
private SSHAgentStep step;

@@ -82,6 +87,11 @@ public void onResume() {
}
}

// TODO use https://github.com/jenkinsci/jenkins/pull/2066
static FilePath tempDir(FilePath ws) {
return ws.sibling(ws.getName() + System.getProperty(WorkspaceList.class.getName(), "@") + "tmp");
}

private static class Callback extends BodyExecutionCallback {

private static final long serialVersionUID = 1L;
@@ -149,7 +159,7 @@ private void initRemoteAgent() throws IOException {
if (factory.isSupported(launcher, listener)) {
try {
listener.getLogger().println("[ssh-agent] " + factory.getDisplayName());
agent = factory.start(launcher, listener);
agent = factory.start(launcher, listener, tempDir(workspace));
break;
} catch (Throwable t) {
faults.put(factory.getDisplayName(), t);
@@ -18,8 +18,7 @@
*/
package com.cloudbees.jenkins.plugins.sshagent.jna;

import java.security.PublicKey;
import java.util.List;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jnr.enxio.channels.NativeSelectorProvider;
import jnr.posix.POSIXFactory;
import jnr.unixsocket.UnixServerSocket;
@@ -41,12 +40,10 @@
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.sshd.common.util.Pair;
import javax.annotation.CheckForNull;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;

import static org.apache.sshd.agent.SshAgentConstants.SSH2_AGENTC_REQUEST_IDENTITIES;
import static org.apache.sshd.agent.SshAgentConstants.SSH2_AGENT_IDENTITIES_ANSWER;


/**
@@ -62,13 +59,15 @@
private UnixServerSocket socket;
private Selector selector;
private volatile boolean selectable = true;
private final @CheckForNull File temp;

public AgentServer() {
this(new AgentImpl());
public AgentServer(File temp) {
this(new AgentImpl(), temp);
}

public AgentServer(SshAgent agent) {
public AgentServer(SshAgent agent, File temp) {
this.agent = agent;
this.temp = temp;
}

public SshAgent getAgent() {
@@ -87,6 +86,9 @@ public String start() throws Exception {
channel.register(selector, SelectionKey.OP_ACCEPT, new SshAgentServerSocketHandler());

POSIXFactory.getPOSIX().chmod(authSocket, 0600);
if (!new File(authSocket).exists()) {
throw new IllegalStateException("failed to create " + authSocket + " of length " + authSocket.length() + " (check UNIX_PATH_MAX)");
}

thread = new Thread(new AgentSocketAcceptor(), "SSH Agent socket acceptor " + authSocket);
thread.setDaemon(true);
@@ -130,14 +132,22 @@ public void run() {
}
}

static String createLocalSocketAddress() throws IOException {
@SuppressFBWarnings(value="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE", justification="createTempFile will fail anyway if there is a problem with mkdirs")
private String createLocalSocketAddress() throws IOException {
String name;
if (temp != null) {
temp.mkdirs();
}
if (OsUtils.isUNIX()) {
File socket = File.createTempFile("jenkins", ".jnr");
File socket = File.createTempFile("ssh", "", temp);
if (socket.getAbsolutePath().length() >= /*UNIX_PATH_MAX*/108) {
LOGGER.log(Level.WARNING, "Cannot use {0} due to UNIX_PATH_MAX; falling back to system temp dir", socket);
socket = File.createTempFile("ssh", "");
}
FileUtils.deleteQuietly(socket);
name = socket.getAbsolutePath();
} else {
File socket = File.createTempFile("jenkins", ".jnr");
File socket = File.createTempFile("ssh", "", temp);
FileUtils.deleteQuietly(socket);
name = "\\\\.\\pipe\\" + socket.getName();
}
@@ -27,6 +27,7 @@
import com.cloudbees.jenkins.plugins.sshagent.Messages;
import com.cloudbees.jenkins.plugins.sshagent.RemoteAgent;
import hudson.model.TaskListener;
import java.io.File;
import org.apache.sshd.common.util.SecurityUtils;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
@@ -38,6 +39,7 @@
import java.io.IOException;
import java.io.StringReader;
import java.security.KeyPair;
import javax.annotation.CheckForNull;

/**
* An implementation that uses Apache SSH to provide the Agent over JNR's UnixSocket implementation.
@@ -62,9 +64,9 @@
* @param listener the listener.
* @throws Exception if the agent could not start.
*/
public JNRRemoteAgent(TaskListener listener) throws Exception {
public JNRRemoteAgent(TaskListener listener, @CheckForNull File temp) throws Exception {
this.listener = listener;
agent = new AgentServer();
agent = new AgentServer(temp);
socket = agent.start();
}

@@ -27,6 +27,7 @@
import com.cloudbees.jenkins.plugins.sshagent.RemoteAgent;
import com.cloudbees.jenkins.plugins.sshagent.RemoteAgentFactory;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.TaskListener;

@@ -57,8 +58,8 @@ public boolean isSupported(Launcher launcher, final TaskListener listener) {
* {@inheritDoc}
*/
@Override
public RemoteAgent start(Launcher launcher, final TaskListener listener) throws Throwable {
return launcher.getChannel().call(new JNRRemoteAgentStarter(listener));
public RemoteAgent start(Launcher launcher, final TaskListener listener, FilePath temp) throws Throwable {
return launcher.getChannel().call(new JNRRemoteAgentStarter(listener, temp != null ? temp.getRemote() : null));
}

}
@@ -30,6 +30,8 @@

import hudson.model.TaskListener;
import hudson.remoting.Channel;
import java.io.File;
import javax.annotation.CheckForNull;

/**
* Callable to start the remote agent.
@@ -47,20 +49,23 @@
*/
private final TaskListener listener;

private final @CheckForNull String tempDir;

/**
* Constructor.
*
* @param listener the listener to pass to the agent.
*/
public JNRRemoteAgentStarter(TaskListener listener) {
public JNRRemoteAgentStarter(TaskListener listener, String tempDir) {
this.listener = listener;
this.tempDir = tempDir;
}

/**
* {@inheritDoc}
*/
public RemoteAgent call() throws Throwable {
final JNRRemoteAgent instance = new JNRRemoteAgent(listener);
final JNRRemoteAgent instance = new JNRRemoteAgent(listener, tempDir != null ? new File(tempDir) : null);
final Channel channel = Channel.current();
return channel == null ? instance : channel.export(RemoteAgent.class, instance);
}
@@ -28,6 +28,7 @@
import com.cloudbees.jenkins.plugins.sshagent.RemoteAgentFactory;

import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.TaskListener;

@@ -64,7 +65,8 @@ public boolean isSupported(Launcher launcher, final TaskListener listener) {
* {@inheritDoc}
*/
@Override
public RemoteAgent start(Launcher launcher, final TaskListener listener) throws Throwable {
public RemoteAgent start(Launcher launcher, final TaskListener listener, FilePath temp) throws Throwable {
// TODO temp directory currently ignored
return launcher.getChannel().call(new MinaRemoteAgentStarter(listener));
}

0 comments on commit d2e0f53

Please sign in to comment.
You can’t perform that action at this time.