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

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

问题描述

是否可以动态设置代理标签而不是设置为纯字符串?

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

该工作分为两个阶段:

  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本身,但不能将其强制转换为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屋!

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