由于这个问题的答案,我最近了解了withCredentials
DSL。试图使用@RamKamath的答案,即以下Jenkinsfile:
pipeline {
agent any
stages {
stage( "1" ) {
steps {
script {
def credId = "cred_id_stored_in_jenkins"
withCredentials([usernamePassword(credentialsId: credId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
String url = "https://bitbucket.company.com/rest/build-status/1.0/commits"
String commit = '0000000000000000000000000000000000000001'
Map dict = [:]
dict.state = "INPROGRESS"
dict.key = "foo_002"
dict.url = "http://server:8080/blue/organizations/jenkins/job/detail/job/002/pipeline"
List command = []
command.add("curl -f -L")
command.add('-u ${username}:${password}')
command.add("-H \"Content-Type: application/json\"")
command.add("-X POST ${url}/${commit}")
command.add("-d \''${JsonOutput.toJson(dict)}'\'")
sh(script: command.join(' '))
}
}
}
}
}
}
…curl
命令本身因为报告的"错误请求"而失败。错误。这是Jenkins控制台输出的代码片段:
+ curl -f -L -u ****:**** -H "Content-Type:application/json" -X POST https://bitbucket.company.com/rest/build-status/1.0/commits/0000000000000000000000000000000000000001 -d '{"state":"INPROGRESS","key":"foo_002","url":"http://server:8080/blue/organizations/jenkins/job/detail/job/002/pipeline"}'
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 153 0 0 100 153 0 4983 --:--:-- --:--:-- --:--:-- 5100
curl: (22) The requested URL returned error: 400 Bad request
我理解-u ****:****
是-u
的掩码username:password参数。
如果我将该字符串复制/粘贴到shell中,并将掩码值替换为实际值,curl
命令工作:
$ curl -f -L -u super_user:super_password -H "Content-Type:application/json" -X POST https://bitbucket.company.com/rest/build-status/1.0/commits/0000000000000000000000000000000000000001 -d '{"state":"INPROGRESS","key":"foo_002","url":"http://server:8080/blue/organizations/jenkins/job/detail/job/002/pipeline"}'
$
怎么回事?为什么curl
命令会导致error 400
/"错误请求";当Jenkins执行它时,但同样的命令在手动执行时运行良好?
请注意:按照建议,我把-u ${username}:${password}
用单引号括起来,而不是双引号。
更新:我觉得好像字符串插值有问题,因为如果我修改Jenkinsfile以添加硬编码的用户名/密码,即
command.add('-u super_user:super_password')
…而不是
command.add('-u ${username}:${password}')
…那么curl
命令仍然像以前一样失败,即因为error: 400 Bad request
有人能帮我找出什么是错的,大概与命令汇编,和/或sh()
调用?
更新
我通过删除withCredentials()
简化了这个问题。甚至这个简化的curl
调用也失败了:
pipeline {
agent any
stages {
stage( "1" ) {
steps {
script {
def credId = "cred_id_stored_in_jenkins"
String url = "https://bitbucket.company.com/rest/build-status/1.0/commits"
String commit = '0000000000000000000000000000000000000001'
Map dict = [:]
dict.state = "INPROGRESS"
dict.key = "foo_002"
dict.url = "http://server:8080/blue/organizations/jenkins/job/detail/job/002/pipeline"
List command = []
command.add("curl -f -L")
command.add('-u super_user:super_password')
command.add("-H \"Content-Type: application/json\"")
command.add("-X POST ${url}/${commit}")
command.add("-d \''${JsonOutput.toJson(dict)}'\'")
sh(script: command.join(' '))
}
}
}
}
}
我尝试了你的脚本内联一个管道项目的改编:
pipeline {
agent any
stages {
stage( "1" ) {
steps {
script {
def username = '********' // my real jenkins user
def password = '********' // my real jenkins pwd
String url = "http://localhost:8083/api/json"
String commit = ""
List command = []
command.add("'C:/Program Files/Git/mingw64/bin/curl.exe' -f -L")
command.add("-u ${username}:${password}")
command.add('-H "Content-Type: application/json"') // no "..." string delimiters and escaping necessary
//command.add("-X POST ${url}/${commit}")
command.add("-X GET ${url}/${commit}") // GET instead
//command.add("-d \''${JsonOutput.toJson(dict)}'\'")
sh(script: command.join(' '))
}
}
}
}
}
控制台输出+ 'C:/Program Files/Git/mingw64/bin/curl.exe' -f -L -u ********:******** -H 'Content-Type: application/json' -X GET http://localhost:8083/api/json/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 3232 100 3232 0 0 42667 0 --:--:-- --:--:-- --:--:-- 43675{"_class":"hudson.model.Hudson","assignedLabels":[{"name":"master"}],"mode":"NORMAL","nodeDescription":"the master Jenkins node","nodeName":"","numExecutors":2,"description":null,"jobs":
...
我记得Jenkinsfile的转义和引号。
使用凭据绑定插件
stage( "curl withCredentials" ) {
steps {
script {
withCredentials([usernamePassword(
credentialsId: 'jenkins-user',
passwordVariable: 'password',
usernameVariable: 'username')]) {
String url = "http://localhost:8083/api/json"
String commit = ""
List command = []
command.add("'C:/Program Files/Git/mingw64/bin/curl.exe' -f -L")
command.add("-u ${username}:${password}")
command.add('-H "Content-Type: application/json"') // no "..." string delimiter and escaping necessary
//command.add("-X POST ${url}/${commit}")
command.add("-X GET ${url}/${commit}") // GET instead
//command.add("-d \''${JsonOutput.toJson(dict)}'\'")
sh(script: command.join(' '))
}
}
}
}
控制台输出+ 'C:/Program Files/Git/mingw64/bin/curl.exe' -f -L -u ****:**** -H 'Content-Type: application/json' -X GET http://localhost:8083/api/json/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 3231 100 3231 0 0 42247 0 --:--:-- --:--:-- --:--:-- 42513
100 3231 100 3231 0 0 42216 0 --:--:-- --:--:-- --:--:-- 42513{"_class":"hudson.model.Hudson","assignedLabels":[{"name":"master"}],"mode":"NORMAL","nodeDescription":"the master Jenkins node","nodeName":"","numExecutors":2,"description":null,"jobs":
...
这个问题原来是字符串转义问题。对我来说,有效的解决方案(包括withCredentials()
,这不是问题的一个因素)是:
pipeline {
agent any
stages {
stage( "1" ) {
steps {
script {
def credId = "cred_id_stored_in_jenkins"
String url = "https://bitbucket.company.com/rest/build-status/1.0/commits"
String commit = '0000000000000000000000000000000000000001'
withCredentials([usernamePassword(credentialsId: credId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
Map dict = [:]
dict.state = "INPROGRESS"
dict.key = "foo_002"
dict.url = http://server:8080/blue/organizations/jenkins/job/detail/job/002/pipeline"
def cmd = "curl -f -L" +
"-u ${username}:${password} " +
"-H "Content-Type: application/json" " +
"-X POST ${url}/${commit} "
"-d '${JsonOutput.toJson(dict)}'")
sh(script: cmd)
}
}
}
}
}
}
我确信List.join()
的一些变化会起作用-并且没有具体的原因我恢复使用+
来加入字符串,而不是我正在黑客攻击,并解决了刚刚工作的第一件事。在Jenkins中,转义字符串似乎是它自己的小地狱圈,所以我不想在那里花费更多的时间。
在这个过程中出现了一些奇怪的事情:
首先,在Windows与Unix/bash中行为似乎是不同的:@GeroldBroser(他的帮助是无价的)能够在他的Windows环境中获得一个工作解决方案,字符串转义更接近/与我原来的帖子相同;然而,我无法在我的Unix/bash环境中重现他的结果(Jenkinssh
调用在我的设置中使用bash)。
最后,我的印象是,记录到Jenkins作业控制台输出的文本是字面上的所执行的内容——但这似乎并不完全正确。
总结我与@GeroldBroser的部分评论讨论:curl
命令,当Jenkins运行error: 400 Bad request
失败时,但是如果我复制/粘贴/执行在bash shell中记录在我的Jenkins作业控制台输出中的curl
命令,它就成功了。
通过使用--trace-ascii /dev/stdout
选项到curl
,我能够发现curl
命令,当在bash中成功运行时,发送141个字节,但是当Jenkins运行失败时,发送143个字节:额外的2个字节是在JSON内容前后的'
(单引号)字符的前前后后。
这让我沿着疯狂的道路走向地狱的圈子,走向诅咒的城堡,走向疯狂的王座,那就是詹金斯串逃跑,我最终到达了上面的工作解决方案。
值得注意的是:有了这个工作解决方案,我不能再复制/粘贴curl
命令——正如我的Jenkins作业控制台输出中登录的那样——到bash shell并成功执行。因此,在Jenkins作业控制台输出中记录的与运行的并不总是正确的。(即复制/粘贴)在shell.">