diff --git a/src/main/java/org/jenkinsci/plugins/workflow/steps/HttpProxyEnvStep.java b/src/main/java/org/jenkinsci/plugins/workflow/steps/HttpProxyEnvStep.java new file mode 100644 index 00000000..f6d8e5aa --- /dev/null +++ b/src/main/java/org/jenkinsci/plugins/workflow/steps/HttpProxyEnvStep.java @@ -0,0 +1,110 @@ +package org.jenkinsci.plugins.workflow.steps; + +import com.google.common.base.Joiner; +import hudson.EnvVars; +import hudson.Extension; +import hudson.ProxyConfiguration; +import jenkins.model.Jenkins; +import org.kohsuke.stapler.DataBoundConstructor; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; + +/** + * @author Robin Müller + */ +public class HttpProxyEnvStep extends Step { + + @DataBoundConstructor + public HttpProxyEnvStep() { + } + + @Override + public StepExecution start(StepContext context) throws Exception { + return new Execution(context); + } + + @Extension + public static class DescriptorImpl extends StepDescriptor { + + @Override + public String getFunctionName() { + return "withHttpProxyEnv"; + } + + @Override + public boolean takesImplicitBlockArgument() { + return true; + } + + @Override + public String getDisplayName() { + return "Set the global proxy settings as environment variables within a block"; + } + + @Override + public Set> getRequiredContext() { + return Collections.emptySet(); + } + + } + + public static class Execution extends AbstractStepExecutionImpl { + + private static final long serialVersionUID = 1; + + Execution(StepContext context) { + super(context); + } + + @Override + public boolean start() throws Exception { + StepContext context = getContext(); + context.newBodyInvoker() + .withContext(EnvironmentExpander.merge(context.get(EnvironmentExpander.class), new HttpProxyEnvironmentExpander())) + .withCallback(BodyExecutionCallback.wrap(context)) + .start(); + return false; + } + + @Override + public void stop(Throwable cause) throws Exception { + getContext().onFailure(cause); + } + + @Override + public void onResume() { + } + + } + + private static class HttpProxyEnvironmentExpander extends EnvironmentExpander { + @Override + public void expand(@Nonnull EnvVars envVars) throws IOException, InterruptedException { + ProxyConfiguration proxyConfiguration = Jenkins.getActiveInstance().proxy; + if (proxyConfiguration != null) { + Proxy proxy = proxyConfiguration.createProxy(null); + InetSocketAddress address = (InetSocketAddress) proxy.address(); + String proxyHost = "http://" + address.getHostName() + ":" + address.getPort(); + envVars.put("http_proxy", proxyHost); + envVars.put("https_proxy", proxyHost); + envVars.put("HTTP_PROXY", proxyHost); + envVars.put("HTTPS_PROXY", proxyHost); + List noProxyHosts = new ArrayList<>(); + for (Pattern noProxyHost : proxyConfiguration.getNoProxyHostPatterns()) { + noProxyHosts.add(noProxyHost.toString().replace("\\.", ".").replace(".*", "*")); + } + String noProxy = Joiner.on(',').join(noProxyHosts); + envVars.put("no_proxy", noProxy); + envVars.put("NO_PROXY", noProxy); + } + } + } +} diff --git a/src/main/resources/org/jenkinsci/plugins/workflow/steps/HttpProxyEnvStep/help.jelly b/src/main/resources/org/jenkinsci/plugins/workflow/steps/HttpProxyEnvStep/help.jelly new file mode 100644 index 00000000..24ca5f07 --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/workflow/steps/HttpProxyEnvStep/help.jelly @@ -0,0 +1,10 @@ + + + + Provides the global proxy settings as HTTP proxy environment variables
+ +
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/HttpProxyEnvStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/HttpProxyEnvStepTest.java new file mode 100644 index 00000000..a60a59ee --- /dev/null +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/HttpProxyEnvStepTest.java @@ -0,0 +1,66 @@ +package org.jenkinsci.plugins.workflow.steps; + +import hudson.ProxyConfiguration; +import hudson.model.Result; +import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; +import org.jenkinsci.plugins.workflow.job.WorkflowJob; +import org.jenkinsci.plugins.workflow.job.WorkflowRun; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; + +/** + * @author Robin Müller + */ +public class HttpProxyEnvStepTest { + + @Rule + public JenkinsRule jenkinsRule = new JenkinsRule(); + + @Test + public void test_proxy_not_set() throws Exception { + WorkflowJob job = jenkinsRule.jenkins.createProject(WorkflowJob.class, "workflow"); + job.setDefinition(new CpsFlowDefinition("withHttpProxyEnv { " + + " echo \"proxy: $env.http_proxy\" " + + "}", true)); + + WorkflowRun run = jenkinsRule.assertBuildStatus(Result.SUCCESS, job.scheduleBuild2(0).get()); + jenkinsRule.assertLogContains("proxy: null", run); + } + + @Test + public void test_proxy_set() throws Exception { + jenkinsRule.getInstance().proxy = new ProxyConfiguration("test", 8080); + + WorkflowJob job = jenkinsRule.jenkins.createProject(WorkflowJob.class, "workflow"); + job.setDefinition(new CpsFlowDefinition("withHttpProxyEnv { " + + " echo \"proxy: $env.http_proxy\" " + + "}", true)); + WorkflowRun run = jenkinsRule.assertBuildStatus(Result.SUCCESS, job.scheduleBuild2(0).get()); + jenkinsRule.assertLogContains("proxy: http://test:8080", run); + } + + @Test + public void test_noProxyHosts_not_set() throws Exception { + WorkflowJob job = jenkinsRule.jenkins.createProject(WorkflowJob.class, "workflow"); + job.setDefinition(new CpsFlowDefinition("withHttpProxyEnv { " + + " echo \"noProxyHosts: $env.no_proxy\" " + + "}", true)); + + WorkflowRun run = jenkinsRule.assertBuildStatus(Result.SUCCESS, job.scheduleBuild2(0).get()); + jenkinsRule.assertLogContains("noProxyHosts: null", run); + } + + @Test + public void test_noProxyHosts_set() throws Exception { + jenkinsRule.getInstance().proxy = new ProxyConfiguration("test", 8080, null, null, "test.tld\n*.test.tld"); + + WorkflowJob job = jenkinsRule.jenkins.createProject(WorkflowJob.class, "workflow"); + job.setDefinition(new CpsFlowDefinition("withHttpProxyEnv { " + + " echo \"noProxyHosts: $env.no_proxy\" " + + "}", true)); + + WorkflowRun run = jenkinsRule.assertBuildStatus(Result.SUCCESS, job.scheduleBuild2(0).get()); + jenkinsRule.assertLogContains("noProxyHosts: test.tld,*.test.tld", run); + } +}