Code Examples

All the following code examples are Python based and rely on the requests module.

Retrieving boot reports

#!/usr/bin/python

"""Get all boot reports for a job and a specified kernel."""

import requests

from urlparse import urljoin

BACKEND_URL = "https://api.kernelci.org"
AUTHORIZATION_TOKEN = "foo"


def main():
    headers = {
        "Authorization": AUTHORIZATION_TOKEN
    }

    params = {
        "job": "next",
        "kernel": "next-20150717"
    }

    url = urljoin(BACKEND_URL, "/boot")
    response = requests.get(url, params=params, headers=headers)

    print response.content


if __name__ == "__main__":
    main()
#!/usr/bin/python

"""Get all failed boot reports of a job.

The results will include the 'job', 'kernel' and 'board' fields. By default
they will contain also the '_id' field.
"""

import requests

from urlparse import urljoin

BACKEND_URL = "https://api.kernelci.org"
AUTHORIZATION_TOKEN = "foo"


def main():
    headers = {
        "Authorization": AUTHORIZATION_TOKEN
    }

    params = {
        "job": "next",
        "status": "FAIL",
        "field": ["job", "kernel", "board"]
    }

    url = urljoin(BACKEND_URL, "/boot")
    response = requests.get(url, params=params, headers=headers)

    print response.content


if __name__ == "__main__":
    main()
#!/usr/bin/python

"""Get all boot reports with a specified job ID.

The results will include only the 'board', 'status' and 'defconfig' fields.
The '_id' field is explicitly excluded.
"""

import requests

from urlparse import urljoin

BACKEND_URL = "https://api.kernelci.org"
AUTHORIZATION_TOKEN = "foo"


def main():
    headers = {
        "Authorization": AUTHORIZATION_TOKEN
    }

    params = {
        "job_id": "123456789012345678901234",
        "field": ["board", "status", "defconfig"],
        "nfield": ["_id"]
    }

    url = urljoin(BACKEND_URL, "/boot")
    response = requests.get(url, params=params, headers=headers)

    print response.content


if __name__ == "__main__":
    main()

Handling compressed data

If you need to directly handle the compressed data as returned by the server, you can access it from the response object.

Keep in mind though that the requests module automatically handles gzip and deflate compressions.

#!/usr/bin/python

"""Get all build reports with a specified job ID.

Explicitly defines the Accept-Encoding header and manually handle the
compressed data.
"""

import gzip
import requests

from cStringIO import StringIO
from urlparse import urljoin

BACKEND_URL = "https://api.kernelci.org"
AUTHORIZATION_TOKEN = "foo"


def main():
    headers = {
        "Authorization": AUTHORIZATION_TOKEN,
        "Accept-Encoding": "gzip"
    }

    params = {
        "job_id": "123456789012345678901234",
    }

    url = urljoin(BACKEND_URL, "/build")
    response = requests.get(url, params=params, headers=headers, stream=True)

    in_buffer = StringIO(response.raw.data)
    json_str = ""

    with gzip.GzipFile(mode="rb", fileobj=in_buffer) as g_data:
        json_str = g_data.read()

    print json_str


if __name__ == "__main__":
    main()

Creating a new lab

Note

Creation of new lab that can send boot reports is permitted only with an administrative token.

The response object will contain:

  • The token that should be used to send boot lab reports.
  • The name of the lab that should be used to send boot lab reports.
  • The lab internal _id value.
#!/usr/bin/python

"""Create a new lab entry."""

try:
    import simplejson as json
except ImportError:
    import json

import requests
import urlparse

BACKEND_URL = "https://api.kernelci.org"
AUTHORIZATION_TOKEN = "foo"


def main():
    headers = {
        "Authorization": AUTHORIZATION_TOKEN,
        "Content-Type": "application/json"
    }

    payload = {
        "name": "lab-enymton",
        "contact": {
            "name": "Ema",
            "surname": "Nymton",
            "email": "ema.nymton@example.org"
        }
    }

    url = urlparse.urljoin(BACKEND_URL, "/lab")
    response = requests.post(url, data=json.dumps(payload), headers=headers)

    print response.content


if __name__ == "__main__":
    main()

Sending a boot report

#!/usr/bin/python

try:
    import simplejson as json
except ImportError:
    import json

import requests
import urlparse

BACKEND_URL = "https://api.kernelci.org"
AUTHORIZATION_TOKEN = "foo"


def main():
    headers = {
        "Authorization": AUTHORIZATION_TOKEN,
        "Content-Type": "application/json"
    }

    payload = {
        "version": "1.0",
        "lab_name": "lab-name-00",
        "kernel": "next-20141118",
        "job": "next",
        "defconfig": "arm-omap2plus_defconfig",
        "board": "omap4-panda",
        "boot_result": "PASS",
        "boot_time": 10.4,
        "boot_warnings": 1,
        "endian": "little",
        "git_branch": "local/master",
        "git_commit": "fad15b648058ee5ea4b352888afa9030e0092f1b",
        "git_describe": "next-20141118"
    }

    url = urlparse.urljoin(BACKEND_URL, "/boot")
    response = requests.post(url, data=json.dumps(payload), headers=headers)

    print response.content


if __name__ == "__main__":
    main()

Sending a boot email report

#!/usr/bin/python

"""Send a boot email report in 60 seconds in TXT and HTML formats."""

try:
    import simplejson as json
except ImportError:
    import json

import requests

from urlparse import urljoin

BACKEND_URL = "https://api.kernelci.org"
AUTHORIZATION_TOKEN = "foo"


