Zdenik
Zdenik

Reputation: 526

Jenkinsfile pipeline.environment values excluded from env.getEnvironment()

(edited/updated from original post to attempt to address confusion about what the problem is)

The problem is: Values that are set in a Jenkinsfile environment section are not added to the object returned by env.getEnvironment()

The question is: How do I get a map of the complete environment, including values that were assigned in the environment section? Because env.getEnvironment() doesn't do that.

Example Jenkinsfile:

pipeline {
    agent any
    environment {
        // this is not included in env.getEnvironment()
        ONE = '1'
    }
    stages {
        stage('Init') {
            steps {
                script {
                    // this is included in env.getEnvironment()
                    env['TWO'] = '2'
                }
            }
        }
        stage('Test') {
            steps {
                script {
                    // get env values as a map (for passing to groovy methods)
                    def envObject = env.getEnvironment()
                    
                    // see what env.getEnvironment() looks like
                    // notice ONE is not present in the output, but TWO is
                    // ONE is set using ONE = '1' in the environment section above
                    // TWO is set using env['TWO'] = '2' in the Init stage above
                    println envObject.toString()
                    
                    // for good measure loop through the env.getEnvironment() map
                    // and print any value(s) named ONE or TWO
                    // only TWO: 2 is output
                    envObject.each { k,v ->
                        if (k == 'ONE' || k == 'TWO') {
                            println "${k}: ${v}"
                        }
                    }
                    
                    // now show that both ONE and TWO are indeed in the environment
                    // by shelling out and using the env linux command
                    // this outputs ONE=1 and TWO=2
                    sh 'env | grep -E "ONE|TWO"'
                }
            }
        }
    }
}

Output (output of envObject.toString() shortened to ... except relevant part):

[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Init)
[Pipeline] script
[Pipeline] {
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
[..., TWO:2]
[Pipeline] echo
TWO: 2
[Pipeline] sh
+ env
+ grep -E ONE|TWO
ONE=1
TWO=2
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline

Notice ONE is missing from the env.getEnvironment() object, but TWO is present.

Also notice that both ONE and TWO are set in the actual environment and I am not asking how to access the environment or how to iterate through the values returned by env.getEnvironment(). The issue is that env.getEnvironment() does not return all the values in the environment, it excludes any values that were set inside the environment section of the Jenkinsfile.

Upvotes: 1

Views: 662

Answers (3)

Samit Kumar Patel
Samit Kumar Patel

Reputation: 2098

Output of env.getEnvironment() method will not return a list or Map, Hence it's difficult to iterate with each but there are some workaround you can do to make this work.

import groovy.json.JsonSlurper
pipeline {
    agent any;
    environment { 
        ONE = 1
        TWO = 2
    }
    stages {
        stage('debug') {
            steps {
                script {
                    def jsonSlurper = new JsonSlurper()
                    def object = jsonSlurper.parseText(env.getEnvironment().toString())
                    assert object instanceof Map 
                    
                    object.each { k,v ->
                        echo "Key: ${k}, Value: ${v}"
                    } 
                }
            }
        }
    }
}

Note - env.getEnvironment().toString() will give you a JSON String . While parsing the JOSN string if groovy jsonSlurper.parseText found any special character it will through an error

You can also explore a little bit around env Jenkins API and find an appropriate method that will either return a Map or List so that you can use each

Upvotes: -1

Greg Biles
Greg Biles

Reputation: 941

I don't have a "why" answer for you, but you can cheat and get a map by parsing the output from env via the readProperties step.

def envMap = readProperties(text: sh(script: 'env', returnStdout: true))
println(envMap.getClass())
println("${envMap}")

Upvotes: 1

Ram
Ram

Reputation: 1224

I would get the env and convert it to map with the help of properties

pipeline {
agent any
environment {
    // this is not included in env.getEnvironment()
    ONE = '1'
}
stages {
    stage('Init') {
        steps {
            script {
                // this is included in env.getEnvironment()
                env['TWO'] = '2'
            }
        }
    }
    stage('Test') {
        steps {
            script {
            

                 def envProp = readProperties text: sh (script: "env", returnStdout: true).trim()
                 Map envMapFromProp = envProp as Map
                 echo "ONE=${envMapFromProp.ONE}\nTWO=${envMapFromProp.TWO}"


                // now show that both ONE and TWO are indeed in the environment
                // by shelling out and using the env linux command
                // this outputs ONE=1 and TWO=2
                sh 'env | grep -E "ONE|TWO"'
            }
        }
    }
}
}

Upvotes: 1

Related Questions