如何使用标准Python库触发带文件参数的认证Jenkins任务
我们现在是通过一个Python脚本来触发Jenkins的任务,使用的是PycURL这个库。不过,我们想要去掉对PycURL的依赖,但到目前为止还没什么成功。让事情变得更复杂的是,我们需要把一个文件作为参数上传。我们现在用PycURL发送请求的代码大概是这样的:
url = "https://myjenkins/job/myjob/build"
with contextlib.closing(pycurl.Curl()) as curl:
curl.setopt(pycurl.URL, url)
curl.setopt(pycurl.USERPWD, "myuser:mypassword")
curl.setopt(pycurl.SSL_VERIFYPEER, False)
curl.setopt(pycurl.SSL_VERIFYHOST, False)
curl.setopt(pycurl.FAILONERROR, True)
data = [
("name", "integration.xml"),
("file0", (pycurl.FORM_FILE, "integration.xml")),
("json", "{'parameter': [{'name': 'integration.xml', 'file': 'file0'}]}"),
("Submit", "Build"),
]
curl.setopt(pycurl.HTTPPOST, data)
try:
curl.perform()
except pycurl.error, err:
raise JenkinsTriggerError(curl.errstr())
我们想知道怎么用Python标准库里的工具来替代这个方法。
我们之前尝试过,但因为不知道怎么成功上传文件,所以最后放弃了。你可以在我关于这个问题的提问中看到相关内容。
7 个回答
6
如果你对Python有点了解,可以使用官方提供的Jenkins REST API的Python封装库。可以查看这个链接。
通过这个Python封装库触发构建非常简单。下面是我的一个例子:
#!/usr/bin/python
import jenkins
if __name == "main":
j = jenkins.Jenkins(jenkins_server_url, username="youruserid", password="yourtoken")
j.build_job(yourjobname,{'param1': 'test value 1', 'param2': 'test value 2'},
{'token': "yourtoken"})
对于那些不知道在哪里找到令牌的人,这里有个方法:
登录Jenkins -> 点击网页顶部的你的用户名 -> 配置 -> 显示API令牌...
祝你使用愉快。
10
我们可以仅通过使用requests库来完成这个任务。
import requests
payload = ( ('file0', open("FILE_LOCATION_ON_LOCAL_MACHINE", "rb")),
('json', '{ "parameter": [ {
"name":"FILE_LOCATION_AS_SET_IN_JENKINS",
"file":"file0" }]}' ))
resp = requests.post("JENKINS_URL/job/JOB_NAME/build",
auth=('username','password'),
headers={"Jenkins-Crumb":"9e1cf46405223fb634323442a55f4412"},
files=payload )
如果需要的话,可以通过以下方式获取Jekins-Crumb:
requests.get('http://username:password@JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
6
我找到了一种解决办法,使用了requests和urllib3这两个库。虽然这不是完全标准的做法,但比起依赖PycURL来说,它更轻量一些。其实可以直接用requests来完成这个任务(这样就不用urllib3了),不过我遇到了一个小错误。
import urllib3, requests, json
url = "https://myjenkins.com/job/myjob"
params = {"parameter": [
{"name": "integration.xml", "file": "file0"},
]}
with open("integration.xml", "rb") as f:
file_data = f.read()
data, content_type = urllib3.encode_multipart_formdata([
("file0", (f.name, file_data)),
("json", json.dumps(params)),
("Submit", "Build"),
])
resp = requests.post(url, auth=("myuser", "mypassword"), data=data,
headers={"content-type": content_type}, verify=False)
resp.raise_for_status()