当前位置: 首页 > 面试题库 >

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

牛枫
2023-03-14
问题内容

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

该工作分为两个阶段:

  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’的节点


问题答案:

要查看其工作原理,请使用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和类型强制,这可能会起作用,但是我没有尝试过。



 类似资料:
  • 我有bash脚本构建,标记和推docker图像到存储库。这是我的Jenkinsfile的一部分; 如何使用podTemplate执行我的步骤。当我使用docker容器进行阶段构建BMF后端时,我有这些错误; 无法连接到UNIX:///var/run/Docker.sock上的Docker守护进程。docker守护进程正在运行吗? /home/jenkins/workspace/bmf/bmf-we

  • 问题内容: 我正在使用声明性Jenkins管道来运行我的一些构建管道,并且想知道是否可以定义多个代理标签。 我有许多构建代理与我的Jenkins挂钩,并且希望此特定管道能够由具有不同标签的各种代理(但不能由ALL代理)构建。 更具体地说,假设我有2个代理,标签为“小”,4个为标签“中”,有6个为标签“大”。现在,我有一个非常节省资源的管道,我希望仅在“小型”或“中型”代理上执行,而不在大型代理上执

  • 问题内容: 我有一个简单的并行管道(请参阅代码),该管道与Jenkins 2.89.2一起使用。另外,我使用参数,现在希望能够通过在作业执行之前提供参数来自动增加/减少deployVM A..Z阶段的数量。 如何通过提供参数动态构建管道? 码 我想要的伪代码-动态生成: 到目前为止,我拥有的代码-可以并行执行,但是是静态的: 问题答案: 尽管该问题假定使用声明性管道,但我建议使用脚本化管道,因为它

  • 我有一个简单的并行管道(见代码),我和Jenkins 2.89.2一起使用。另外,我使用参数,现在希望能够通过在作业执行之前提供参数来自动地in-/减少deployVM A.Z阶段的数量。 null 到目前为止,我的代码是并行执行的,但是静态的:

  • 问题内容: 我当前正在尝试触发现有作业,并在当前作业的工作区中接收生成的工件。 以下工作正常: 问题是,这确实需要最后一次成功的构建,这意味着如果其他一些用户设法比我更快地运行并行构建,那么我将采用他们的工件而不是我的工件。 根据此页面 ,应该有一种使用特定作业的方法: 但是,没有关于如何在声明式管道中使用它的解释或示例。 有什么提示吗? 在此先感谢您的帮助。 问题答案: 我找到了一个不错的解决方

  • 问题内容: 已解决 :感谢S.Richmond的以下答复我需要取消所有类型的存储映射,这意味着将变量和使用后作废。 附加 :搜索此错误的人员可能有兴趣使用Jenkins管道步骤- 在此处查找更多信息。 我正在尝试使用Jenkins Pipeline从用户那里获取输入,该输入作为json字符串传递给作业。管道然后使用隔离器对此进行解析,然后选择重要信息。然后,它将使用该信息与不同的作业参数并行运行1