Use Object Returned by readYaml from file in Declarative Jenkinsfile

7/29/2019

I want to read the contents of a yaml file in a declarative Jenkinsfile via the readYaml utility. My understanding is that readYaml should return a Map, however, the object type I am seeing returned is a String. This defeats the purpose of putting the data in a yaml file in the first place.

Specifically, I want to get some values from a helm values.yaml file to set env values in the global environment section of the Jenkinsfile for all subsequent stages to be able to use.

The println valuesYaml.getClass() returns java.lang.String which I think is not correct because this object comes from a nested yaml file so I think the returned object should be a map.

https://jenkins.io/doc/pipeline/steps/pipeline-utility-steps/#readyaml-read-yaml-from-files-in-the-workspace-or-text

When the following echo statement runs echo valuesYaml.appName.toString() it errors out with the following error:

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: No such field found: field java.lang.String appName

This is a snippet of the values.yaml I'm trying to read:

replicaCount: 1
appName: test
def loadValuesYaml(){
  def valuesYaml = readYaml (file: './chart/values.yaml')
  return valuesYaml;
}

pipeline {
  agent {
    label "jenkins-maven"
  }

  environment {
    valuesYaml = loadValuesYaml()
  }
  stages {
    stage('CICD Initialize') {
      steps {
        script{
          echo valuesYaml
          println valuesYaml.getClass()
        }
        echo valuesYaml.appName.toString()
      }
    }
}
-- Amy Bachir
jenkins-groovy
kubernetes-helm
yaml

1 Answer

7/30/2019

You are setting your valuesYaml variable inside environment block, which makes it string. Move your variable declaration to script block, the variable will be accessible in subsequent stages.

def loadValuesYaml(){
  def valuesYaml = readYaml (file: './chart/values.yaml')
  return valuesYaml;
}

pipeline {
  agent {
    label "jenkins-maven"
  }
  stages {
    stage('CICD Initialize') {
      steps {
        script{
          valuesYaml = loadValuesYaml()
          println valuesYaml.getClass()
        }
      }
    }
    stage('Deploy') {
      steps {
        echo valuesYaml.appName
      }
    }
  }
}

Alternatively, if you want to declare them inside environment block, you can rewrite your loadValuesYaml function to return a specific string, however, this will call readYaml multiple times.

def loadValuesYaml(x){
  def valuesYaml = readYaml (file: './chart/values.yaml')
  return valuesYaml[x];
}

pipeline {
  agent {
    label "jenkins-maven"
  }
  environment {
    APP=loadValuesYaml('appName')
    REPLICACOUNT=loadValuesYaml('replicaCount')
  }
  stages {
    stage('CICD Initialize') {
      steps {
        script{
          println APP
          println REPLICACOUNT
        }
      }
    }
  }
}
-- edbighead
Source: StackOverflow