Groovy ArrayList not working in a Map under Jenkins - jenkins

The code below doesn't actaully add the element "asset" into the list associated in the Map map_masters. The code does compile and does not error when running. The value of the entry in the map is always empty. Hoping someone here on stackoverflow can see what the problems is, any help is appreciated.
Map map_masters = [:]
List nonAssignedAssets = _hardwareList.findAll{it.assigned_to == null}
List assignedAssets = _hardwareList.findAll{it.assigned_to != null}
if(assignedAssets != null && assignedAssets.size() > 0){
println("====> passed filters where size is: ${assignedAssets.size()}<===")}
for(asset in assignedAssets)
{
found = nonAssignedAssets.find{it->it.id == asset.assigned_to.id}
if(found == null)
{
found = assignedAssets.find{it->it.id == asset.assigned_to.id}
}
if(found != null)
{
if(map_masters[found] == null)
{
map_masters[found] = []
}
map_masters[found].value.add(asset)
println("assigned asset: ${map_masters[found].value.size()}")
}
}
return map_masters
The Map should contain lists of items associated to its key. I've tried just putting a string "hello" into the list but that doesn't work either.
I added the code this code:
if(map_masters[found] == null)
{
map_masters[found] = [asset]
}
else
{
map_masters[found].value.add(asset)
println("Just add another asset to existing list")
}
This is the pipeline print:
[Pipeline] echo
assigned asset: 1
[Pipeline] echo
assigned asset: 1
[Pipeline] echo
assigned asset: 1
[Pipeline] echo
Just add another asset to existing list
[Pipeline] echo
assigned asset: 1
When the add method is used it doesn't work, but if I initialize the array with a value that does work.

Related

The jenkins job is not continue after checking the if statement

stage('Checkout')
{
steps
{
checkout scm
script
{
if (params.myParam == '') { // and/or whatever condition you want
currentBuild.result = 'ABORTED'
error('myParam not set')
}
}
}
}
Above will Abort the build if parameter is null, working as expected.But when i give the value on parameter the job is still failing, not taking the value or passing the build.
The == '' (equality operator) also needs to be declared that it represents 'null' to satisfy the boolean value.
As this is not declared, any value in that parameter will meet the condition to error/false, see the slight change to your stage below:
stage('Checkout') {
steps {
checkout scm
script {
if(params.myParam == '' || params.myParam == null) {
currentBuild.result = 'ABORTED'
error('myParam not set')
} else {
//whatever condition you want
}
}
}
}

Jenkins groovy for loops behaving differently

My jenkins job looks like this:
class Device {
String name
Device(name) {
this.name = name
}
}
class globals {
static List<Device> devices = new ArrayList<Device>()
}
pipeline {
stages {
stage('test for loop') {
steps {
script {
addDevices()
def testStages = [:]
echo "TESTING REGULAR LOOP"
for(index=0; index < globals.devices.size(); index++) {
Device device = globals.devices.get(index)
echo "BEFORE TEST STAGES $device.name" //shows correct name
testStages["$device.name"] = { //correct name here
echo "INSIDE TEST STAGE $device.name" //works correctly
}
}
parallel testStages
}
}
}
stage('test for each loop') {
steps {
script {
def testStages = [:]
echo "TESTING FOR EACH LOOP"
for(Device device: globals.devices) {
echo "BEFORE $device.name" //shows correct name
testStages["$device.name"] = { //correct name here
echo "INSIDE TESTSTAGES: $device.name" //device name is always the last name in the list.
}
}
parallel testStages
}
}
}
}
}
void addDevices() {
globals.devices.add(new Device("a"))
globals.devices.add(new Device("b"))
}
The first loop works fine, it's a different device.name every time. However the second loop does not work, it prints the last item in the list. I really don't understand why. Would be really greatful if anyone can provide some insight.
The core of the problem is this:
int x = 1
def cls = { y -> x + y }
x = 2
println cls(3)
Output:
5
So the closure changes when the variable x changes. If you are using a normal for loop or the each method, every iteration creates a new instance of the variable (device in you case), but since the for-each loop uses iterators internally, the same variable is reused which is then used in the created closures. So only the last value of device counts in this case.

Getting OR to work properly on Jenkins Pipeline

I'm trying to disallow certain names to be used on a pipeline.
simply put: " If it is name1 or NAME1, ignore - otherwise, proceed"
But apparently it is not working properly. (still prints hello, according to the example)
It does work if I put "params.project != 'name1' || params.project != 'name1' " Which I really don't understand why.
What am I missing here ?
pipeline {
agent { label 'master'}
parameters {
string(defaultValue: '', description: '', name: 'project')
}
stages {
stage ('project stage') {
steps {
script {
if (params.project != 'name1' || params.project != 'NAME1')
println "Hello"
}
}
}
}
}
It is not duplicate of THIS since I'm trying to understand the logic behind this behavior.
In the end I went with
if (params.project!= 'name') {
if (params.project!= 'NAME1') {
}
}
But I believe there is a better way than that..
Update:
I found another way, which is to use contains
if (project.contains('name'))
If your objective is to disallow both values from being used for the project parameter, then you need the && logical operator ("and"):
if (params.project != 'name1' && params.project != 'NAME1')
This will prevent both values for the parameter as desired.
Alternatively, you could also use a regular expression similar to the following:
if !(params.project ==~ /name1|NAME1/) // =~ if instead do not want to additionally require type match

