Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to trigger authenticated Jenkins job with file parameter using standard Python library

We are currently triggering Jenkins jobs from a Python script with the help of PycURL. We would like, however, to get rid of the PycURL dependency, but have had little success so far. What makes our scenario more complicated is that we need to post a file as a parameter. Our current PycURL logic for posting the request looks as follows:

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())

How can we replace this with facilities from the standard Python library?

We've tried before, but had to give up as we could not see how to upload files successfully, as you can see from my question on that issue.

like image 610
aknuds1 Avatar asked Dec 05 '11 10:12

aknuds1


People also ask

How do you auto trigger the job in Jenkins?

Follow the steps as mentioned below to trigger a Jenkins job automatically based on GitHub's webhook configurations: Step 1: Go to the Configuration page of the respective job and under the build trigger section, check the "GitHub hook trigger for GITScm polling" checkbox and click on the Save button.


2 Answers

We can do it with the help of requests library only.

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 if required can be obtained using:

requests.get('http://username:password@JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
like image 103
ssaurav Avatar answered Sep 27 '22 20:09

ssaurav


I found a solution, using the requests and urllib3 libraries. Not entirely standard, but more lightweight than the PycURL dependency. It should be possible to do this directly with requests (avoiding the urllib3 part), but I ran into a bug.

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()
like image 24
aknuds1 Avatar answered Sep 27 '22 20:09

aknuds1