Egidijus
Egidijus

Reputation: 148

Jenkinsfile groovy, setting global variable that is only evaluated once, and creating another variable from first var

I have this code:

#!groovy
pipeline {
    agent any
    environment {
      def SUPER_VAR = sh(returnStdout: true, script: """openssl rand -base64 12""").trim()
      SUPER_VALUE = sh(returnStdout: true, script: """echo ${SUPER_VAR}""").trim()
      SUPER_DUPER_VALUE = sh(returnStdout: true, script: """echo ${SUPER_VAR}""").trim()
    }
    stages {
        stage("initialise") {
            steps {
              script {
                    sh "echo SUPER_VAR \${SUB_VAR}"
                    sh "echo SUPER_VALUE \${SUPER_VALUE}"
                    sh "echo SUPER_DUPER_VALUE \${SUPER_DUPER_VALUE}"
                    sh "env"
              }
            }
        }
    }
}

My desired output is, where each time I call / create a new var, the value is the same:

[Pipeline] { (initialise)
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ echo SUPER_VAR
SUPER_VAR
[Pipeline] sh
+ echo SUPER_VALUE FSDYe8VNL3VTvASj
SUPER_VALUE FSDYe8VNL3VTvASj
[Pipeline] sh
+ echo SUPER_DUPER_VALUE FSDYe8VNL3VTvASj
SUPER_DUPER_VALUE FSDYe8VNL3VTvASj
[Pipeline] sh

What happens in jenkins is this:

[Pipeline] { (initialise)
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ echo SUPER_VAR
SUPER_VAR
[Pipeline] sh
+ echo SUPER_VALUE FSDYe8VNL3VTvASj
SUPER_VALUE FSDYe8VNL3VTvASj
[Pipeline] sh
+ echo SUPER_DUPER_VALUE NSmVwW9xz6IPG5AO
SUPER_DUPER_VALUE NSmVwW9xz6IPG5AO
[Pipeline] sh

Every time I created a var based on SUPER_VAR it seems the script is ran again, and I get different output.

How does one register output of script in to a global var, so it can later be used to create new vars globally?

Upvotes: 1

Views: 711

Answers (2)

Catalin
Catalin

Reputation: 484

I cannot come with a better solution, but to use a singleton.

class Singleton {
    def static Value = 0
    def static GetRandomValue() {
        if(!Value)
            Value = Math.random()
        Value
    }
}

println Singleton.GetRandomValue()
println Singleton.GetRandomValue()

pipeline {
    agent any
    environment {
        SUPER_VAL1 = Singleton.GetRandomValue()
        SUPER_VAL2 = "$SUPER_VAL1"
        SUPER_VAL3 = "$SUPER_VAL2"
    }
    stages {
        stage("initialise") {
            steps {
              script {
                  bat "set SUPER"
              }
            }
        }
    }
}

I rewrote your script to use it on a Windows Jenkins, but for Linux it is the same idea. You need just to replace Math.random() with sh(returnStdout: true, script: """openssl rand -base64 12""").trim().

First call to Singleton.GetRandomValue() will initialize the value and any subsequent call to Singleton.GetRandomValue() will not call the random routine, but return the existing value.

Upvotes: 1

Egidijus
Egidijus

Reputation: 148

This is what I am using as a solution, I have to define vars in each stage, it looks dirty, but it works.

This way, the initial value SUPER_VAR will only be evaluated once, and subsequently we can use sub-elements of these vars.

My use case, I do not want to use more jenkins plugins to get aws sts assume. SUPER_VAR calls sts assume, and returns credentials, I run jq against it, and get a dictionary registered in SUPER_VAR.

In every stage I run jq to extract credentials for aws for sts assume to work.

#!groovy
pipeline {
    agent any
    environment {
      def SUPER_VAR = sh(returnStdout: true, script: """openssl rand -base64 12""").trim()

    }
    stages {
        stage("initialise") {
            environment {
                SUPER_VALUE = sh(returnStdout: true, script: """echo ${SUPER_VAR}""").trim()
                SUPER_DUPER_VALUE = sh(returnStdout: true, script: """echo ${SUPER_VAR}""").trim()
            }
            steps {
              script {
                    sh "echo SUPER_VAR \${SUB_VAR}"
                    sh "echo SUPER_VALUE \${SUPER_VALUE}"
                    sh "echo SUPER_DUPER_VALUE \${SUPER_DUPER_VALUE}"
                    sh "env"
              }
            }
        }
        stage("go again") {
            environment {
                SUPER_VALUE = sh(returnStdout: true, script: """echo ${SUPER_VAR}""").trim()
                SUPER_DUPER_VALUE = sh(returnStdout: true, script: """echo ${SUPER_VAR}""").trim()
            }
            steps {
              script {
                    sh "echo SUPER_VAR \${SUB_VAR}"
                    sh "echo SUPER_VALUE \${SUPER_VALUE}"
                    sh "echo SUPER_DUPER_VALUE \${SUPER_DUPER_VALUE}"
                    sh "env"
              }
            }
        }
    }
}

Upvotes: 1

Related Questions