Skip to content

Commit

Permalink
Merge pull request #141 from timja/proxy-handling
Browse files Browse the repository at this point in the history
Fix sauce labs connection when running on agents
  • Loading branch information
alexh-sauce authored Dec 1, 2023
2 parents 2c54d7e + 5f023b0 commit 551e372
Show file tree
Hide file tree
Showing 13 changed files with 75 additions and 39 deletions.
37 changes: 27 additions & 10 deletions src/main/java/com/saucelabs/jenkins/pipeline/SauceConnectStep.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.saucelabs.jenkins.HudsonSauceManagerFactory;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.ProxyConfiguration;
import hudson.Util;
import hudson.model.Computer;
import hudson.model.Item;
Expand All @@ -21,11 +22,14 @@
import hudson.plugins.sauce_ondemand.SauceOnDemandBuildWrapper;
import hudson.plugins.sauce_ondemand.credentials.SauceCredentials;
import hudson.util.ListBoxModel;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import jenkins.model.Jenkins;
import jenkins.security.MasterToSlaveCallable;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.workflow.steps.BodyExecution;
Expand Down Expand Up @@ -66,7 +70,8 @@ public StepExecution start(StepContext context) throws Exception {
useGeneratedTunnelIdentifier,
verboseLogging,
sauceConnectPath,
useLatestSauceConnect
useLatestSauceConnect,
Jenkins.get().getProxy()
);
}

Expand Down Expand Up @@ -154,21 +159,23 @@ private static final class SauceStartConnectHandler extends MasterToSlaveCallabl
private final Boolean verboseLogging;
private final String sauceConnectPath;
private final Boolean useLatestSauceConnect;
private final ProxyConfiguration proxy;

