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 suite, test set 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 suite data sent does not contain any test sets nor 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_suite = {
        "name": "A test suite",
        "build_id": "123456789012345678901234",
        "lab_name": "lab-test-00"
    }

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

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

        test_set = {
            "name": "A test set",
            "test_suite_id": test_suite_id
        }

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

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

            test_case = {
                "name": "A test case",
                "test_set_id": test_set_id,
                "test_suite_id": test_suite_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 suite, then test set and case together

In this example, the test suite is first registered, then the test set is created embedding the test cases data.

Notes:

  • The test suite data sent does not contain any test sets nor test cases: in this case the response status code will be 201.
  • The test set data sent contains the test cases: in this case the response status code will be 202.
  • The embedded test cases do not need the mandatory field test_suite_id: it will be automatically added based on the value in the test set data.
#!/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_suite = {
        "name": "A test suite",
        "build_id": "123456789012345678901234",
        "lab_name": "lab-test-00"
    }

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

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

        test_set = {
            "name": "A test set",
            "test_suite_id": test_suite_id,
            "test_case": [
                {
                    "name": "A test case - 0"
                },
                {
                    "name": "A test case - 1"
                },
                {
                    "name": "A test case - 2"
                }
            ]
        }

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

        print response.content

if __name__ == "__main__":
    main()

Upload test suite, set and case all embedded

In this example, the test suite data sent contains the test set and case data.

Notes:

  • The test suite data contains all the necessary data: in this case the response status code will be 202 (the test set and cases will be imported asynchronously).
  • Test set and test case do not need the mandatory test_suite_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_suite = {
        "name": "A test suite",
        "build_id": "123456789012345678901234",
        "lab_name": "lab-test-00",
        "test_set": [
            {
                "name": "A test set",
                "test_case": [
                    {
                        "name": "A test case - 0"
                    },
                    {
                        "name": "A test case - 1"
                    }
                ]
            }
        ]
    }

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

    print response.content

if __name__ == "__main__":
    main()