如何获取分配有包括主节点在内的标签的所有 Jenkins 节点的列表?

How to get a list of all Jenkins nodes assigned with label including master node?

我正在创建一个 Jenkins 管道作业,我需要 运行 在所有标有特定标签的节点上创建一个作业。

因此我试图获取分配有特定标签的节点名称列表。 (有了一个节点,我可以用 getAssignedLabels() 获得标签)

jenkins.model.Jenkins.instance.nodes 中的 nodes-list 似乎不包含我需要在搜索中包含的主节点。

我目前的解决方案是遍历 jenkins.model.Jenkins.instance.computers 并使用 getNode() 方法获取节点。这可行,但在 Jenkins 的 javadoc 中我正在阅读此列表可能不是最新的。

在长期运行我会添加(动态)云节点,我担心我将无法使用computers

获取当前所有节点列表的正确方法是什么?

这就是我现在正在做的事情:

@NonCPS
def nodeNames(label) {
    def nodes = []
    jenkins.model.Jenkins.instance.computers.each { c ->
        if (c.node.labelString.contains(label)) {
            nodes.add(c.node.selfLabel.name)
        }
    }   
    return nodes
}

尝试使用 for (aSlave in hudson.model.Hudson.instance.slaves) {}aSlave.getLabelString()); 获取所有节点的所有标签。您可以通过这种方式构建每个标签的节点列表。

我现在就是这样做的。我还没有找到其他任何东西:

@NonCPS
def hostNames(label) {
  def nodes = []
  jenkins.model.Jenkins.get().computers.each { c ->
    if (c.node.labelString.contains(label)) {
      nodes.add(c.node.selfLabel.name)
    }
  }
  return nodes
}

jenkins.model.Jenkins.get.computers 包含 master-node 和所有的奴隶。

我认为你可以这样做:

def nodes = Jenkins.get.getLabel('my-label').getNodes()
for (int i = 0; i < nodes.size(); i++) {
    node(nodes[i].getNodeName()) {
        // on node
    }
}

我不确定这是否适用于云节点。

@patrick-b 回答的更新:如果您有包含相同字符串的标签,则包含可能会出现错误,我添加了一个拆分步骤,检查每个用空格分隔的标签。

@NonCPS
def hostNames(label) {
    def nodes = []
    jenkins.model.Jenkins.get.computers.each { c ->
        c.node.labelString.split(/\s+/).each { l ->
            if (l != null && l.equals(label)) {
                nodes.add(c.node.selfLabel.name)
             }
        }
    }

    return nodes
}

更新的答案:在管道中使用 nodesByLabel 将所有节点分配给标签。

这是一个更易读和简洁的功能性解决方案:

def nodes = jenkins.model.Jenkins.get().computers
  .findAll{ it.node.labelString.contains(label) }
  .collect{ it.node.selfLabel.name }

你可以在Jenkins中验证一下Script Console

这是我的答案

String labelIWantServersOf = "XXXX"; // This is the label assosiated with nodes for which i want the server names of
List serverList = [];

for (aSlave in hudson.model.Hudson.instance.slaves) {          
  if (aSlave.getLabelString().indexOf(labelIWantServersOf ) > -1) {
     if(!aSlave.getComputer().isOffline() ){
          serverList.add(aSlave.name);        
     }
  }    
}

return serverList;

使用@towel 指出的nodesByLabel 可能是大多数情况下的解决方案。我发现 nodesByLabel 的一个限制是无法不加选择地 select 所有 节点。由于脚本安全性,我不能使用任何其他解决方案,其中一些可能非常危险,所以我宁愿不批准使用它们。

或者,您可以添加一个函数作为管道库,这将允许使用这些函数。由于可以设置流水线库,使它们完全处于管理员的控制之下,因此采用这种方式更为安全。为此,设置一个管道库(我认为它是否是全局的并不重要,但对我来说是)。然后在文件中添加以下内容vars/parallelRunOnNodes.groovy:

def call(Closure callback) {
    parallel jenkins.model.Jenkins.get().computers.collectEntries { agent ->
        def nodeLabel = agent.node.selfLabel.name
        ["${nodeLabel}": {
            node("${nodeLabel}") {
                stage("${nodeLabel}") {
                    callback(nodeLabel)
                }
            }
        }]
    }
}

然后可以按如下方式使用:

pipeline {
    agent none
    stages {
        stage('Parallel on all nodes') {
            steps {
                parallelRunOnNodes { nodeLabel ->
                    println(nodeLabel)
                }
            }
        }
    }
}

显然可以根据需要进行调整,例如你可以添加额外的参数来过滤,也许你不关心并行等

这是关于如何在 Jenkins 服务器上列出节点的 Google 热门文章之一。如果您只是寻找节点列表,可以在以下服务器URL:

查看
http://JENKINS_HOSTNAME:JENKINS_PORT/computer/

结果是 table 显示名称,OS,JVM 版本,时钟同步状态,远程处理版本和已知节点的响应时间。它还显示节点图像(嗯,JAR)是否明显过时或受到 error/security 警报。

如果无法访问 API 调用,URL 始终可以被抓取和解析以获取节点列表和 [=21= 中包含的任何其他数据].

获取节点 LabelsDisplay Name 的另一种方法

def jenkins = Jenkins.instance
def computers = jenkins.computers
computers.each {
   println "${it.displayName} ${it.hostName}"
}

def labels = jenkins.getLabels()
labels.each {
   println "${it.displayName}"
}