def main():
    headers = {
        "Authorization": AUTHORIZATION_TOKEN,
        "Content-Type": "application/json"
    }

    payload = {
        "job": "next",
        "kernel": "next-20150105",
        "boot_report": 1,
        "send_to": ["email1@example.org", "email2@example.org"],
        "delay": 60,
        "format": ["txt", "html"]
    }

    url = urljoin(BACKEND_URL, "/send")
    response = requests.post(url, data=json.dumps(payload), headers=headers)

    print response.content


if __name__ == "__main__":
    main()

Uploading files

Upload a single file

#!/usr/bin/python

import io
import requests

from urlparse import urljoin

BACKEND_URL = "https://api.kernelci.org"
AUTHORIZATION_TOKEN = "foo"


def main():
    headers = {
        "Authorization": AUTHORIZATION_TOKEN
    }

    url = urljoin(
        BACKEND_URL,
        "/upload/next/next-20150116/arm64-allnoconfig/lab-name/boot-arch.json")

    with io.open("/path/to/boot-arch.json", mode="rb") as upload_file:
        response = requests.put(url, headers=headers, data=upload_file)

    print response.content


if __name__ == "__main__":
    main()

Upload multiple files

The following example, before sending the files, will load them in memory. With big files this might not be convenient.

#!/usr/bin/python

import io
import requests

from urlparse import urljoin

BACKEND_URL = "https://api.kernelci.org"
AUTHORIZATION_TOKEN = "foo"


def main():
    headers = {
        "Authorization": AUTHORIZATION_TOKEN
    }

    data = {
        "path": "next/next-20150116/arm64-allnoconfig/"
    }

    files = [
        ("file1", ("Image", io.open("/path/to/Image", mode="rb"))),
        ("file2", ("kernel.config", io.open("/path/to/kernel.config", mode="rb"))),
        ("file3", ("build.json", io.open("/path/to/build.json", mode="rb"))),
        ("file4", ("build.log", io.open("/path/to/build.log", mode="rb"))),
        ("file5", ("System.map", io.open("/path/to/System.map", mode="rb"))),
    ]

    url = urljoin(BACKEND_URL, "/upload")
    response = requests.post(url, data=data, headers=headers, files=files)

    print response.content


if __name__ == "__main__":
    main()

Upload multiple files - 2

The following example does not load the files in memory, but it relies on an external library: requests-toolbelt.

#!/usr/bin/python

import io
import requests

from requests_toolbelt import MultipartEncoder
from urlparse import urljoin

BACKEND_URL = "https://api.kernelci.org"
AUTHORIZATION_TOKEN = "foo"


def main():
    data = MultipartEncoder(
        fields={
            "path": "next/next-20150116/arm64-allnoconfig/",
            "file1": ("Image", io.open("/path/to/Image", mode="rb")),
            "file2": ("kernel.config", io.open("/path/to/kernel.config", mode="rb")),
            "file3": ("build.json", io.open("/path/to/build.json", mode="rb")),
            "file4": ("build.log", io.open("/path/to/build.log", mode="rb")),
            "file5": ("System.map", io.open("/path/to/System.map", mode="rb")),
        }
    )

    headers = {
        "Authorization": AUTHORIZATION_TOKEN,
        "Content-Type": data.content_type
    }

    url = urljoin(BACKEND_URL, "/upload")
    response = requests.post(url, headers=headers, data=data)

    print response.content


if __name__ == "__main__":
    main()

Uploading tests

Upload each single test schema

In this example each test schema - test group and test case - will be uploaded one at the time and the results of each API request will be used to create the next data to be sent.

Notes:

  • The test group data sent does not contain any test cases: in this case the response status code will be 201.
#!/usr/bin/python

try:
    import simplejson as json
except ImportError:
    import json

import requests

from urlparse import urljoin

BACKEND_URL = "https://api.kernelci.org"
AUTHORIZATION_TOKEN = "foo"


def main():
    headers = {
        "Authorization": AUTHORIZATION_TOKEN,
        "Content-Type": "application/json"
    }

    test_group = {
        "name": "A test group",
        "build_id": "123456789012345678901234",
        "lab_name": "lab-test-00"
    }

    url = urljoin(BACKEND_URL, "/test/group")
    response = requests.post(url, data=json.dumps(test_group), headers=headers)

    if response.status_code == 201:
        test_group_result = response.json()["result"][0]
        test_group_id = test_group_result["_id"]["$oid"]

        test_case = {
            "name": "A test case",
            "test_group_id": test_group_id
        }

        url = urljoin(BACKEND_URL, "/test/case")
        response = requests.post(
            url, data=json.dumps(test_case), headers=headers)

        print response.content


if __name__ == "__main__":
    main()

Upload test group and all test case embedded

In this example, the test group data sent contains all the case data.

Notes:

  • The test group data contains all the necessary data: in this case the response status code will be 202 (the test cases will be imported asynchronously).
  • Test tests case do not need the mandatory test_group_id key: it will be automatically added when being imported.
#!/usr/bin/python

try:
    import simplejson as json
except ImportError:
    import json

import requests

from urlparse import urljoin

BACKEND_URL = "https://api.kernelci.org"
AUTHORIZATION_TOKEN = "foo"


def main():
    headers = {
        "Authorization": AUTHORIZATION_TOKEN,
        "Content-Type": "application/json"
    }

    test_group = {
        "name": "A test group",
        "build_id": "123456789012345678901234",
        "lab_name": "lab-test-00",
        "test_cases": [
            {
                "name": "A test case - 0"
            },
            {
                "name": "A test case - 1"
            }
        ]
    }

    url = urljoin(BACKEND_URL, "/test/group")
    response = requests.post(url, data=json.dumps(test_group), headers=headers)

    print response.content


if __name__ == "__main__":
    main()