SauceStartConnectHandler(SauceCredentials sauceCredentials, int port, String options, TaskListener listener, Boolean verboseLogging, String sauceConnectPath, Boolean useLatestSauceConnect) {
SauceStartConnectHandler(SauceCredentials sauceCredentials, int port, String options, TaskListener listener, Boolean verboseLogging, String sauceConnectPath, Boolean useLatestSauceConnect, ProxyConfiguration proxy) {
this.sauceCredentials = sauceCredentials;
this.port = port;
this.options = options;
this.listener = listener;
this.verboseLogging = verboseLogging;
this.sauceConnectPath = sauceConnectPath;
this.useLatestSauceConnect = useLatestSauceConnect;
this.proxy = proxy;
}

@Override
public Void call() throws AbstractSauceTunnelManager.SauceConnectException {
SauceConnectFourManager sauceTunnelManager = getSauceTunnelManager();
sauceTunnelManager.setSauceRest(sauceCredentials.getSauceREST());
sauceTunnelManager.setSauceRest(sauceCredentials.getSauceREST(proxy));
sauceTunnelManager.setUseLatestSauceConnect(useLatestSauceConnect);
sauceTunnelManager.openConnection(
sauceCredentials.getUsername(),
Expand All @@ -190,17 +197,19 @@ private static final class SauceStopConnectHandler extends MasterToSlaveCallable
private final SauceCredentials sauceCredentials;
private final String options;
private final TaskListener listener;
private final ProxyConfiguration proxy;

SauceStopConnectHandler(SauceCredentials sauceCredentials, String options, TaskListener listener) {
SauceStopConnectHandler(SauceCredentials sauceCredentials, String options, TaskListener listener, ProxyConfiguration proxy) {
this.sauceCredentials = sauceCredentials;
this.options = options;
this.listener = listener;
this.proxy = proxy;
}

@Override
public Void call() throws AbstractSauceTunnelManager.SauceConnectException {
SauceConnectFourManager sauceTunnelManager = getSauceTunnelManager();
sauceTunnelManager.setSauceRest(sauceCredentials.getSauceREST());
sauceTunnelManager.setSauceRest(sauceCredentials.getSauceREST(proxy));
sauceTunnelManager.closeTunnelsForPlan(
sauceCredentials.getUsername(),
options,
Expand All @@ -219,6 +228,7 @@ public static class SauceConnectStepExecution extends StepExecution {
private final boolean useLatestSauceConnect;

private static final long serialVersionUID = 1L;
private final ProxyConfiguration proxy;

private BodyExecution body;

Expand All @@ -229,7 +239,8 @@ public SauceConnectStepExecution(
boolean useGeneratedTunnelIdentifier,
boolean verboseLogging,
String sauceConnectPath,
boolean useLatestSauceConnect
boolean useLatestSauceConnect,
ProxyConfiguration proxy
) {
super(context);
this.globalOptions = globalOptions;
Expand All @@ -238,6 +249,7 @@ public SauceConnectStepExecution(
this.verboseLogging = verboseLogging;
this.sauceConnectPath = sauceConnectPath;
this.useLatestSauceConnect = useLatestSauceConnect;
this.proxy = proxy;
}

@Override
Expand Down Expand Up @@ -290,13 +302,14 @@ public boolean start() throws Exception {
listener,
verboseLogging,
sauceConnectPath,
useLatestSauceConnect
useLatestSauceConnect,
proxy
);
computer.getChannel().call(handler);

body = getContext().newBodyInvoker()
.withContext(EnvironmentExpander.merge(getContext().get(EnvironmentExpander.class), new ExpanderImpl(overrides)))
.withCallback(new Callback(sauceCredentials, options))
.withCallback(new Callback(sauceCredentials, options, proxy))
.withDisplayName("Sauce Connect")
.start();

Expand All @@ -320,10 +333,13 @@ private static final class Callback extends BodyExecutionCallback.TailCall {
private final String options;
private final SauceCredentials sauceCredentials;

private final ProxyConfiguration proxy;


Callback(SauceCredentials sauceCredentials, String options) {
Callback(SauceCredentials sauceCredentials, String options, ProxyConfiguration proxy) {
this.sauceCredentials = sauceCredentials;
this.options = options;
this.proxy = proxy;
}

@Override protected void finished(StepContext context) throws Exception {
Expand All @@ -333,7 +349,8 @@ private static final class Callback extends BodyExecutionCallback.TailCall {
SauceStopConnectHandler stopConnectHandler = new SauceStopConnectHandler(
sauceCredentials,
options,
listener
listener,
proxy
);
computer.getChannel().call(stopConnectHandler);
}
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/hudson/plugins/sauce_ondemand/BrowserAxis.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import hudson.matrix.MatrixBuild;
import hudson.matrix.MatrixProject;
import hudson.plugins.sauce_ondemand.credentials.SauceCredentials;
import jenkins.model.Jenkins;

import java.util.List;
import java.util.Map;

Expand All @@ -42,7 +44,7 @@
public abstract class BrowserAxis extends Axis {

/** Handles the retrieval of browsers from Sauce Labs. */
protected static final BrowserFactory BROWSER_FACTORY = BrowserFactory.getInstance(new JenkinsSauceREST(null, null, DataCenter.US_WEST));
protected static final BrowserFactory BROWSER_FACTORY = BrowserFactory.getInstance(new JenkinsSauceREST(null, null, DataCenter.US_WEST, Jenkins.get().getProxy()));

Check warning on line 47 in src/main/java/hudson/plugins/sauce_ondemand/BrowserAxis.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 47 is not covered by tests
private transient MatrixProject project;

public BrowserAxis(List<String> values) {
Expand Down
21 changes: 10 additions & 11 deletions src/main/java/hudson/plugins/sauce_ondemand/JenkinsSauceREST.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public class JenkinsSauceREST extends SauceREST {
"Jenkins/" + Jenkins.VERSION + " " + "JenkinsSauceOnDemand/" + BuildUtils.getCurrentVersion();
private String server = getSauceRestUrlFromEnv();

public JenkinsSauceREST(String username, String accessKey, DataCenter dataCenter) {
super(username, accessKey, dataCenter, getJenkinsPluginHttpConfig(dataCenter));
public JenkinsSauceREST(String username, String accessKey, DataCenter dataCenter, ProxyConfiguration proxy) {
super(username, accessKey, dataCenter, getJenkinsPluginHttpConfig(dataCenter, proxy));
if (server == null) {
server = dataCenter.server();
}
Expand All @@ -44,24 +44,23 @@ private static String getSauceRestUrlFromEnv() {
return srUrl;
}

private static HttpClientConfig getJenkinsPluginHttpConfig(DataCenter dataCenter) {
private static HttpClientConfig getJenkinsPluginHttpConfig(DataCenter dataCenter, ProxyConfiguration proxyConfig) {
String server = getSauceRestUrlFromEnv();
if (server == null) {
server = dataCenter.server();
}
Proxy proxy = null;
Authenticator auth = Authenticator.NONE;
ProxyConfiguration pc = Jenkins.get().getProxy();

if (pc != null) {
if (proxyConfig != null) {

Check warning on line 55 in src/main/java/hudson/plugins/sauce_ondemand/JenkinsSauceREST.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 55 is only partially covered, one branch is missing
String host = Objects.requireNonNull(buildURL(server)).getHost();
proxy = pc.createProxy(host);
proxy = proxyConfig.createProxy(host);

if (pc.getUserName() != null
&& !pc.getUserName().isEmpty()
&& pc.getSecretPassword() != null
&& !pc.getSecretPassword().getPlainText().isEmpty()) {
auth = new ProxyAuthenticator(pc.getUserName(), pc.getSecretPassword().getPlainText());
if (proxyConfig.getUserName() != null
&& !proxyConfig.getUserName().isEmpty()
&& proxyConfig.getSecretPassword() != null
&& !proxyConfig.getSecretPassword().getPlainText().isEmpty()) {
auth = new ProxyAuthenticator(proxyConfig.getUserName(), proxyConfig.getSecretPassword().getPlainText());

Check warning on line 63 in src/main/java/hudson/plugins/sauce_ondemand/JenkinsSauceREST.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 57-63 are not covered by tests
}
}
UserAgentInterceptor ua = new UserAgentInterceptor(userAgent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class PluginImpl extends Plugin implements Describable<PluginImpl> {

/** Handles the retrieval of browsers from Sauce Labs. */
static final BrowserFactory BROWSER_FACTORY =
BrowserFactory.getInstance(new JenkinsSauceREST(null, null, DataCenter.US_WEST));
BrowserFactory.getInstance(new JenkinsSauceREST(null, null, DataCenter.US_WEST, null));
private static final Logger logger = Logger.getLogger(PluginImpl.class.getName());
/** Username to access Sauce OnDemand. */
@Deprecated private transient String username;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.servlet.ServletException;

import jenkins.model.Jenkins;
import jenkins.model.RunAction2;
import jenkins.tasks.SimpleBuildStep;
import jenkins.util.Timer;
Expand Down Expand Up @@ -440,7 +442,7 @@ protected JenkinsSauceREST getSauceREST() {

DataCenter dc = DataCenter.fromString(dataCenter);

return new JenkinsSauceREST(username, accessKey, dc);
return new JenkinsSauceREST(username, accessKey, dc, Jenkins.get().getProxy());
}

public SauceTestResultsById getById(String id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import hudson.EnvVars;
import hudson.Extension;
import hudson.Launcher;
import hudson.ProxyConfiguration;
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
Expand Down Expand Up @@ -428,7 +429,9 @@ public Environment setUp(
credentials.getApiKey().getPlainText(),
dc,
maxRetries,
retryWaitTime);
retryWaitTime,
Jenkins.get().getProxy()
);

if (launchSauceConnectOnSlave) {
listener
Expand Down Expand Up @@ -684,7 +687,7 @@ public boolean tearDown(AbstractBuild build, BuildListener listener)
SauceCredentials.getSauceCredentials(
build, SauceOnDemandBuildWrapper.this); // get credentials
JenkinsSauceREST sauceREST =
credentials.getSauceREST(); // use credentials to get sauceRest
credentials.getSauceREST(Jenkins.get().getProxy()); // use credentials to get sauceRest

Check warning on line 690 in src/main/java/hudson/plugins/sauce_ondemand/SauceOnDemandBuildWrapper.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 690 is not covered by tests
SauceConnectEndpoint ep = sauceREST.getSauceConnectEndpoint();

if (isEnableSauceConnect() && isUseGeneratedTunnelIdentifier()) {
Expand Down Expand Up @@ -1103,7 +1106,8 @@ private static final class SauceConnectHandler
private final String username;
private final String key;
private final DataCenter dataCenter;
private final BuildListener listener;
private final ProxyConfiguration proxy;
private final BuildListener listener;
private final boolean verboseLogging;
private final String sauceConnectPath;
private int maxRetries;
Expand All @@ -1123,15 +1127,17 @@ public SauceConnectHandler(
String apiKey,
DataCenter dataCenter,
String maxRetries,
String retryWaitTime) {
String retryWaitTime,
ProxyConfiguration proxy) {
this.options = resolvedOptions;
this.workingDirectory = workingDirectory;
this.useLatestSauceConnect = useLatestSauceConnect;
this.listener = listener;
this.username = username;
this.key = apiKey;
this.dataCenter = dataCenter;
this.port = sauceOnDemandBuildWrapper.getPort(env);
this.proxy = proxy;
this.port = sauceOnDemandBuildWrapper.getPort(env);
this.verboseLogging = sauceOnDemandBuildWrapper.isVerboseLogging();
this.sauceConnectPath = sauceOnDemandBuildWrapper.getSauceConnectPath();
this.sauceConnectJar = sauceConnectJar;
Expand Down Expand Up @@ -1171,7 +1177,7 @@ public SauceConnectHandler call() throws AbstractSauceTunnelManager.SauceConnect
((HudsonSauceConnectFourManager) sauceTunnelManager)
.setUseLatestSauceConnect(useLatestSauceConnect);
}
sauceTunnelManager.setSauceRest(new JenkinsSauceREST(username, key, dataCenter));
sauceTunnelManager.setSauceRest(new JenkinsSauceREST(username, key, dataCenter, proxy));
if (StringUtils.isBlank(username)) {
listener.getLogger().println("Username not set, not starting Sauce Connect");
} else if (StringUtils.isBlank(key)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jenkins.model.Jenkins;
import org.json.JSONException;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
Expand Down Expand Up @@ -399,7 +401,7 @@ private boolean isDisableUsageStats() {
}

protected JenkinsSauceREST getSauceREST(Run build) {
return SauceOnDemandBuildAction.getSauceBuildAction(build).getCredentials().getSauceREST();
return SauceOnDemandBuildAction.getSauceBuildAction(build).getCredentials().getSauceREST(Jenkins.get().getProxy());

Check warning on line 404 in src/main/java/hudson/plugins/sauce_ondemand/SauceOnDemandReportPublisher.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 404 is not covered by tests
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.json.JSONException;
import org.kohsuke.stapler.DataBoundConstructor;
Expand All @@ -27,7 +29,7 @@ public class SauceParameterDefinition extends ParameterDefinition {
private static final Logger logger = Logger.getLogger(SauceParameterDefinition.class.getName());

/** Handles the retrieval of browsers from Sauce Labs. */
private static final BrowserFactory BROWSER_FACTORY = BrowserFactory.getInstance(new JenkinsSauceREST(null, null, DataCenter.US_WEST));
private static final BrowserFactory BROWSER_FACTORY = BrowserFactory.getInstance(new JenkinsSauceREST(null, null, DataCenter.US_WEST, Jenkins.get().getProxy()));

Check warning on line 32 in src/main/java/hudson/plugins/sauce_ondemand/SauceParameterDefinition.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 32 is not covered by tests

@DataBoundConstructor
public SauceParameterDefinition() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
public class SauceParameterValue extends ParameterValue {

/** Handles the retrieval of browsers from Sauce Labs. */
private static final BrowserFactory BROWSER_FACTORY = BrowserFactory.getInstance(new JenkinsSauceREST(null, null, DataCenter.US_WEST));
private static final BrowserFactory BROWSER_FACTORY = BrowserFactory.getInstance(new JenkinsSauceREST(null, null, DataCenter.US_WEST, null));

Check warning on line 20 in src/main/java/hudson/plugins/sauce_ondemand/SauceParameterValue.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 20 is not covered by tests

private final String selectedBrowsersString;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import jenkins.model.Jenkins;
import org.json.JSONException;

/** */
Expand Down Expand Up @@ -40,7 +42,10 @@ public SauceTestResultsById(String id, SauceCredentials credentials) {
new JenkinsSauceREST(
credentials.getUsername(),
credentials.getPassword().getPlainText(),
DataCenter.fromString(credentials.getRestEndpointName())));
DataCenter.fromString(credentials.getRestEndpointName()),
Jenkins.get().getProxy()

Check warning on line 46 in src/main/java/hudson/plugins/sauce_ondemand/SauceTestResultsById.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 45-46 are not covered by tests
)
);
}

public String getId() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.ProxyConfiguration;
import hudson.model.AbstractBuild;
import hudson.model.AbstractDescribableImpl;
import hudson.model.AbstractProject;
Expand Down Expand Up @@ -171,9 +172,9 @@ public static SauceCredentials getSauceCredentials(AbstractBuild build, SauceOnD
return getCredentialsById(build.getProject(), credentialId);
}

public JenkinsSauceREST getSauceREST() {
public JenkinsSauceREST getSauceREST(ProxyConfiguration proxy) {
DataCenter dc = DataCenter.fromString(getRestEndpointName());
JenkinsSauceREST sauceREST = new JenkinsSauceREST(getUsername(), getPassword().getPlainText(), dc);
JenkinsSauceREST sauceREST = new JenkinsSauceREST(getUsername(), getPassword().getPlainText(), dc, proxy);
return sauceREST;
}

Expand All @@ -193,7 +194,7 @@ public FormValidation doCheckApiKey(@QueryParameter String value, @QueryParamete

DataCenter dc = DataCenter.fromString(dataCenter);

JenkinsSauceREST rest = new JenkinsSauceREST(username, value, dc);
JenkinsSauceREST rest = new JenkinsSauceREST(username, value, dc, Jenkins.get().getProxy());

Check warning on line 197 in src/main/java/hudson/plugins/sauce_ondemand/credentials/SauceCredentials.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 197 is not covered by tests
AccountsEndpoint users = rest.getAccountsEndpoint();
// If unauthorized getUser returns an empty string.
try {
Expand Down
Loading

0 comments on commit 551e372

Please sign in to comment.