Skip to content

Commit

Permalink
JENKINS-47376: Fix global env variables
Browse files Browse the repository at this point in the history
  • Loading branch information
MattLud committed Dec 22, 2017
1 parent ec7d74f commit c0ee807
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public class ContainerExecDecorator extends LauncherDecorator implements Seriali
private static final String COOKIE_VAR = "JENKINS_SERVER_COOKIE";
private static final String JENKINS_HOME = "JENKINS_HOME=";
private static final Logger LOGGER = Logger.getLogger(ContainerExecDecorator.class.getName());
private final String [] builtInVars = new String[]{"BUILD_NUMBER","BUILD_ID","BUILD_URL","NODE_NAME","JOB_NAME","JENKINS_URL","BUILD_TAG","GIT_COMMIT","GIT_URL","GIT_BRANCH"};

private transient KubernetesClient client;

Expand All @@ -82,34 +83,38 @@ public class ContainerExecDecorator extends LauncherDecorator implements Seriali
private final String namespace;
private final String containerName;
private final EnvironmentExpander environmentExpander;
private final EnvVars globalVars;

public ContainerExecDecorator(KubernetesClient client, String podName, String containerName, String namespace, EnvironmentExpander environmentExpander) {
public ContainerExecDecorator(KubernetesClient client, String podName, String containerName, String namespace, EnvironmentExpander environmentExpander, EnvVars globalVars) {
this.client = client;
this.podName = podName;
this.namespace = namespace;
this.containerName = containerName;
this.environmentExpander = environmentExpander;
this.globalVars = globalVars;
}
public ContainerExecDecorator(KubernetesClient client, String podName, String containerName, String namespace, EnvironmentExpander environmentExpander) {
this(client, podName, containerName, namespace, environmentExpander, null);
}

public ContainerExecDecorator(KubernetesClient client, String podName, String containerName, String namespace) {
this(client, podName, containerName, namespace, null);
this(client, podName, containerName, namespace, null, null);
}

@Deprecated
public ContainerExecDecorator(KubernetesClient client, String podName, String containerName, AtomicBoolean alive, CountDownLatch started, CountDownLatch finished, String namespace) {
this(client, podName, containerName, namespace, null);
this(client, podName, containerName, namespace, null, null);
}

@Deprecated
public ContainerExecDecorator(KubernetesClient client, String podName, String containerName, AtomicBoolean alive, CountDownLatch started, CountDownLatch finished) {
this(client, podName, containerName, null, null);
this(client, podName, containerName, null);
}

@Deprecated
public ContainerExecDecorator(KubernetesClient client, String podName, String containerName, String path, AtomicBoolean alive, CountDownLatch started, CountDownLatch finished) {
this(client, podName, containerName, null, null);
this(client, podName, containerName, null);
}

@Override
public Launcher decorate(final Launcher launcher, final Node node) {
return new Launcher.DecoratedLauncher(launcher) {
Expand All @@ -118,18 +123,31 @@ public Proc launch(ProcStarter starter) throws IOException {
boolean quiet = starter.quiet();
FilePath pwd = starter.pwd();

String [] cmdEnvs = starter.envs();

//check if the cmd is sourced from Jenkins, rather than another plugin; if so, skip cmdEnvs as we are getting other environment variables
for (String cmd : cmdEnvs) {
if (cmd.startsWith(JENKINS_HOME)) {
cmdEnvs = new String[0];
LOGGER.info("Skipping injection of procstarter cmdenvs due to JENKINS_HOME present");
List<String> procStarter = Arrays.asList(starter.envs());
List<String> cmdEnvs = new ArrayList<String>();
//check if the cmd is sourced from Jenkins, rather than another plugin; if so, skip cmdEnvs except for built-in ones.
boolean javaHome_detected = false;
for(String env: procStarter)
{
if(env.contains("JAVA_HOME"))
{
javaHome_detected = true;
break;
}
for (String builtEnvVar : builtInVars) {
if(env.contains(builtEnvVar))
{
cmdEnvs.add(env);
}
}
}
if(!javaHome_detected)
{
cmdEnvs = procStarter;
}
String [] commands = getCommands(starter);
return doLaunch(quiet, cmdEnvs, starter.stdout(), pwd, commands);
return doLaunch(quiet, cmdEnvs.toArray(new String[cmdEnvs.size()]), starter.stdout(), pwd, commands);
}

private Proc doLaunch(boolean quiet, String [] cmdEnvs, OutputStream outputForCaller, FilePath pwd, String... commands) throws IOException {
Expand Down Expand Up @@ -223,6 +241,10 @@ public void onClose(int i, String s) {
String.format("cd \"%s\"%s", pwd, NEWLINE).getBytes(StandardCharsets.UTF_8));

}
//get global vars here, run the export first as they'll get overwritten.
if (globalVars != null) {
this.setupEnvironmentVariable(globalVars, watch);
}

EnvVars envVars = new EnvVars();
if (environmentExpander != null) {
Expand Down Expand Up @@ -432,3 +454,5 @@ public int getExitCode() {
}
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class ContainerExecProc extends Proc implements Closeable {
private final Callable<Integer> exitCode;

/**
*
*
* @param watch
* @param alive
* @param finished
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,17 @@
import org.jenkinsci.plugins.workflow.steps.StepContext;

import hudson.LauncherDecorator;
import hudson.slaves.EnvironmentVariablesNodeProperty;
import hudson.slaves.NodeProperty;
import hudson.slaves.NodePropertyDescriptor;
import hudson.util.DescribableList;
import io.fabric8.kubernetes.client.KubernetesClient;
import org.jenkinsci.plugins.workflow.steps.StepExecution;
import java.util.List;


import javax.annotation.Nonnull;
import jenkins.model.Jenkins;

import static org.csanchez.jenkins.plugins.kubernetes.pipeline.Resources.closeQuietly;

Expand Down Expand Up @@ -57,7 +64,14 @@ public boolean start() throws Exception {
client = nodeContext.connectToCloud();

EnvironmentExpander env = getContext().get(EnvironmentExpander.class);
decorator = new ContainerExecDecorator(client, nodeContext.getPodName(), containerName, nodeContext.getNamespace(), env);
EnvVars globalVars = null;
Jenkins instance = Jenkins.getInstance();
DescribableList<NodeProperty<?>, NodePropertyDescriptor>globalNodeProperties = instance.getGlobalNodeProperties();
List<EnvironmentVariablesNodeProperty> envVarsNodePropertyList = globalNodeProperties.getAll(EnvironmentVariablesNodeProperty.class);
if ( envVarsNodePropertyList != null && envVarsNodePropertyList.size() != 0 ) {
globalVars = envVarsNodePropertyList.get(0).getEnvVars();
}
decorator = new ContainerExecDecorator(client, nodeContext.getPodName(), containerName, nodeContext.getNamespace(), env, globalVars);
getContext().newBodyInvoker()
.withContext(BodyInvoker
.mergeLauncherDecorators(getContext().get(LauncherDecorator.class), decorator))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
import org.jvnet.hudson.test.LoggerRule;

import com.google.common.collect.ImmutableMap;
import hudson.EnvVars;
import hudson.slaves.EnvironmentVariablesNodeProperty;
import hudson.slaves.NodeProperty;
import hudson.slaves.NodePropertyDescriptor;
import hudson.util.DescribableList;

import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.api.model.SecretBuilder;
Expand All @@ -61,6 +66,7 @@ public class AbstractKubernetesPipelineTest {
protected static final String SECRET_KEY = "password";
protected static final String CONTAINER_ENV_VAR_FROM_SECRET_VALUE = "container-pa55w0rd";
protected static final String POD_ENV_VAR_FROM_SECRET_VALUE = "pod-pa55w0rd";
protected static final String GLOBAL = "GLOBAL";

@ClassRule
public static BuildWatcher buildWatcher = new BuildWatcher();
Expand Down Expand Up @@ -96,6 +102,14 @@ public void configureCloud() throws Exception {
JenkinsLocationConfiguration.get().setUrl(nonLocalhostUrl.toString());

r.jenkins.clouds.add(cloud);

DescribableList<NodeProperty<?>, NodePropertyDescriptor> list = r.jenkins.getGlobalNodeProperties();
list.getAll(hudson.slaves.EnvironmentVariablesNodeProperty.class);
EnvironmentVariablesNodeProperty newEnvVarsNodeProperty = new hudson.slaves.EnvironmentVariablesNodeProperty();
list.add(newEnvVarsNodeProperty);
EnvVars envVars = newEnvVarsNodeProperty.getEnvVars();
envVars.put("GLOBAL", "GLOBAL");
r.jenkins.save();
}

private PodTemplate buildBusyboxTemplate(String label) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public void declarative() throws Exception {
r.assertBuildStatusSuccess(r.waitForCompletion(b));
r.assertLogContains("Apache Maven 3.3.9", b);
r.assertLogContains("INSIDE_CONTAINER_ENV_VAR = " + CONTAINER_ENV_VAR_VALUE + "\n", b);
r.assertLogContains("OUTSIDE_CONTAINER_ENV_VAR = " + CONTAINER_ENV_VAR_VALUE + "\n", b);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ public void runWithEnvVariables() throws Exception {
assertNotNull(b);
r.assertBuildStatusSuccess(r.waitForCompletion(b));
assertEnvVars(r, b);
r.assertLogContains("OUTSIDE_CONTAINER_BUILD_NUMBER = 1\n", b);
r.assertLogContains("INSIDE_CONTAINER_BUILD_NUMBER = 1\n", b);
}

@Test
Expand Down Expand Up @@ -146,12 +148,15 @@ private void assertEnvVars(JenkinsRuleNonLocalhost r2, WorkflowRun b) throws Exc
r.assertLogContains("INSIDE_CONTAINER_ENV_VAR_FROM_SECRET = " + CONTAINER_ENV_VAR_FROM_SECRET_VALUE + "\n", b);
r.assertLogContains("INSIDE_POD_ENV_VAR = " + POD_ENV_VAR_VALUE + "\n", b);
r.assertLogContains("INSIDE_POD_ENV_VAR_FROM_SECRET = " + POD_ENV_VAR_FROM_SECRET_VALUE + "\n", b);
r.assertLogContains("INSIDE_GLOBAL = " + GLOBAL + "\n", b);

r.assertLogContains("OUTSIDE_CONTAINER_ENV_VAR =\n", b);
r.assertLogContains("OUTSIDE_CONTAINER_ENV_VAR_LEGACY =\n", b);
r.assertLogContains("OUTSIDE_CONTAINER_ENV_VAR_FROM_SECRET =\n", b);
r.assertLogContains("OUTSIDE_POD_ENV_VAR = " + POD_ENV_VAR_VALUE + "\n", b);
r.assertLogContains("OUTSIDE_POD_ENV_VAR_FROM_SECRET = " + POD_ENV_VAR_FROM_SECRET_VALUE + "\n", b);
r.assertLogContains("OUTSIDE_GLOBAL = " + GLOBAL + "\n", b);

}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ pipeline {
stages {
stage('Run maven') {
steps {
sh 'set'
sh "echo OUTSIDE_CONTAINER_ENV_VAR = ${CONTAINER_ENV_VAR}"
container('maven') {
sh 'echo INSIDE_CONTAINER_ENV_VAR = ${CONTAINER_ENV_VAR}'
sh 'mvn -version'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ node ('busybox') {
echo OUTSIDE_CONTAINER_ENV_VAR_FROM_SECRET = \$CONTAINER_ENV_VAR_FROM_SECRET
echo OUTSIDE_POD_ENV_VAR = \$POD_ENV_VAR
echo OUTSIDE_POD_ENV_VAR_FROM_SECRET = \$POD_ENV_VAR_FROM_SECRET
echo OUTSIDE_GLOBAL = \$GLOBAL
"""

stage('Run busybox') {
Expand All @@ -18,6 +19,7 @@ node ('busybox') {
echo INSIDE_CONTAINER_ENV_VAR_FROM_SECRET = \$CONTAINER_ENV_VAR_FROM_SECRET
echo INSIDE_POD_ENV_VAR = \$POD_ENV_VAR
echo INSIDE_POD_ENV_VAR_FROM_SECRET = \$POD_ENV_VAR_FROM_SECRET
echo INSIDE_GLOBAL = \$GLOBAL
"""
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,27 @@ podTemplate(label: 'mypod',
]) {

node ('mypod') {

sh """
echo OUTSIDE_CONTAINER_BUILD_NUMBER = \$BUILD_NUMBER
echo OUTSIDE_CONTAINER_ENV_VAR = \$CONTAINER_ENV_VAR
echo OUTSIDE_CONTAINER_ENV_VAR_LEGACY = \$CONTAINER_ENV_VAR_LEGACY
echo OUTSIDE_CONTAINER_ENV_VAR_FROM_SECRET = \$CONTAINER_ENV_VAR_FROM_SECRET
echo OUTSIDE_POD_ENV_VAR = \$POD_ENV_VAR
echo OUTSIDE_POD_ENV_VAR_FROM_SECRET = \$POD_ENV_VAR_FROM_SECRET
echo OUTSIDE_GLOBAL = \$GLOBAL
"""
stage('Run busybox') {
container('busybox') {
sh 'echo inside container'
sh """
echo INSIDE_CONTAINER_BUILD_NUMBER = \$BUILD_NUMBER
echo INSIDE_CONTAINER_ENV_VAR = \$CONTAINER_ENV_VAR
echo INSIDE_CONTAINER_ENV_VAR_LEGACY = \$CONTAINER_ENV_VAR_LEGACY
echo INSIDE_CONTAINER_ENV_VAR_FROM_SECRET = \$CONTAINER_ENV_VAR_FROM_SECRET
echo INSIDE_POD_ENV_VAR = \$POD_ENV_VAR
echo INSIDE_POD_ENV_VAR_FROM_SECRET = \$POD_ENV_VAR_FROM_SECRET
echo INSIDE_GLOBAL = \$GLOBAL
"""
}
}
Expand Down

0 comments on commit c0ee807

Please sign in to comment.