如何使用标准Python库通过文件参数触发经过身份验证的Jenkins作业

问题描述 投票:0回答:7

我们目前正在 PycURL 的帮助下从 Python 脚本触发 Jenkins 作业。然而,我们希望摆脱 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 库中的工具来替换它?

我们之前尝试过,但不得不放弃,因为我们看不到如何成功上传文件,正如您从我关于该问题的问题中看到的那样。

python rest post jenkins pycurl
7个回答
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
投票

我找到了一个解决方案,使用 requestsurllib3 库。不完全标准,但比 PycURL 依赖项更轻量。应该可以直接使用请求来执行此操作(避免 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()

6
投票

如果您熟悉Python,那么您可以使用官方网站提供的jenkins REST APT 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 -> 从网页顶部单击您的用户 ID -> 配置 -> 显示 API 令牌...

享受它。


1
投票

可能看起来像这样:

url = "https://myjenkins/job/myjob/build"
req = urllib2.Request(url)

auth = 'Basic ' + base64.urlsafe_b64encode("myuser:mypassword")
req.add_header('Authorization', auth)

with open("integration.xml", "r") as f:
  file0 = f.read()
  data = {
            "name": "integration.xml",
            "file0": file0,
            "json": "{'parameter': [{'name': 'integration.xml', 'file': 'file0'}]}",
            "Submit": "Build"
         }
  req.add_data(urllib.urlencode(data))

urllib2.urlopen(req)

抱歉,我没有安装 Jenkins 来测试它。


0
投票

这是与 aknuds1 答案类似的版本,其中

test_result
是 xml 字符串:

j_string = "{'parameter': [{'name': 'integration_tests.xml', 'file': 'someFileKey0'}]}"
data = {
          "name": "integration_tests.xml",
          "json": j_string, 
        }
for xml_string in tests.values():
    post_form_result = requests.post('http://jenkins/job/deployment_tests/build',
                                     data=data,
                                     files={'someFileKey0': xml_string})
    print(post_form_result.status_code)

猜测,附加参数将作为 json 字符串数组或附加文件等的一部分传入。如果是这种情况,请告诉我,如果我发现,我会更新这个答案。该解决方案可以很好地触发 JUnit 测试。

版本:

master* $ pip show requests                                                                                                                                                                      [21:45:05]
Name: requests
Version: 2.12.3
Summary: Python HTTP for Humans.
Home-page: http://python-requests.org
Author: Kenneth Reitz
Author-email: [email protected]
License: Apache 2.0
Location: /usr/local/lib/python2.7/site-packages

0
投票

(2024.01) 经过一天的尝试和错误,让我提供迄今为止最好的解决方案。

  • Python 3.8.11
  • 詹金斯2.426.2

import requests

ENDPOINT = 'https://$JENKINS_SERVICE/job/$JENKINS_JOB'
AUTH = ('johndow', 'johndowpwd')

def post_build():
    with open('example.txt', 'rb') as fs:
        r = requests.post(f'{ENDPOINT}/buildWithParameters',
                          auth=AUTH,
                          files={'hey.txt': fs},
                          params={'HI': 'abc', 'HELLO': 'xyz'})
    r.raise_for_status()

注意必须声明文件关闭,参考:https://stackoverflow.com/a/52396494/8013269


-1
投票

我使用的另一个替代方案:

import requests
import json
url = "https://myjenkins/job/myjob/build"
payload = {'key1': 'value1', 'key2': 'value2'}
resp = requests.post(url, params=payload, auth=("username", "password"),verify=False)
json_data = json.loads(resp.text)

欲了解更多详情,您可以参考:提出请求

© www.soinside.com 2019 - 2024. All rights reserved.