简体   繁体   English

如何在声明性管道中将并行作业限制为特定从属

[英]How to restrict parallel jobs to particular slaves in Declarative Pipeline

I have 3 nodes: A, B, C我有 3 个节点:A、B、C

On each of these nodes I set up a Jenkins slave with its own root directory They all have the following label: test && database && mysql在每个节点上,我设置了一个 Jenkins slave 和它自己的根目录它们都有以下标签:test && database && mysql

I want to run a job in parallel on all 3 nodes, to clean the workspace folder on them To achieve that, I wrote this Jenkins script我想在所有 3 个节点上并行运行一个作业,以清理它们上的工作区文件夹为此,我编写了这个 Jenkins 脚本

def labels = "test && mysql && database"

def getNodesName(labels){
    def targets = []
    def nodes = Jenkins.instance.getLabel(labels).getNodes()
    for(node in nodes){
        targets.add(node.getNodeName())
    }
    return targets
}

def nodes = getNodesName(labels)

def cleanWSTasks(targets){
    tasks = [:]
    for(target in targets){
        tasks[target] = {
            node(target){
                script {
                    cleanWs()
                }
            }
        }
    }
    return tasks
}

pipeline{
    agent none

    stages{

        stage ('Clean Workspace'){
            steps{
                script{
                    parallel cleanWSTasks(nodes)
                }
            }
        }

    }
}

So I thought with node(target) in the cleanWsTasks function I already told Jenkins to restrict the execution of the task only on the particular target node I want.所以我想在 cleanWsTasks 函数中使用 node(target) 我已经告诉 Jenkins 只在我想要的特定目标节点上限制任务的执行。 So that all 3 nodes will start cleaning their own workspaces at the same time.这样所有 3 个节点将同时开始清理自己的工作区。

However, what I see is that only 1 node picked up the task to cleanUp the workspace, and it does it 3 times.但是,我看到只有 1 个节点接受了清理工作区的任务,并且执行了 3 次。

For example, it shows:例如,它显示:

Running on node A in ...在节点 A 上运行...

clean up workspace ..清理工作区..

Running on node A in ...在节点 A 上运行...

clean up workspace ..清理工作区..

Running on node A in ...在节点 A 上运行...

clean up workspace ..清理工作区..

What did I do wrong in my code?我的代码做错了什么? Please help.请帮忙。

The node step is working correctly, the problem you're coming across has to do with how you're defining your tasks.节点步骤工作正常,您遇到的问题与您定义任务的方式有关。 In your for loop, you're assigning this closure:在你的 for 循环中,你分配了这个闭包:

          {
            node(target){
                script {
                    cleanWs()
                }
            }

to tasks[target] .tasks[target]

The code inside the closure won't get evaluated until you execute the closure.在您执行闭包之前,不会对闭包内的代码进行评估。 So even though you assign node(target) inside the for loop, target 's value won't get evaluated until parallel tasks runs, which is when the closure is executed.因此,即使您在 for 循环内分配node(target)parallel tasks运行之前也不会评估target的值,即执行闭包时。 That happens after the for loop has finished running and so target 's value is the name of the last node in your list of nodes.这发生在 for 循环完成运行之后,因此target的值是节点列表中最后一个节点的名称。

An easy fix for this is to create a variable in your for loop that's equal to target and use that inside the closure, because you will force the evaluation of target to happen inside your for loop, instead of when the closure runs.一个简单的解决方法是在你的 for 循环中创建一个等于 target 的变量,并在闭包中使用它,因为你将强制在 for 循环中对target进行评估,而不是在闭包运行时进行。 That would look like this:那看起来像这样:

def cleanWSTasks(targets){
    tasks = [:]
    for(target in targets){
        def thisTarget = target
        tasks[thisTarget] = {
            node(thisTarget){
                script {
                    cleanWs()
                }
            }
        }
    }
    return tasks
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM