在声明性詹金斯管道中-我可以动态设置代理标签吗? [英] In a declarative jenkins pipeline - can I set the agent label dynamically?
问题描述
是否可以动态设置代理标签而不是设置为纯字符串?
Is there a way to set the agent label dynamically and not as plain string?
该工作分为两个阶段:
- 第一阶段-始终在主"代理上运行.在本阶段结束时,我将知道第二阶段应该在哪个代理上运行.
- 第二阶段-应在第一阶段确定的代理上运行.
我的(无效的)尝试如下:
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本身,但不能将其强制转换为String.因此,当我强制强制使用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节点并完成管道. Windows永远不会发生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屋!