1

The code below uses Jenkins and Groovy with a call to parallel with two tasks which call a global method that takes a closure. The issue I have is that the parallel call does not use the correct variables. It works for the first job in the parallel call, but the second job ends up using the variables from the first job. I don't understand how this can happen, as the variables are named differently.

In the example below there are two jobs, A and B. A runs correctly with annotation A_POD_ROLE. But B runs incorrectly with annotation A_POD_ROLE!

If I run the two jobs independently like parallel(A); parallel(B); then it works (but the Blue Ocean UI doesn't look right).

Any ideas, please? Many Thanks!

String CONTAINER_IMAGE="ubuntu:1.2.3"
String A_POD_ROLE = "role_for_a" as String
String B_POD_ROLE = "role_for_b" as String

def withPodTemplate(String containerImage, String annotation, Closure closure) {
    podTemplate(podRetention: never(), label: "waf", inheritFrom: 'jnlp', cloud: 'kubernetes', containers: [
            containerTemplate(
                    name: 'devops',
                    image: containerImage,
                    ttyEnabled: true,
                    command: 'cat',
            )
    ],
            annotations: [
                    podAnnotation(
                            key: "the_role",
                            value: annotation
                    )
            ]) {
        node('mynode') {
          closure()
        }
    }
}

///////////////////////// MAIN /////////////////////////
parallel(
        "A": {
            withPodTemplate(CONTAINER_IMAGE, A_POD_ROLE) {
                stage('A: do stuff') {
                    container('devops') {
                    sh 'echo A-Stuff!'
                  }
                }
            }
        }
        "B": {
            withPodTemplate(CONTAINER_IMAGE, B_POD_ROLE) {
                stage('B: do stuff') {
                    container('devops') {
                    sh 'echo B-Stuff!'
                  }
                }
            }
        }
)
Ausin
  • 9
  • 2
Banoona
  • 1,470
  • 3
  • 18
  • 32

1 Answers1

0

The answer is to:

  • refactor the jobs into a map

  • use collectEntries inside the call to parallel as follows

     def jobs = [
             "A": {
             withPodTemplate(CONTAINER_IMAGE, A_POD_ROLE) {
                 stage('A: do stuff') {
                     container('devops') {
                     sh 'echo A-Stuff!'
                   }
                 }
             }
         }
         "B": {
             withPodTemplate(CONTAINER_IMAGE, B_POD_ROLE) {
                 stage('B: do stuff') {
                     container('devops') {
                     sh 'echo B-Stuff!'
                   }
                 }
             }
         }
    

    ]

    parallel(jobs.collectEntries{ [it.key, it.value ]})

I am not sure why this works, but possibly something to do with scope, closures, the def keyword (related to global versus local scope) and the way that parallel is designed in conjunction with the collectEntries method for lists?

Please see the following references:

Banoona
  • 1,470
  • 3
  • 18
  • 32