Storing list of values in the environment variable in declarative Jenkins pipeline

2/13/2019

I've got the following pipeline but I don't know why it fails on the first line of code:

pipeline {
    agent any
    environment {
        def mypods = []
    }
    stages {
        stage('Getting pods') {
            steps {
                script {
                   withKubeConfig(caCertificate: '.....', credentialsId: '.....', serverUrl: '.....') {
                       env.mypods = sh "kubectl get pod | grep Running | awk '{print \$1}'"
                    }
                }
            }
        }
        stage('Print pods') {
            steps {
                script {
                    mypods.each {
                        println "Item: $it"
                    }
                }
            }
        }
    }
}

I need to use a list because the kubectl get pods command return a list of pods, so I have to save and use them during the stages. How can I create a list on declarative pipeline? Thanks in advance.

This is the error:

Running in Durability level: MAX_SURVIVABILITY
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 4: Environment variable values must either be single quoted, double quoted, or function calls. @ line 4, column 22.
           def mypods = []
                        ^

WorkflowScript: 3: No variables specified for environment @ line 3, column 5.
       environment {
       ^

2 errors

    at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
    at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1085)
    at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
    at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
    at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
    at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
    at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
    at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
    at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:131)
    at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:125)
    at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:560)
    at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:521)
    at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:320)
    at hudson.model.ResourceController.execute(ResourceController.java:97)
    at hudson.model.Executor.run(Executor.java:429)
Finished: FAILURE
-- carlo.zermo
devops
groovy
jenkins-pipeline
kubernetes

2 Answers

2/14/2019

The declarative pipeline comes with some limitations if it comes to its syntax. You see this error because in the environment block you can assign only two types of expressions:

  • strings (single or double quoted)
  • values returns from function calls

However, you need to be aware that the environment variables store only string values, so if you return an array (or any other type from) from the function call, it will be automatically converted to its toString() representation.

pipeline {
    agent any 

    environment {
        MYPODS = getPods()
    }

    stages {
        stage("Test") {
            steps {
                script {
                    println "My pods = ${env.MYPODS}"
                }
            }
        }
    }
}

def getPods() {
    return ['pod1', 'pod2']
}

Console output:

[Pipeline] node
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] script (hide)
[Pipeline] {
[Pipeline] echo
<java.lang.String@ed6c7b35 value=[pod1, pod2] hash=-311657675>
[Pipeline] echo
MYPODS = [pod1, pod2]
[Pipeline] echo
Item: [
[Pipeline] echo
Item: p
[Pipeline] echo
Item: o
[Pipeline] echo
Item: d
[Pipeline] echo
Item: 1
[Pipeline] echo
Item: ,
[Pipeline] echo
Item:  
[Pipeline] echo
Item: p
[Pipeline] echo
Item: o
[Pipeline] echo
Item: d
[Pipeline] echo
Item: 2
[Pipeline] echo
Item: ]
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

Solution

If you want to store a list of string values then you can define it as a single string of values delimited with , character. In this case you can simply tokenize it to a list of values. Consider the following example:

pipeline {
    agent any 

    environment {
        MYPODS = 'pod1,pod2,pod3'
    }

    stages {
        stage("Test") {
            steps {
                script {
                    MYPODS.tokenize(',').each {
                        println "Item: ${it}"
                    }
                }
            }
        }
    }
}

Output:

[Pipeline] node
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Item: pod1
[Pipeline] echo
Item: pod2
[Pipeline] echo
Item: pod3
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
-- Szymon Stepniak
Source: StackOverflow

2/13/2019

your environment should be after the agent

pipeline {

agent any
environment {
    def mypods = []
}
stages {
    stage('Getting pods') {
        steps {
            script {
               withKubeConfig(caCertificate: '.....', credentialsId: '.....', serverUrl: '.....') {
                    env.mypods = sh "kubectl get pod | grep Running | awk '{print \$1}'"
                }
            }
        }
    }
    stage('Print pods') {
        steps {
            script {
                mypods.each {
                    println "Item: $it"
                }
            }
        }
    }
}

}

-- mbn217
Source: StackOverflow