You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jenkins Active Choices插件中从Ansible Inventory动态提取主机名

Ansible Inventory与Jenkins Active Choices集成问题

我正在做Ansible和Jenkins的集成,需要从Ansible Inventory文件里动态提取主机名,用来填充Jenkins任务中Active Choices插件的选项。我写的脚本在Jenkins里作为独立任务执行正常,但放到插件里就失效了,不知道怎么调试插件里的脚本,也搞不清为啥在插件环境里执行失败,希望能得到调试思路和失败原因分析。

以下是我尝试的脚本:

properties([
    parameters([
        activeChoice(
            choiceType: 'PT_SINGLE_SELECT', 
            filterLength: 1, 
            filterable: false, 
            name: 'cloud', 
            randomName: 'choice-parameter-291132897896439385', 
            script: groovyScript(
                fallbackScript: [
                    classpath: [], 
                    oldScript: '', 
                    sandbox: false, 
                    script: ''
                ], 
            script: [
               classpath: [], 
               oldScript: '', 
               sandbox: false, 
               script: 
                  '''def getHostList(String envir, String envGroup) {
    node("slave-python") {
        
        def hosts = []
        checkout scmGit(branches: 
           [[name: \'*/master\']], 
           extensions: [
               cloneOption(
                   depth: 1, 
                   noTags: false, 
                   reference: \'\', 
                   shallow: true
                )
            ], 
            userRemoteConfigs: [
                [
                    credentialsId: \'jhgfghghf\', 
                    url: \'git@git.com:ansible/env.git\'
                ]
            ]
        )
        
        withCredentials([file(credentialsId: \'vault_file\', variable: \'ansibleVaultKeyFile\')]) {
            sh \'ls -lha\'
            
            String output = sh returnStdout: true, script: "ansible-inventory -i inventories/inventory.yml --list --vault-password-file ${ansibleVaultKeyFile}| jq -r \\'.[] | select(.hosts != null) | .hosts | .[]\\' | sort -u |grep \\"${envGroup}\\""
            
            hosts = output.trim().split(\'\\n\').collect { "\'${it}\'" }.join(\', \')
        }
        println("[$hosts]")
    
        return hosts.tokenize()
        
    }
}
return getHostList(\'env-test\', \'kuber\')''']))])])

我的目标是:

  1. 从Ansible Inventory中动态提取主机名;
  2. 将这些主机名用于填充Jenkins任务的Active Choices参数。

我有两个问题:

  1. 如何修改脚本以正确从Ansible Inventory提取主机名?
  2. 是否有更优的方法或插件可将Ansible Inventory主机名集成到Jenkins Active Choices中?

一、脚本修改与调试思路

1. 脚本问题修正

你的脚本存在几个导致在Active Choices中失效的核心问题,修改如下:

  • 移除node块:Active Choices参数初始化阶段无法分配Jenkins节点,直接调用node会触发异常。改用sh的label参数指定执行节点(需Jenkins版本支持),或确保依赖工具在主节点可用。
  • 修复字符串处理逻辑:原脚本中把主机名转成带单引号的字符串再tokenize(),会导致主机名被错误拆分。直接收集原始主机名到列表即可。
  • 添加调试输出与异常兜底:用println输出到Jenkins系统日志,同时设置兜底选项避免参数为空。

修改后的脚本示例:

properties([
    parameters([
        activeChoice(
            choiceType: 'PT_SINGLE_SELECT', 
            filterLength: 1, 
            filterable: false, 
            name: 'cloud', 
            randomName: 'choice-parameter-291132897896439385', 
            script: groovyScript(
                fallbackScript: [
                    classpath: [], 
                    oldScript: '', 
                    sandbox: false, 
                    script: 'return ["fallback-host"]'
                ], 
                script: [
                   classpath: [], 
                   oldScript: '', 
                   sandbox: false, 
                   script: '''
def getHostList(String envir, String envGroup) {
    def hosts = []
    // 用label指定执行节点,避免在参数阶段使用node块
    sh(
        label: "slave-python",
        script: 'rm -rf temp-inventory && git clone --depth 1 --branch master git@git.com:ansible/env.git temp-inventory'
    )
    
    withCredentials([file(credentialsId: 'vault_file', variable: 'ansibleVaultKeyFile')]) {
        String output = sh(
            returnStdout: true,
            label: "slave-python",
            script: '''
                cd temp-inventory
                ansible-inventory -i inventories/inventory.yml --list --vault-password-file ${ansibleVaultKeyFile} | jq -r '.[] | select(.hosts != null) | .hosts | .[]' | sort -u | grep "${envGroup}"
            '''
        )
        // 直接拆分并过滤空行,得到主机名列表
        hosts = output.trim().split('\\n').findAll { it != '' }
        // 输出到Jenkins系统日志用于调试
        println("Extracted hosts: ${hosts}")
    }
    
    // 清理临时目录
    sh(label: "slave-python", script: 'rm -rf temp-inventory')
    
    return hosts ?: ["no-hosts-found"]
}
return getHostList('env-test', 'kuber')
                   '''
                ]
            )
        )
    ])
])

2. 插件内脚本调试方法

  • 查看系统日志:脚本中的println内容会输出到Jenkins系统日志(路径:Manage Jenkins → System Log),可查看变量值和执行错误。
  • 测试fallback脚本:设置fallbackScript返回固定选项,判断是脚本逻辑问题还是插件环境问题。
  • 手动验证命令:在slave-python节点上手动执行ansible-inventory和jq命令,确认命令本身能正确输出主机名,排除工具依赖或权限问题。
  • 检查权限:确保Jenkins代理节点用户有权限访问Git仓库、Vault文件,以及执行ansible-inventory命令。

二、更优方案与替代插件

1. 优化集成逻辑

Active Choices参数阶段执行环境受限,更合理的做法是:

  • 提前缓存主机列表:用定时Jenkins任务定期提取Inventory主机名,保存到文件或Jenkins参数存储(如Extended Choice Parameter的预定义列表),Active Choices直接读取缓存内容。
  • Pipeline动态参数:在Pipeline的parameters块之前,先执行节点上的Inventory提取逻辑,再用input步骤或动态参数插件生成选项。

2. 替代插件

  • Ansible Plugin:直接解析Ansible Inventory文件,无需手动执行ansible-inventory命令,结合Groovy脚本即可提取主机名。
  • Dynamic Parameter Plugin:比Active Choices更轻量,支持从脚本、文件或外部命令生成参数选项,调试更直观。
  • Config File Provider Plugin:将Ansible Inventory作为配置文件管理,参数脚本直接读取解析,避免每次克隆Git仓库。

内容的提问来源于stack exchange,提问作者Stribog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 10:28:11