jenkinsci / jenkinsci/lockable-resources-plugin

Add documentation example on how to pass build arguments into the Groovy script

Open
#73 1 comment 0 reactions 0 assignees View on GitHub
documentation Triage
Dominant language
Java
Stars
99
Forks
205
Avg merge
2d 13h
Merged PRs (30d)
8

Description

Context: the Lockable Resources plugin includes an option to specify the needed resource by one of: exact resource name, matching a label, or evaluating a Groovy script for each configured resource that would return `true` if this resource is okay for this job. Then one of the "okay" resources (assuming "Number of resources to request" setting is 1) is reserved while the build runs.

My use-case, now solved by code in PR #72, is that we have a test farm, where usually any of the systems can be used for a test (so label-matching is in place), except when developers want to run the job against some particular system - and protect it from being used by any other job during this time. The build job (or actually a Multiphase job calling several others) has build arguments, including specification of the environment to use for the test (a "CONTROLLER" in examples below).

For the test, I used a build of the plugin with PR above integrated (made by `mvn package`), and in the job I selected "Meta Data / This build requires lockable resources", further selected "Groovy Expression" and entered the script below. The "Resources" and "Label" fields were left empty, and the "Number of resources to request" was set to `1` (disregard the warning that `Given amount 1 is greater than amount of resources: 0.`), and "Reserved resources variable name" is `LOCKED_CONTROLLER`.

Note the `println` lines below end up in `jenkins.log`, and can be pretty noisy, so comment them away when your job definition works well :)

````
// We need an available testbed resource marked with label "rc-validation-farm"
// If the user specified a particular testbed name in CONTROLLER var, require that one instead (regardless of labels)

/*
println "Inspecting the resource to lock for requested CONTROLLER='" +
CONTROLLER + "' (looking at resourceName='" + resourceName +
"' resourceDescription='" + resourceDescription + "' resourceLabels='"
+ resourceLabels + "')"
*/

if ( CONTROLLER.startsWith("LOCK_LABEL:") ) {
def LOCK_LABEL = (CONTROLLER =~ /^LOCK_LABEL:(.*?)$/ )[0][1];
/*
println "Looking for LOCK_LABEL='" + LOCK_LABEL + "' among '" +
resourceLabels + "' for '" + resourceName + "' (" + resourceDescription + ")"
*/
if (resourceLabels.contains( LOCK_LABEL )) {
// println "ACCEPTED '" + resourceName + "'"
return true;
}
} else {
// println "Looking for 'rc:" + CONTROLLER + "' in the name '" + resourceName + "'"
if (resourceName == ("rc:"+CONTROLLER) ) {
// println "ACCEPTED '" + resourceName + "'"
return true;
}
}

// println "Resource '" + resourceName + "' is not suitable for this job"
return false; // Tested resource is not appropriate for this build
````

The numerous corresponding lockable resource definitions in Manage Jenkins define a name (like `rc:controller1`) and labels (like `rc-validation-farm rc-model-3`), and sometimes comments about nuances of the controller model.

The job build parameter `CONTROLLER` is a predefined Global Choice Parameter, which includes the names like `controller1` that our devs can pick, and a default value of `LOCK_LABEL:rc-validation-farm`.

The script above was made generic enough to ease copy-pasting, so it reacts to the build arguments starting with `LOCK_LABEL:` and picks the rest of the string as the label to look for in resources; otherwise it would look for the requested resource name (with the prefix `rc:`).

As you could guess, there is a second side to the medal: the default `CONTROLLER` build argument is not usable as a definitive host name, so that build argument has to be replaced with the actually picked value :)

For this we use the EnvInject plugin, so in the job I further selected "Prepare an environment for the run" and entered an "Evaluated Groovy script" with:

````
def map = [:]

/*
println "Requested build arg CONTROLLER=='" + CONTROLLER +
"'; the locked resource == '" + LOCKED_CONTROLLER + "'";
*/

if ("LOCK_LABEL:rc-validation-farm".equals(CONTROLLER)) {
def CTLNAME = ( (LOCKED_CONTROLLER =~ /^rc:(.*?)$/)[0][1] )
println "Extracted CONTROLLER:='" + CTLNAME + "'"
map << [ CONTROLLER : CTLNAME ]
}

return map
````

(the script actually evaluates optional overrides for a few other variables as well, hence this structure and not a simpler one). Note that `println` here ends up in the build job's log.

Finally note, that for sub-jobs called from this one, you should also specify "Predefined parameters" including `CONTROLLER=${CONTROLLER}` so the one mapped above is in place for those jobs that would access it, and not the default token. The "Build on same node" and "Current build parameters" are useful for such cases as well :)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.