Jenkins动态用户输入使用JsonSlurper报错求助
解决Jenkins动态流水线镜像标签下拉选择的两个问题:解析失败与标签过滤
核心问题分析
你遇到的两个问题本质是:
- 云CLI命令输出非标准JSON(可能包含ANSI颜色码、日志前缀等冗余内容),导致
JsonSlurper解析失败 - 未从CLI输出中提取纯标签字段,导致下拉菜单显示完整镜像名
分步解决方案
1. 确保CLI输出纯净的JSON
首先检查你的云CLI命令是否支持输出JSON格式,绝大多数云厂商的CLI都提供--output json或-o json参数。如果输出仍包含冗余内容(比如颜色代码),用管道命令清理:
- 清理ANSI颜色码:
| sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" - 过滤仅保留JSON结构:
| grep -E '^\{|\[.*\]$'
以阿里云容器镜像服务CR为例,完整命令如下:
aliyun cr ListImageTags --RepoNamespace your-namespace --RepoName your-repo --output json | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | grep -E '^\{|\[.*\]$'
2. 安全解析JSON并提取纯标签
在Jenkinsfile中,先捕获清理后的CLI输出,再用JsonSlurper解析,最后提取标签字段(不同云厂商的JSON结构字段名不同,需调整)。
3. 动态生成纯标签下拉菜单
将提取的标签列表传入input步骤的choice参数,即可实现仅显示标签的下拉选择。
完整Jenkinsfile示例
pipeline { agent any environment { // 从Jenkins凭证中读取敏感信息,避免硬编码 ALIYUN_AK = credentials('aliyun-access-key-id') ALIYUN_SK = credentials('aliyun-access-key-secret') REPO_NAMESPACE = 'your-project' REPO_NAME = 'your-app-image' } stages { stage('Fetch Image Tags') { steps { script { // 1. 获取并清理CLI输出 def rawOutput = sh( script: """aliyun cr ListImageTags \ --RepoNamespace ${REPO_NAMESPACE} \ --RepoName ${REPO_NAME} \ --output json \ | sed -r "s/\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" \ | grep -E '^\{|\[.*\]$'""", returnStdout: true ).trim() // 2. 解析JSON并提取标签 def jsonParser = new groovy.json.JsonSlurper() def tagData = jsonParser.parseText(rawOutput) // 阿里云CR的标签在Tags数组的Tag字段,其他厂商需调整字段名 def tagList = tagData.Tags.collect { it.Tag } // 可选:去重并按语义化版本排序 tagList = tagList.unique().sort { a, b -> compareVersions(a, b) } // 3. 生成下拉选择框 def selectedTag = input( message: '选择要部署的镜像标签', parameters: [ choice( name: 'TARGET_TAG', choices: tagList.join('\n'), description: '可用镜像标签' ) ] ) // 保存选择结果到环境变量 env.SELECTED_TAG = selectedTag } } } stage('Deploy to Target Env') { steps { echo "部署镜像: ${REPO_NAMESPACE}/${REPO_NAME}:${env.SELECTED_TAG}" // 替换为你的部署命令,比如K8S部署 // sh "kubectl set image deployment/my-app app-container=${REPO_NAMESPACE}/${REPO_NAME}:${env.SELECTED_TAG}" } } } } // 辅助函数:语义化版本比较(可选) def compareVersions(String v1, String v2) { def parts1 = v1.split('\\.').collect { it.isInteger() ? it.toInteger() : it } def parts2 = v2.split('\\.').collect { it.isInteger() ? it.toInteger() : it } def minLen = Math.min(parts1.size(), parts2.size()) for (int i = 0; i < minLen; i++) { def p1 = parts1[i], p2 = parts2[i] if (p1 instanceof Integer && p2 instanceof Integer) { if (p1 != p2) return p1 < p2 ? -1 : 1 } else { def cmp = p1.compareTo(p2) if (cmp != 0) return cmp } } return parts1.size() < parts2.size() ? -1 : (parts1.size() > parts2.size() ? 1 : 0) }
注意事项
- 适配不同云厂商:替换CLI命令和JSON字段名,比如:
- 腾讯云CCR:用
tccli ccr DescribeImageTags --repo-namespace xxx --repo-name xxx --output json,标签字段为ImageTags数组的TagName - Harbor:用
curl -u ${HARBOR_USER}:${HARBOR_PWD} https://harbor.example.com/v2/${REPO_NAME}/tags/list | jq '.tags',直接取tags数组
- 腾讯云CCR:用
- 凭证安全:所有敏感信息(AK/SK、仓库账号密码)必须存在Jenkins凭证中,禁止硬编码
- 输出清理:如果你的CLI输出没有冗余内容,可去掉
sed和grep步骤
内容的提问来源于stack exchange,提问作者shank46
相关产品推荐
相关产品推荐

