Как запустить аутентифицированное задание Jenkins с параметром файла, используя стандартную библиотеку Python

В настоящее время мы запускаем задания Jenkins из скрипта Python с помощью 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?

Мы уже пытались раньше, но вынуждены были сдаться, так как не видели, как успешно загружать файлы, как вы можете видеть из мой вопрос по этому поводу.


person aknuds1    schedule 05.12.2011    source источник
comment
Кажется, вы используете https. Имейте в виду, что httplib и urllib2 не проверяют сертификат сервера при подключении к веб-сайту HTTPS (см. официальную документацию), поэтому безопасно установить соединение не получится. (Вы можете обойти это, обернув соединение httplib с помощью модуля ssl.)   -  person Bruno    schedule 05.12.2011
comment
Если вы посмотрите на мой код, вы увидите, что я говорю cURL игнорировать сертификат HTTPS :) Это сайт внутренней сети, так что это не имеет значения.   -  person aknuds1    schedule 05.12.2011
comment
Почему вы хотите использовать urllib2/httplib вместо pycURL?   -  person codersofthedark    schedule 15.03.2012
comment
@dragosrsupercool Потому что pycURL — это зависимость, которую я предпочел бы избегать.   -  person aknuds1    schedule 15.03.2012
comment
pycURL основан на libcurl (чистый код C), который доказал свою лучшую производительность и стабильность по сравнению с urllib и httplib. Более того, каждая машина Linux поставляется с cURL, а pycURL — это всего лишь один код API для этого cURL.   -  person codersofthedark    schedule 15.03.2012
comment
@dragosrsupercool Это все еще (слишком) сильная зависимость   -  person aknuds1    schedule 15.03.2012
comment
@aknuds1: слишком тяжелый? как? Можете ли вы уточнить свое наблюдение? Я новый администратор pycURL и могу обеспечить какое-то решение в следующем выпуске, который мы планируем на следующий месяц..   -  person codersofthedark    schedule 15.03.2012
comment
@dragosrsupercool Мы должны вручную собрать / установить и это, и cURL в Windows.   -  person aknuds1    schedule 15.03.2012
comment
@ aknuds1: что делать с exe-файлом? установка в один клик из окон?   -  person codersofthedark    schedule 15.03.2012
comment
@dragosrsupercool Это определенно было бы лучше. Я предполагаю, что автоматическая установка через EasyInstall невозможна (из-за зависимости от libcurl)?   -  person aknuds1    schedule 19.03.2012
comment
давайте обсудим, можем ли мы включить libcurl с pycurl в один пакет.. .   -  person codersofthedark    schedule 20.03.2012
comment
@aknuds1: есть обновления? Можете ли вы опубликовать код (может быть, то, что у вас было в этом другом вопросе)?   -  person TryPyPy    schedule 24.04.2012
comment
@TryPyPy Смотрите мой ответ, это лучшее, что я смог придумать.   -  person aknuds1    schedule 12.08.2012


Ответы (6)


Мы можем сделать это только с помощью библиотеки запросов.

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)')
person ssaurav    schedule 04.03.2017
comment
Jenkins Crumb не нужен, если вместо пароля пользователя используется токен API. - person recvfrom; 21.05.2021

Я нашел решение, используя запросы и urllib3 библиотеки. Не совсем стандартная, но более легкая, чем зависимость 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()
person aknuds1    schedule 09.08.2012
comment
Так что, если для сборки требуется токен, он будет добавлен вместе с параметрами? Я пробовал это, и он, похоже, не строится - person AsadSMalik; 15.08.2014
comment
* кажется, не строится с установленным параметром - person AsadSMalik; 15.08.2014
comment
@ Joiya550 Вы должны воспроизвести то, как обычно отправляются токены (например, в браузере). - person aknuds1; 16.08.2014

Если вы знакомы с 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 -> щелкните свой идентификатор пользователя в верхней части веб-страницы -> Настроить -> Показать токен API...

Наслаждайся этим.

person mainframer    schedule 21.05.2015
comment
Однако он не включает параметр файла. - person aknuds1; 12.04.2016

Вероятно, это может выглядеть примерно так:

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, чтобы проверить это.

person Ivan Blinkov    schedule 24.04.2012

Другая альтернатива, которую я использовал:

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)

Для получения более подробной информации вы можете обратиться:Сделать запрос

person Kamesh Jungi    schedule 12.04.2016
comment
@aknuds1 Улучшен ответ на запрос публикации с параметрами. Надеюсь, это решит ваш вопрос. - person Kamesh Jungi; 12.04.2016
comment
Однако показывает ли он, как опубликовать файл? Взгляните на мой вопрос и ответ для справки. - person aknuds1; 12.04.2016
comment
Да, когда вы печатаете json_data, вы можете получить текст ответа. Попробуйте один раз .. вы найдете выход. - person Kamesh Jungi; 12.04.2016
comment
Я не думаю, что вы понимаете, что я имею в виду. Вопрос в том, как опубликовать файл в Jenkins, мой ответ обрабатывает это. - person aknuds1; 12.04.2016

Вот аналогичная версия ответа 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
person jmunsch    schedule 07.12.2016