Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
gboissinot committed Mar 18, 2012
1 parent efbc513 commit 257acc1
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 35 deletions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class EnvFileBuildWrapper extends EnvInjectMigrationBuildWrapper {


@Override @Override
public EnvInjectBuildWrapper getEnvInjectBuildWrapper() { public EnvInjectBuildWrapper getEnvInjectBuildWrapper() {
EnvInjectJobPropertyInfo jobPropertyInfo = new EnvInjectJobPropertyInfo(filePath, null, null, null, false); EnvInjectJobPropertyInfo jobPropertyInfo = new EnvInjectJobPropertyInfo(filePath, null, null, null, null, false);
EnvInjectBuildWrapper envInjectBuildWrapper = new EnvInjectBuildWrapper(); EnvInjectBuildWrapper envInjectBuildWrapper = new EnvInjectBuildWrapper();
envInjectBuildWrapper.setInfo(jobPropertyInfo); envInjectBuildWrapper.setInfo(jobPropertyInfo);
return envInjectBuildWrapper; return envInjectBuildWrapper;
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class SetEnvBuildWrapper extends EnvInjectMigrationBuildWrapper {


@Override @Override
public EnvInjectBuildWrapper getEnvInjectBuildWrapper() { public EnvInjectBuildWrapper getEnvInjectBuildWrapper() {
EnvInjectJobPropertyInfo jobPropertyInfo = new EnvInjectJobPropertyInfo(null, localVarText, null, null, false); EnvInjectJobPropertyInfo jobPropertyInfo = new EnvInjectJobPropertyInfo(null, localVarText, null, null, null, false);
EnvInjectBuildWrapper envInjectBuildWrapper = new EnvInjectBuildWrapper(); EnvInjectBuildWrapper envInjectBuildWrapper = new EnvInjectBuildWrapper();
envInjectBuildWrapper.setInfo(jobPropertyInfo); envInjectBuildWrapper.setInfo(jobPropertyInfo);
return envInjectBuildWrapper; return envInjectBuildWrapper;
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ public class EnvInjectJobPropertyInfo extends EnvInjectInfo {


private String scriptFilePath; private String scriptFilePath;
private String scriptContent; private String scriptContent;
private String groovyScriptContent;
private boolean loadFilesFromMaster; private boolean loadFilesFromMaster;


@DataBoundConstructor @DataBoundConstructor
public EnvInjectJobPropertyInfo(String propertiesFilePath, String propertiesContent, String scriptFilePath, String scriptContent, boolean loadFilesFromMaster) { public EnvInjectJobPropertyInfo(String propertiesFilePath, String propertiesContent, String scriptFilePath, String scriptContent, String groovyScriptContent, boolean loadFilesFromMaster) {
super(propertiesFilePath, propertiesContent); super(propertiesFilePath, propertiesContent);
this.scriptFilePath = Util.fixEmpty(scriptFilePath); this.scriptFilePath = Util.fixEmpty(scriptFilePath);
this.scriptContent = Util.fixEmpty(scriptContent); this.scriptContent = Util.fixEmpty(scriptContent);
this.groovyScriptContent = Util.fixEmpty(groovyScriptContent);
this.loadFilesFromMaster = loadFilesFromMaster; this.loadFilesFromMaster = loadFilesFromMaster;
} }


Expand All @@ -28,6 +30,10 @@ public String getScriptContent() {
return scriptContent; return scriptContent;
} }


public String getGroovyScriptContent() {
return groovyScriptContent;
}

public boolean isLoadFilesFromMaster() { public boolean isLoadFilesFromMaster() {
return loadFilesFromMaster; return loadFilesFromMaster;
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class EnvInjectListener extends RunListener<Run> implements Serializable
public Environment setUpEnvironment(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { public Environment setUpEnvironment(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
if (!(build instanceof MatrixBuild)) { if (!(build instanceof MatrixBuild)) {
EnvInjectLogger logger = new EnvInjectLogger(listener); EnvInjectLogger logger = new EnvInjectLogger(listener);
logger.info("Preparing an environment for the build.");
try { try {


//Process environment variables at node level //Process environment variables at node level
Expand All @@ -44,7 +45,7 @@ public Environment setUpEnvironment(AbstractBuild build, Launcher launcher, Buil


//Load job envinject job property //Load job envinject job property
if (isEnvInjectJobPropertyActive(build)) { if (isEnvInjectJobPropertyActive(build)) {
return setUpEnvironmentRun(build, launcher, listener); return setUpEnvironmentJobPropertyObject(build, launcher, listener);
} }
} catch (Run.RunnerAbortedException rre) { } catch (Run.RunnerAbortedException rre) {
logger.info("Fail the build."); logger.info("Fail the build.");
Expand Down Expand Up @@ -194,7 +195,7 @@ public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener l
} }
} }


private Environment setUpEnvironmentRun(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException, EnvInjectException { private Environment setUpEnvironmentJobPropertyObject(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException, EnvInjectException {


EnvInjectVariableGetter variableGetter = new EnvInjectVariableGetter(); EnvInjectVariableGetter variableGetter = new EnvInjectVariableGetter();
EnvInjectJobProperty envInjectJobProperty = variableGetter.getEnvInjectJobProperty(build); EnvInjectJobProperty envInjectJobProperty = variableGetter.getEnvInjectJobProperty(build);
Expand All @@ -203,7 +204,6 @@ private Environment setUpEnvironmentRun(AbstractBuild build, Launcher launcher,
assert envInjectJobProperty != null && envInjectJobProperty.isOn(); assert envInjectJobProperty != null && envInjectJobProperty.isOn();


EnvInjectLogger logger = new EnvInjectLogger(listener); EnvInjectLogger logger = new EnvInjectLogger(listener);
logger.info("Preparing an environment for the job.");


//Init infra env vars //Init infra env vars
Map<String, String> previousEnvVars = variableGetter.getEnvVarsPreviousSteps(build, logger); Map<String, String> previousEnvVars = variableGetter.getEnvVarsPreviousSteps(build, logger);
Expand Down Expand Up @@ -246,6 +246,9 @@ private Environment setUpEnvironmentRun(AbstractBuild build, Launcher launcher,
throw new Run.RunnerAbortedException(); throw new Run.RunnerAbortedException();
} }


//Evaluate Groovy script
Map<String, String> groovyMapEnvVars = envInjectEnvVarsService.executeAndGetMapGroovyScript(info.getGroovyScriptContent(), infraEnvVarsNode);

final Map<String, String> propertiesVariables = envInjectEnvVarsService.getEnvVarsPropertiesJobProperty(rootPath, final Map<String, String> propertiesVariables = envInjectEnvVarsService.getEnvVarsPropertiesJobProperty(rootPath,
logger, info.isLoadFilesFromMaster(), logger, info.isLoadFilesFromMaster(),
info.getPropertiesFilePath(), info.getPropertiesContentMap(), info.getPropertiesFilePath(), info.getPropertiesContentMap(),
Expand All @@ -254,7 +257,11 @@ private Environment setUpEnvironmentRun(AbstractBuild build, Launcher launcher,
//Get variables get by contribution //Get variables get by contribution
Map<String, String> contributionVariables = getEnvVarsByContribution(build, envInjectJobProperty, listener); Map<String, String> contributionVariables = getEnvVarsByContribution(build, envInjectJobProperty, listener);


final Map<String, String> resultVariables = envInjectEnvVarsService.getMergedVariables(infraEnvVarsNode, contributionVariables, propertiesVariables); final Map<String, String> resultVariables = envInjectEnvVarsService.getMergedVariables(
infraEnvVarsNode,
propertiesVariables,
groovyMapEnvVars,
contributionVariables);


//Add an action //Add an action
new EnvInjectActionSetter(rootPath).addEnvVarsToEnvInjectBuildAction(build, resultVariables); new EnvInjectActionSetter(rootPath).addEnvVarsToEnvInjectBuildAction(build, resultVariables);
Expand Down Expand Up @@ -324,26 +331,6 @@ private Map<String, String> getJenkinsSystemVariables(boolean onMaster) throws I
result.put("JENKINS_HOME", Hudson.getInstance().getRootDir().getPath()); result.put("JENKINS_HOME", Hudson.getInstance().getRootDir().getPath());
result.put("HUDSON_HOME", Hudson.getInstance().getRootDir().getPath()); // legacy compatibility result.put("HUDSON_HOME", Hudson.getInstance().getRootDir().getPath()); // legacy compatibility


//Global properties
for (NodeProperty<?> nodeProperty : Hudson.getInstance().getGlobalNodeProperties()) {
if (nodeProperty instanceof EnvironmentVariablesNodeProperty) {
EnvironmentVariablesNodeProperty environmentVariablesNodeProperty = (EnvironmentVariablesNodeProperty) nodeProperty;
result.putAll(environmentVariablesNodeProperty.getEnvVars());
}
}

//Node properties
if (computer != null) {
Node node = computer.getNode();
if (node != null) {
for (NodeProperty<?> nodeProperty : node.getNodeProperties()) {
if (nodeProperty instanceof EnvironmentVariablesNodeProperty) {
EnvironmentVariablesNodeProperty environmentVariablesNodeProperty = (EnvironmentVariablesNodeProperty) nodeProperty;
result.putAll(environmentVariablesNodeProperty.getEnvVars());
}
}
}
}
return result; return result;
} }


Expand Down
Original file line number Original file line Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jenkinsci.plugins.envinject.service; package org.jenkinsci.plugins.envinject.service;


import groovy.lang.GroovyShell;
import hudson.FilePath; import hudson.FilePath;
import hudson.Launcher; import hudson.Launcher;
import hudson.Util; import hudson.Util;
Expand Down Expand Up @@ -87,6 +88,38 @@ public int executeScript(boolean loadFromMaster,
} }
} }


public Map<String, String> executeAndGetMapGroovyScript(String scriptContent, Map<String, String> envVars) throws EnvInjectException {

if (scriptContent == null) {
return new HashMap<String, String>();
}

if (scriptContent.trim().length() == 0) {
return new HashMap<String, String>();
}

logger.info(String.format("Evaluation the following Groovy script content: \n%s\n", scriptContent));
GroovyShell shell = new GroovyShell();
for (Map.Entry<String, String> entryVariable : envVars.entrySet()) {
shell.setVariable(entryVariable.getKey(), entryVariable.getValue());
}
Object groovyResult = shell.evaluate(scriptContent);
if (groovyResult != null && !(groovyResult instanceof Map)) {
throw new EnvInjectException("The evaluated Groovy script must return a Map object.");
}

Map<String, String> result = new HashMap<String, String>();
if (groovyResult == null) {
return result;
}

for (Map.Entry entry : (((Map<Object, Object>) groovyResult).entrySet())) {
result.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
}
return result;

}

This comment has been minimized.

Copy link
@ndeloof

ndeloof Apr 24, 2013

Contributor

This method need to check for RUN_SCRIPT permission, as this code is ran on jenkins master: a malicious user with Job.CONFIGURE could set groovy script to access Jenkins.instance.XXX and bypass security

public int executeScript( public int executeScript(
String scriptContent, String scriptContent,
FilePath scriptExecutionRoot, FilePath scriptExecutionRoot,
Expand All @@ -101,21 +134,26 @@ public int executeScript(
} }


public Map<String, String> getMergedVariables(Map<String, String> infraEnvVars, Map<String, String> propertiesEnvVars) { public Map<String, String> getMergedVariables(Map<String, String> infraEnvVars, Map<String, String> propertiesEnvVars) {
return getMergedVariables(infraEnvVars, new HashMap<String, String>(), propertiesEnvVars); return getMergedVariables(infraEnvVars, propertiesEnvVars, new HashMap<String, String>(), new HashMap<String, String>());
} }


public Map<String, String> getMergedVariables(Map<String, String> infraEnvVars, public Map<String, String> getMergedVariables(Map<String, String> infraEnvVars,
Map<String, String> contribEnvVars, Map<String, String> propertiesEnvVars,
Map<String, String> propertiesEnvVars) { Map<String, String> groovyMapEnvVars,
Map<String, String> contribEnvVars) {


//1--Resolve properties against infraEnvVars //1--Resolve properties against infraEnvVars
resolveVars(propertiesEnvVars, infraEnvVars); resolveVars(propertiesEnvVars, infraEnvVars);


//2--Resolve properties against contribEnvVars //2--Resolve properties against groovyEnvVars
resolveVars(propertiesEnvVars, groovyMapEnvVars);

//3--Resolve properties against contribEnvVars
resolveVars(propertiesEnvVars, contribEnvVars); resolveVars(propertiesEnvVars, contribEnvVars);


//3-- Get All variables in order (infraEnvVars, contribEnvVars, properties) //4-- Get All variables in order (infraEnvVars, groovyEnvVars, contribEnvVars, properties)
Map<String, String> variables = new LinkedHashMap<String, String>(infraEnvVars); Map<String, String> variables = new LinkedHashMap<String, String>(infraEnvVars);
variables.putAll(groovyMapEnvVars);
variables.putAll(contribEnvVars); variables.putAll(contribEnvVars);
variables.putAll(propertiesEnvVars); variables.putAll(propertiesEnvVars);


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public int executeScriptSection(FilePath scriptExecutionRoot,


} }



return 0; return 0;
} }


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@
value="${instance.info.scriptContent}"/> value="${instance.info.scriptContent}"/>
</f:entry> </f:entry>


<f:entry title="${%Evaluated Groovy script}"
help="/descriptor/org.jenkinsci.plugins.envinject.EnvInjectJobProperty/help/groovyScriptContent">
<f:textarea
name="envInjectInfoJobProperty.groovyScriptContent"
value="${instance.info.groovyScriptContent}"/>
</f:entry>

<f:entry <f:entry
title="${%Properties File Path}" title="${%Properties File Path}"
help="/descriptor/org.jenkinsci.plugins.envinject.EnvInjectJobProperty/help/propertiesFilePath"> help="/descriptor/org.jenkinsci.plugins.envinject.EnvInjectJobProperty/help/propertiesFilePath">
Expand Down
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,27 @@
<div>
<p>
Evaluate a Groovy script and inject a map result.<br/>
The groovy script must return a map Java object.<br/>
You can access parameters and other environment variables through variables in the Groovy script.<br/>
For example, the Groovy can compute environment variables from user input parameters, such as:<br/>
<i>
if (CASE==null){<br/>
return null; <br/>
} <br/>

def stringValue="StRinG"; <br/>

if ("upper".equals(CASE)){ <br/>
def map = [COMPUTE_VAR: stringValue.toUpperCase()]<br/>
return map <br/>
} <br/>
<br/>
if ("lower".equals(CASE)){ <br/>
def map = [COMPUTE_VAR: stringValue.toLowerCase()] <br/>
return map <br/>
} <br/>
</i>
<br/>
This script injects the COMPUTE_VAR environment variable according the CASE parameter value.
</p>
</div>
Original file line number Original file line Diff line number Diff line change
@@ -1,6 +1,6 @@
<div> <div>
<p> <p>
Inject Jenkins build variables such as EXECUTOR_NUMBER, BUILD_ID, BUILD_TAG, JOB_NAME and so on. Inject Jenkins build variables such as EXECUTOR_NUMBER, BUILD_ID, BUILD_TAG, JOB_NAME and so on.<br/>
Inject also environment contributors and build variable contributors provided by other plugins. Inject also environment contributors and build variable contributors provided by other plugins.
</p> </p>
</div> </div>
3 changes: 2 additions & 1 deletion src/main/webapp/help.html
Original file line number Original file line Diff line number Diff line change
@@ -1,7 +1,8 @@
<div> <div>
<p> <p>
If this option is checked, Jenkins makes it possible to set an environment If this option is checked, Jenkins makes it possible to set an environment
for the build job (or for each run on a matrix project) by defining environment variables and execute a script (a setup script).<br/> for the build job (or for each run on a matrix project) by defining environment variables and execute a script
(a setup script).<br/>
All these actions will be executed before a SCM checkout.<br/> All these actions will be executed before a SCM checkout.<br/>
By default, after the set up, only injected variables (with Jenkins variables) will be available in the build By default, after the set up, only injected variables (with Jenkins variables) will be available in the build
scripts, in the Jenkins post-actions, and so on. <br/> scripts, in the Jenkins post-actions, and so on. <br/>
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public void testPropertiesContentCustomWorkspace() throws Exception {


String propertiesContent = customEnvVarName + "=" + customEnvVarValue; String propertiesContent = customEnvVarName + "=" + customEnvVarValue;


EnvInjectJobPropertyInfo jobPropertyInfo = new EnvInjectJobPropertyInfo(null, propertiesContent, null, null, false); EnvInjectJobPropertyInfo jobPropertyInfo = new EnvInjectJobPropertyInfo(null, propertiesContent, null, null, null, false);
EnvInjectBuildWrapper envInjectBuildWrapper = new EnvInjectBuildWrapper(); EnvInjectBuildWrapper envInjectBuildWrapper = new EnvInjectBuildWrapper();
envInjectBuildWrapper.setInfo(jobPropertyInfo); envInjectBuildWrapper.setInfo(jobPropertyInfo);
project.getBuildWrappersList().add(envInjectBuildWrapper); project.getBuildWrappersList().add(envInjectBuildWrapper);
Expand Down

0 comments on commit 257acc1

Please sign in to comment.