愿意在代理列表上运行清理脚本,而无需为每个代理创建单独的阶段

问题描述

问题陈述

我愿意在包含Linux OS的代理列表上运行清理脚本。 现在,该脚本已完成,我可以一次在一个代理上运行它,或者如果我愿意在几个代理上运行它,我需要复制“阶段”并在下面更改代理的名称标签”。有没有办法提高效率?能够创建“标签”列表并要求它同时在所有实例上并行运行它们?

尝试的解决方

我尝试使用stage{agent{label "x && y"}}stage{agent{label "x || y"}}。第一个结果是脚本说没有名为“ x && y”的标签,第二个则只运行了“ y”标签

当前管道代码

pipeline 
{
  agent none
  options { timestamps () }
  stages
  {
    stage('Cleaning up label1')
      {
        agent { 
          label "label1"
          }
        steps
          {
            echo "Cleaning up unused docker images from Jenkins Instance"
            sh "date +%Y%m%d-%H%M%s > datestamp.txt" 
            sh "docker system prune -a --volumes -f"
            echo "Cleaning up space from unused packages (orphaned dependencies),remove old kernels in Ubuntu"
            sh "sudo apt-get -y autoremove --purge"
            echo "clean the apt cache on Ubuntu"
            sh "sudo apt-get -y clean"
          }
      }
  stage('Cleaning up label2')
      {
        agent { 
          label "label2"
          }
        steps
          {
            echo "Cleaning up unused docker images from Jenkins Instance"
            sh "date +%Y%m%d-%H%M%s > datestamp.txt" 
            sh "docker system prune -a --volumes -f"
            echo "Cleaning up space from unused packages (orphaned dependencies),remove old kernels in Ubuntu"
            sh "sudo apt-get -y autoremove --purge"
            echo "clean the apt cache on Ubuntu"
            sh "sudo apt-get -y clean"
          }
      }
  }

解决方法

默认情况下,詹金斯(Jenkins)在单个节点上运行舞台。

如果您需要在多个节点上运行一个阶段(例如,“标签的所有实例”),则需要自己进行相应的编程。

这里有一个小功能,我们可以用来获取给定模式的所有在线节点(您可以修改此功能以查找标签):


@NonCPS
def getNodeNames(String some_pattern) {
    String[] ret_value = []
    for (Node node in Hudson.instance.nodes) {
        def nodeName = node.getNodeName()
        if (nodeName.equals(some_pattern) ||
            nodeName  ==~ '^' + some_pattern + '$') {
            if (node != null && node.toComputer() != null && node.toComputer().online) {
              ret_value += node.name 
            }
        } 
        node = null
    }
    return ret_value
}

以下是您可以以编程方式构建管道以在任意数量的节点(仅在运行时知道)上运行代码的方法:


def builders = [:].asSynchronized()

node('master') {
    stage('Prepare the Pipeline') {
        // get deploy pattern from params or something
        def node_names = getNodeNames(deploy_pattern)
        
        for (node_name in node_names) {
            // Groovy closures stuff,need to copy it over
            def final_node_name = node_name

            builders[final_node_name] = {
                node(final_node_name) {
                    timeout(time:5,unit: "MINUTES") {
                        // have your cleanups here
                    }
                }
            }
        }
    }
}

现在您在builders变量中有了阶段,您可以同时调用所有阶段:

pipeline {
    agent { node { label 'master'} }
    
    stages{
        stage ('Do the cleanup') {
            steps {
                script {
                    parallel builders
                }
            }
        }
    }
}