1

I have multipe Jenkins node agents, including "master", "tiering_agent1", and "cirrus". I am trying to set the node on which a Stage is executed by a parameters{} setting.

I have this pipeline code

def BuildAgentLabel='tiering_agent1'

pipeline {

    agent { label 'master' } 

    parameters { 
        string( 
            name:         'NEW_LABEL', 
            defaultValue: '',  
            description:  ''
        )
    }
    stages {
        stage( 'Init') {
            steps {
                script {
                    if ( params.NEW_LABEL != '' ){
                        echo "Setting BuildAgentLabel to '${params.NEW_LABEL}'" 
                        BuildAgentLabel = params.NEW_LABEL
                        echo "BuildAgentLabel is now '${BuildAgentLabel}'" 
                    } 
                } 
            }
        }
        stage( "Build") {
            agent { label BuildAgentLabel } 
            steps {
                echo "Performing Stage '${STAGE_NAME}' on NODE '${env.NODE_NAME}'"
                echo "BuildAgentLabel=${BuildAgentLabel}"
            }
        }
    }
}

Though the 'Init' stage sets the global variable BuildAgentLabel to a different value( if the NEW_LABEL parameters is a string with length > 0), the 'Build' stage always gets executed on whatever node the "def BuildAgentLabel" statement is originally set to.

The console output of the run echoes this:

[Pipeline] node
Running on Jenkins in ...
[Pipeline] {
.
.
.
[Pipeline] stage
[Pipeline] { (Init)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Setting BuildAgentLabel to 'master'
[Pipeline] echo
BuildAgentLabel is now 'master'
.
.
.
[Pipeline] stage
[Pipeline] { (Build)
[Pipeline] node
Running on tiering_agent1 in /opt/jenkins-agent/workspace/ine-multibranch-test_master-RGJIAQXOIAPL7XDIJW6DOGF4KUE5KBRXCAZ7U4IUW2YOTZVQTWCA
[Pipeline] {
.
.
.
[Pipeline] {
[Pipeline] echo
Performing Stage 'Build' on NODE 'tiering_agent1'
[Pipeline] echo
BuildAgentLabel=master
.
.
.
[Pipeline] End of Pipeline
Finished: SUCCESS

It's like the stage{} objects are instantiated almost concurrently and snag their agent label at that time, but stage execution comes after that.

I would like the 'Init' stage to be able to affect the node on which the 'Build' stage is performed upon, but cannot seem to make it work. How can I get the result I want?

StephenKing
  • 36,187
  • 11
  • 83
  • 112
jeffrotull
  • 13
  • 4

2 Answers2

0

The issue is agent { label BuildAgentLabel } doesn't resolve the variable BuildAgentLabel to it's value possibly due to this bug - https://issues.jenkins-ci.org/browse/JENKINS-9665 and I'm guessing your node agent 'tiering_agent1' is configured as Use this node as much as possible and it's defaulting to this agent.

However, setting label to the parameter directly works agent { label "${params.NEW_LABEL}" }

ben5556
  • 2,915
  • 2
  • 11
  • 16
0

If I'm not mistaken, you can't change a params item. At least, when I have tried, I get some kind of "static/inaccessible map" error. You can, however, change environment variables, as long as they have not been instantiated in a parent environment declarative (see this link for complete details). And I also believe that you can access any param.name variable as env.name, and that might be changeable. It might depend on the circumstance. If it's not, you can always set a new env var as the value of the incoming parameter, and that will definitely be mutable.

Max Cascone
  • 648
  • 9
  • 25