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

时间:2019-07-24 05:38:26

标签: parallel-processing jenkins-pipeline jenkins-plugins master-slave jenkins-slave

我有3个节点:A,B,C

在这些节点的每个节点上,我都设置了一个拥有自己根目录的Jenkins从属服务器 它们都具有以下标签:test && database && mysql

我想在所有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)
                }
            }
        }

    }
}

因此,我认为在cleanWsTasks函数中使用node(target)时,我已经告诉Jenkins将任务的执行限制在我想要的特定目标节点上。这样所有3个节点将同时开始清理自己的工作区。

但是,我看到的是只有1个节点拾取了任务以清理工作空间,并且执行了3次。

例如,它显示:

在...的节点A上运行

清理工作区..

在...的节点A上运行

清理工作区..

在...的节点A上运行

清理工作区..

我在代码中做错了什么?请帮忙。

1 个答案:

答案 0 :(得分:1)

节点步骤正常运行,遇到的问题与定义任务的方式有关。 在for循环中,您要分配此闭包:

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

tasks[target]

在执行闭包之前,闭包内部的代码不会得到评估。因此,即使您在for循环中分配了node(target)target的值也要到parallel tasks运行(闭包执行时)才会被求值。这是在for循环完成运行之后发生的,因此target的值是节点列表中最后一个节点的名称。

一个简单的解决方法是在for循环中创建一个与target相等的变量,并在闭包中使用该变量,因为您将强制target的求值发生在for循环中,而不是何时关闭运行。 看起来像这样:

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