Multiple when clause inside single stage in Jenkins file

I want to put multiple when clause in a single stage. Here is the basic example
def foo = 0
pipeline {
agent any
stages {
stage('Hello') {
when {
expression {foo == 0}
}
steps {
echo 'foo is 0'
}
when {
expression {foo == 1}
}
steps {
echo 'foo is 1'
}
}
}
}
When I try this I recieve an error
Multiple occurrences of the when section
Actually my real problem is different but solving this will probably solve my real problem. Thanks in advance
It looks you'll be much better off using the directives as intended:
Multiple when is disallowed by design, if you looking a simple if else logic it's there:
Straghtforward if statement:
stage {
steps {
script {
if (foo == 0){
echo 'foo is 0'
}
else if (foo == 1){
echo 'foo is 1'
}
}
}
}
If you'd like to use nested conditions in when:
2. Here you go:
stage {
when {
anyOf {
environment name: 'VAR_1', value: '1'
branch 'production'
}
}
steps {
<your steps>
}

Bulk update parameter in jobs

We have a lot of jobs that all perform SCM checkout based on a Build Parameter value: say REPO_URL=ssh://url. Over time there accumulated small differences in names and values of these parameters: REPOURL, repo_url, =ssh://url/, =ssh://url:port, etc.
We need to reduce them to a common denominator with a single parameter name and a single value. How do we bulk update parameters in 50+ jobs?
Using Jenkins Script Console.
NOTE: these are essentially destructive operations, so make sure you tested your code on some spare jobs before running it in production!!!
Change default value of a parameter
Jenkins.instance.getAllItems(Job)
// filter jobs by name if needed
.findAll { it.fullName.startsWith('sandbox/tmp-magic') }
.each {
it
.getProperty(ParametersDefinitionProperty)
.getParameterDefinition('MAGIC_PARAMETER')
// `each` ensures nothing happens if `get` returns null; also see paragraph below
.each {
it.defaultValue = 'shmagic'
}
// the job has changed, but next config reload (f.x. at restart) will overwrite our changes
// so we need to save job config to its config.xml file
it.save()
}
Instead of .getParameterDefinition('MAGIC_PARAMETER') you can use
.parameterDefinitions
.findAll { it.name == 'MAGIC_PARAMETER' }
, changing predicate in findAll if you need f.x. to change value of multiple parameters with different names - then you iterate over found definitions via each{}.
Change parameter name (and value)
This is slightly more tricky, since apparently you cannot edit name of ParameterDefinition, only replace one in a list.
Jenkins.instance.getAllItems(Job)
.findAll { it.fullName.startsWith('sandbox/tmp-magic') }
.each {
def parameters = it.getProperty(ParametersDefinitionProperty).parameterDefinitions
def oldParameter = parameters.find { it.name == 'FOO' }
// avoid changing jobs without this parameter
if (!oldParameter)
return
def idx = parameters.indexOf(oldParameter)
// preserve original value if necessary
def oldValue = oldParameter.defaultValue
parameters[idx] = new StringParameterDefinition('GOOD_FOO', oldValue)
it.save()
}
Bonus points: replace value for SCM step in Freestyle and Pipeline From SCM job
Some of our jobs use MercurialSCM plugin, and some use MultiSCM plugin to checkout multiple repos, so this is what I tested it with.
import hudson.plugins.mercurial.MercurialSCM
import org.jenkinsci.plugins.multiplescms.MultiSCM
import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition
import org.jenkinsci.plugins.workflow.job.WorkflowJob
Jenkins.instance.getAllItems(Job)
.findAll { it.fullName.startsWith('sandbox/tmp-magic') }
.each {
print "Checking $it ... "
if (it.class == FreeStyleProject && it.scm) {
println "Freestyle"
it.scm = replaceWhateverScm(it.scm)
it.save()
} else if (it.class == WorkflowJob) {
print "Pipeline ... "
def flow = it.definition
if (flow.class == CpsScmFlowDefinition) {
println "ScmFlow"
def scm = replaceWhateverScm(flow.scm)
def newFlow = new CpsScmFlowDefinition(scm, flow.scriptPath)
newFlow.lightweight = flow.lightweight
it.definition = newFlow
it.save()
} else
println "unsupported definition"
} else
println "unsupported job"
}
def replaceWhateverScm(scm) {
if (scm.class == MercurialSCM) {
println "replacing MercurialSCM"
return replaceMercurialSource(scm)
}
if (scm.class == MultiSCM) {
println "replacing MultiSCM"
// cannot replace part of MultiSCM, replace whole scm instead
return new MultiSCM(
scm.configuredSCMs
.collect { (it.class == MercurialSCM) ? replaceMercurialSource(it) : it }
)
}
throw new Exception("unknown class ${scm.class}")
}
def replaceMercurialSource(MercurialSCM original) {
if (!original.source.toLowerCase().contains('repo_url'))
return original
def s = new MercurialSCM('<new_url>')
for (v in ["browser","clean","credentialsId","disableChangeLog","installation","modules","revision","revisionType","subdir",]) {
s."$v" = original."$v"
}
return s
}```

Resources