詹金斯:在声明性詹金斯管道中 - 我可以动态设置代理标签吗? [英] Jenkins: In a declarative jenkins pipeline - can I set the agent label dynamically?

查看:20
本文介绍了詹金斯:在声明性詹金斯管道中 - 我可以动态设置代理标签吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法动态设置代理标签而不是纯字符串?

Is there a way to set the agent label dynamically and not as plain string?

作业有 2 个阶段:

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

我的(不工作)尝试看起来像这样:

My (not working) attempt looks like this:

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"的代理上运行,控制台打印:

The first echo works fine and "my_node_label" is printed. The second stage fails to run on an agent labeled "my_node_label" and the console prints:

没有标签为‘null’的节点

There are no nodes with the label ‘null’

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

Maybe it can help - if I just put "${env}" in the label field I can see that this is a java class as it prints:

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

There are no nodes with the label ‘org.jenkinsci.plugins.workflow.cps.EnvActionImpl@79c0ce06’

推荐答案

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

To see how this works, use a GString object to do a println and return the variable for the agentName at the same time. You can see from the output that this line evaluates well before any of the other pipeline code.

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 的节点,因此在找不到它后我中止了):

Console output (note that I don't actually have node on this instance labeled Windows, so I aborted after it couldn't find it):

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 行是如何在输出的早期出现的.这解释了为什么您的值为空.该语句在脚本修改变量之前很久就被评估了.

Notice how the line Right Now the Agent Name is Windows appears very early in the output. This explains why your value is null. That statement is evaluated long before your script modifies the variable.

我以后可能会尝试使用懒惰的 GString 来获取变量.

I might try to use a lazy GString to get the variable later.

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

不幸的是,这会引发错误,因为它期望的是 String 类型.显然它可以将非惰性 GString 强制转换为自身的字符串,但不能将惰性版本强制转换为字符串.因此,当我强制强制转换为 String 时,当然,它会评估当时的变量(这又是在管道代码实际运行之前).

Unfortunately, this throws an error because it is expecting a type of String. Apparently it can coerce the non-lazy GString to a String on its own, but not the lazy version. So when I force coercion to a String, of course, it evaluates the variable at that time (which is again, before the pipeline code actually runs).

agent { label agentLabel as String }

可以通过回退到旧的节点分配方式来解决问题:

You can solve the problem by falling back to the old node allocation method:

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 节点并完成了管道.早期评估而 agentName == Windows 永远不会发生:

You can see from this console output that it now properly finds the Linux node and finishes the pipeline. The early evaluation while agentName == Windows never happens:

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 和类型强制,这可能会起作用,但我没有尝试这样做.

This would probably work without the lazy GString and type coercion later, but I didn't try that.

这篇关于詹金斯:在声明性詹金斯管道中 - 我可以动态设置代理标签吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