1

(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.

Zdenik
  • 406
  • 1
  • 4
  • 13
  • Possible duplicate of https://stackoverflow.com/questions/37083285/how-to-list-all-env-properties-within-jenkins-pipeline-job – Ram Feb 17 '21 at 07:53
  • Does this answer your question? [How to list all \`env\` properties within jenkins pipeline job?](https://stackoverflow.com/questions/37083285/how-to-list-all-env-properties-within-jenkins-pipeline-job) – Ram Feb 17 '21 at 07:54
  • 1
    Thanks Ram, but it does not. The question isn't how to get env vars from a shell - that works just fine. what I need is to get all env values in a map so I can pass it into another groovy method. the problem is that env.getEnvironment() returns an "incomplete" map. It does not include values set in the environment section. i will update my question to be more clear – Zdenik Feb 19 '21 at 00:54

3 Answers3

1

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"'
            }
        }
    }
}
}
Ram
  • 1,154
  • 6
  • 22
1

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}")
Greg Biles
  • 941
  • 2
  • 10
  • 10
-1

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

Samit Kumar Patel
  • 1,932
  • 1
  • 13
  • 20
  • env.getEnvironment() returns an EnvVars class which derives from map: https://javadoc.jenkins.io/hudson/EnvVars.html . What kind of object env.getEnvironment() returns isn't the issue in any case. The issue is the env vars within the returned object does not include the values set inside the environment section. – Zdenik Feb 19 '21 at 00:23
  • Well now the question is more clearly after you edit. But not happy with your - vote , as your question before point how to use each on env and i was trying to explain one way – Samit Kumar Patel Feb 20 '21 at 07:56
  • I downvoted because what you said is wrong. env.getEnvironment() doesn't return a JSON object. It returns an EnvVars object which implements a Map interface. Calling toString() on it returns something that looks similar to JSON, but it's not - as your own comment about getting errors trying to parse it as json shows. – Zdenik Feb 25 '21 at 20:47