一尘不染

在声明性詹金斯管道中-我可以动态设置代理标签吗?

jenkins

有没有一种方法可以动态设置代理标签而不是设置为纯字符串?

该工作分为两个阶段:

  1. 第一阶段-始终在“主”代理上运行。在本阶段结束时,我将知道第二阶段应在哪个代理上运行。
  2. 第二阶段-应在第一阶段决定的代理上运行。

我的(无效)尝试如下所示:

pipeline {
    agent { label 'master' }
    stages {
        stage('Stage1') {
            steps {
                script {
                    env.node_name = "my_node_label"
                }
                echo "node_name: ${env.node_name}"
            }
        }

        stage('Stage2') {
            agent { label "${env.node_name}" }
            steps {
                echo "node_name: ${env.node_name}"
            }
        }
    }
}

第一个回声可以正常工作,并打印“ my_node_label”。第二阶段无法在标有“ my_node_label”的代理上运行,控制台将输出:

没有标签为“ null”的节点

也许会有所帮助-如果我只是在标签字段中输入“ $ {env}”,则可以看到这是一个Java类,它可以打印:

没有标签为’org.jenkinsci.plugins.workflow.cps.EnvActionImpl@79c0ce06’的节点


阅读 404

收藏
2020-07-25

共1个答案

一尘不染

要查看其工作原理,请使用GString对象执行a
println并同时返回agentName的变量。您可以从输出中看到,该行在任何其他管道代码之前的评估效果都很好。

agentName = "Windows"
agentLabel = "${println 'Right Now the Agent Name is ' + agentName; return agentName}"

pipeline {
    agent none

    stages {
        stage('Prep') {
            steps {
                script {
                    agentName = "Linux"
                }
            }
        }
        stage('Checking') {
            steps {
                script {
                    println agentLabel
                    println agentName
                }
            }
        }
        stage('Final') {
            agent { label agentLabel }

            steps {
                script {
                    println agentLabel
                    println agentName
                }
            }
    }

    }
}

控制台输出(请注意,在此实例上我实际上没有节点标记为Windows,因此在找不到该节点后中止了操作):

Started by user Admin
[Pipeline] echo
Right Now the Agent Name is Windows
[Pipeline] stage
[Pipeline] { (Prep)
[Pipeline] script
[Pipeline] {
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Checking)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Windows
[Pipeline] echo
Linux
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Final)
[Pipeline] node
Still waiting to schedule task
There are no nodes with the label ‘Windows’
Aborted by Admin
[Pipeline] // node
[Pipeline] }
[Pipeline] // stage
[Pipeline] End of Pipeline
ERROR: Queue task was cancelled
Finished: ABORTED

请注意,该行在Right Now the Agent Name is Windows输出中很早就出现了。这说明了为什么您的值为空。在您的脚本修改变量之前很久就对该语句进行了评估。

我可能稍后会尝试使用惰性GString来获取变量。

agentLabel = "${-> println 'Right Now the Agent Name is ' + agentName; return agentName}"

不幸的是,这会引发错误,因为它期望使用String类型。显然,它可以自行将非惰性GString强制转换为String,而不是强制性版本。因此,当我强制强制使用String时,它会在那时(也就是在管道代码实际运行之前)对变量进行求值。

agent { label agentLabel as String }

您可以通过使用旧的节点分配方法来解决此问题:

agentName = "Windows"
agentLabel = "${-> println 'Right Now the Agent Name is ' + agentName; return agentName}"

pipeline {
    agent none

    stages {
        stage('Prep') {
            steps {
                script {
                    agentName = "Linux"
                }
            }
        }
        stage('Checking') {
            steps {
                script {
                    println agentLabel
                    println agentName
                }
            }
        }
        stage('Final') {

            steps {
                node( agentLabel as String ) {  // Evaluate the node label later
                    echo "TEST"
                }
                script {
                    println agentLabel
                    println agentName
                }
            }
        }
    }
}

您可以从此控制台输出中看到,它现在可以正确找到Linux节点并完成管道。Windows永远不会发生agentName == Windows的早期评估:

Started by user Admin
[Pipeline] stage
[Pipeline] { (Prep)
[Pipeline] script
[Pipeline] {
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Checking)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Right Now the Agent Name is Linux
[Pipeline] echo
Linux
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Final)
[Pipeline] echo
Right Now the Agent Name is Linux
[Pipeline] node
Running on Slave 1 in /home/jenkinsslave/jenkins/workspace/test
[Pipeline] {
[Pipeline] echo
TEST
[Pipeline] }
[Pipeline] // node
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Right Now the Agent Name is Linux
[Pipeline] echo
Linux
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] End of Pipeline
Finished: SUCCESS

如果没有延迟GString和类型强制,这可能会起作用,但是我没有尝试过。

2020-07-25