Skip to content

DCI Server API documentation

Endpoints

The resources of DCI can be accessed through our API in a Restful way. Currently, only the json output format is supported.

Each resource provides two endpoints, one for listing: /<resources>/, one for fetching a dedicated element: /<resources>/<resource_id>/.

On those endpoints we can use some parameters on the GET method to filter, search or complete results.

On the listing endpoint:

/<resources>?sort=field1,-field2&limit=20&offset=0&where=field1:foo,field2:bar

  • sort parameter will allow the user to sort the listing output according to fields, the sorting is done by ascending results, if the field is prefixed with -, the sorting is done descending. The order also matter, it sorts the first field, when its done it sorts the second field with the resources which have the same first field values, and so on. In our example, it will sort ascending on field1 and on resources which have the same value for field1 will sort descending on field2.
  • limit parameter is usually used with the offset one in order to paginate results. It will limit the number of resources retrivied, by default it is set to 20 entries, but you can augment that value. Be careful, the more you fetch the longer the http call can be.
  • offset parameter is the second pagination parameter, this will indicate at which entry we want to start the listing in the order defined by default or with other parameters.
  • where parameter is here to filter the resources according to a field value. In this example we will retrieve the resources which field1 is equal to foo and field2 equal to bar.

On the resource endpoint:

/<resources>/<resource_id>

Concurrency control with ETag

The REST API support etag headers, each request result contains the HTTP header ETag which is a fingerprint of the requested resource.

When a user wants to update or delete a resource then the API requires the user to provide the HTTP header If-match with the corresponding ETag in order to prevent concurrency errors.

This mechanism ensure that the user has read the most up to date value of the resource before to update/delete it.

Example:

$ http POST $URL/api/v1/componenttypes name=kikoolol
HTTP/1.0 201 CREATED
Content-Length: 217
Content-Type: application/json
Date: Fri, 13 Nov 2015 12:46:18 GMT
ETag: 8f5dc53c14b865d2c2f0ca6654a4a5c2
Server: Werkzeug/0.10.4 Python/2.7.6

Here is the etag ETag: 8f5dc53c14b865d2c2f0ca6654a4a5c2.

$ http PUT $URL/api/v1/componenttypes/kikoolol name=kikoolol2
HTTP/1.0 412 PRECONDITION FAILED
Content-Length: 92
Content-Type: application/json
Date: Fri, 13 Nov 2015 12:47:33 GMT
Server: Werkzeug/0.10.4 Python/2.7.6
{
    "message": "'If-match' header must be provided",
    "payload": {},
    "status_code": 412
}

Here an update request must provide the If-match header.

$ http PUT $URL/api/v1/componenttypes/kikoolol \
If-match:8f5dc53c14b865d2c2f0ca6654a4a5c2 name=kikoolol2
HTTP/1.0 204 NO CONTENT
Content-Length: 0
Content-Type: application/json
Date: Fri, 13 Nov 2015 12:48:45 GMT
ETag: 71c076a7ccda10632a40be60ba065511
Server: Eve/0.6 Werkzeug/0.10.4 Python/2.7.6

The update succeeded and the ETag has been updated.

Complex where clauses

If you need more complex queries, you can use this format in the query parameter:

/<resources>?sort=<field1>,-<field2>&limit=20&offset=0&query=and(eq(<field1>,foo),eq(<field2>,bar))

Then the language is defined like that:

eq(<field>,<value>) to lookup resources with a <field> having the value <value>.

You can use the comparison functions gt (greater than), ge (greater or equal), lt (less than) or le (less or equal) using the same syntax as eq: <op>(<field>,<value>).

like(<field>,<value with percent>) and ilike(<field>,<value with percent>) to lookup a field with a SQL glob like way.

contains(<field>,<value1>,...) and not_contains(<field>,<value1>,...) to lookup elements in an array. This is useful mainly for tags.

and(<op1>(...),<op2>(...)), or(<op1>(...),<op2>(...)) and not(<op>) allow to build nested boolean queries.

null(<field>) to lookup resources with a field having a NULL value.

Component Type

object attributes:

  • id
  • created_at
  • updated_at
  • name

listing url: /api/v1/componenttypes

  • GET: get all the components type
  • response: 200 {'componenttypes': [{componenttype1}, {componenttype2}]}
  • POST: create a component type element
  • data: {'name': ...}
  • response: 201 {'componenttype': {componenttype}}

resource url: /api/v1/componenttypes/<componenttype_id>

  • GET: retrieve the dedicated component type
  • response: 200 {'componenttype': {componenttype}}
  • PUT: update the given component type
  • data: {'name': ...}
  • response: 204 {'componenttype': {componentype}}
  • DELETE: remove the given component type
  • response: 204

Component

object attributes

  • id
  • created_at
  • updated_at
  • released_at
  • name
  • componenttype

listing url: /api/v1/components

  • GET: get all the components
  • response: 200 {'components': [{component1}, {component2}]}
  • POST: create a component element
  • data: {'name': ..., 'componenttype': ...}
  • response: 201 {'component': {component}}

resource url: /api/v1/components/<component_id>

  • GET: retrieve the dedicated component
  • response: 200 {'component': {component}}
  • PUT: update the given component
  • data: {'name': ..., 'componenttype': ...}
  • response: 201 {'component': {component}}
  • DELETE: remove the given component
  • response: 204

Check if the request is authenticated

Check if the request is authenticated. Returns 200 = success, or 401 = failure.

Endpoint:

Method: GET
Type: 
URL: https://api.distributed-ci.io/api/v1/identity

Responses:

Status: Check if the request is authenticated | Code: 200

{
    "identity": {
        "email": null,
        "etag": null,
        "fullname": null,
        "id": "6cee7286-5d99-4a96-9949-200977f4be07",
        "name": null,
        "teams": {
            "713ecb86-0157-4445-ad90-c7aa7d0306a0": {
                "team_name": "Red Hat"
            }
        },
        "timezone": null
    }
}

Get all topics

Get all topics

Endpoint:

Method: GET
Type: 
URL: https://api.distributed-ci.io/api/v1/topics

Get a topic id by topic name

Get topic id by topic name:

GET /api/v1/topics?where=name:<topic_name>
response.data.topic
{
  id: <topic_id>
}

id: <topic_id> in response body should be saved for later use in requests: Get components for a topic and Create a new job

Endpoint:

Method: GET
Type: 
URL: https://api.distributed-ci.io/api/v1/topics

Query params:

Key Value Description
where name:RHEL-8.2

Responses:

Status: Get a topic id by topic name | Code: 200

{
    "_meta": {
        "count": 1
    },
    "topics": [
        {
            "component_types": [
                "Compose",
                "hwcert"
            ],
            "created_at": "2019-10-10T06:14:55.269457",
            "data": {},
            "etag": "6d279adf27286020ef95eec7349f317c",
            "export_control": false,
            "id": "c4171062-e2b4-4b60-9a5f-3e2fb32b4f68",
            "name": "RHEL-8.2",
            "next_topic_id": null,
            "product_id": "b3d8d6f3-8223-4553-bf08-9b2cecb869f2",
            "state": "active",
            "updated_at": "2019-10-10T06:15:07.565374"
        }
    ]
}

Get components for a topic

GET /api/v1/topics/\<topic_id>/components

where topic_id is obtained from Get topic id by name request.

response.data.components
[
    {
        id: <component_id_1>
    },
    {
        id: <component_id_2>
    },
]

Endpoint:

Method: GET
Type: 
URL: https://api.distributed-ci.io/api/v1/topics/c4171062-e2b4-4b60-9a5f-3e2fb32b4f68/components

Responses:

Status: Get components for a topic | Code: 200

{
    "_meta": {
        "count": 21
    },
    "components": [
        {
            "canonical_project_name": "RHEL-8.2.0-20191029.n.0",
            "created_at": "2019-10-29T05:45:00.790012",
            "data": {},
            "etag": "729416351fa3e5ee5d72bfa0a336d55d",
            "id": "4e7a2754-9871-41ad-9444-665219fd0745",
            "message": null,
            "name": "RHEL-8.2.0-20191029.n.0",
            "state": "active",
            "title": null,
            "topic_id": "c4171062-e2b4-4b60-9a5f-3e2fb32b4f68",
            "type": "Compose",
            "updated_at": "2019-10-29T07:08:46.539578",
            "url": "http://download-node-02.eng.bos.redhat.com/rhel-8/nightly/RHEL-8/RHEL-8.2.0-20191029.n.0"
        },
        {
            "canonical_project_name": "hwcert-1572272875",
            "created_at": "2019-10-28T14:45:00.572710",
            "data": {
                "path": "/packages/devel/RHEL8",
                "repo_name": "rhcert-dev-el8",
                "version": "hwcert-server.khw2.lab.eng.bos.redhat.com"
            },
            "etag": "d1992b9538ad3d01288b6ecd7f91928c",
            "id": "8c8f22fd-611a-4284-9cde-057c8d2599b7",
            "message": null,
            "name": "hwcert-1572272875",
            "state": "active",
            "title": null,
            "topic_id": "c4171062-e2b4-4b60-9a5f-3e2fb32b4f68",
            "type": "hwcert",
            "updated_at": "2019-10-28T14:45:44.252868",
            "url": "http://hwcert-server.khw2.lab.eng.bos.redhat.com/packages/devel/RHEL8"
        },
        {
            "canonical_project_name": "RHEL-8.2.0-20191028.n.0",
            "created_at": "2019-10-28T05:45:00.063471",
            "data": {},
            "etag": "04276278c6a6def258010a4e950c92d4",
            "id": "a3587df1-83f0-418c-8a97-094df763006d",
            "message": null,
            "name": "RHEL-8.2.0-20191028.n.0",
            "state": "active",
            "title": null,
            "topic_id": "c4171062-e2b4-4b60-9a5f-3e2fb32b4f68",
            "type": "Compose",
            "updated_at": "2019-10-28T07:06:18.939543",
            "url": "http://download-node-02.eng.bos.redhat.com/rhel-8/nightly/RHEL-8/RHEL-8.2.0-20191028.n.0"
        },
        {
            "canonical_project_name": "RHEL-8.2.0-20191027.n.0",
            "created_at": "2019-10-27T05:44:59.913636",
            "data": {},
            "etag": "9a66c947bfc5ac88329688b92cd7a186",
            "id": "9242b2c6-4c6b-4547-8688-ed8a77330cc0",
            "message": null,
            "name": "RHEL-8.2.0-20191027.n.0",
            "state": "active",
            "title": null,
            "topic_id": "c4171062-e2b4-4b60-9a5f-3e2fb32b4f68",
            "type": "Compose",
            "updated_at": "2019-10-27T07:13:04.559639",
            "url": "http://download-node-02.eng.bos.redhat.com/rhel-8/nightly/RHEL-8/RHEL-8.2.0-20191027.n.0"
        },
        {
            "canonical_project_name": "RHEL-8.2.0-20191026.n.0",
            "created_at": "2019-10-26T05:44:59.542342",
            "data": {},
            "etag": "9b3e12c39a027dec726d9be90e4b0fda",
            "id": "530c727c-22f0-486a-98a8-868b21c42d13",
            "message": null,
            "name": "RHEL-8.2.0-20191026.n.0",
            "state": "inactive",
            "title": null,
            "topic_id": "c4171062-e2b4-4b60-9a5f-3e2fb32b4f68",
            "type": "Compose",
            "updated_at": "2019-10-29T07:08:48.150986",
            "url": "http://download-node-02.eng.bos.redhat.com/rhel-8/nightly/RHEL-8/RHEL-8.2.0-20191026.n.0"
        },
        {
            "canonical_project_name": "RHEL-8.2.0-20191025.n.0",
            "created_at": "2019-10-25T05:45:00.658373",
            "data": {},
            "etag": "87cb1dd32f4e56ded9d1bd93813e0fc4",
            "id": "c5f4993c-aefe-40bc-a628-d51febccb773",
            "message": null,
            "name": "RHEL-8.2.0-20191025.n.0",
            "state": "inactive",
            "title": null,
            "topic_id": "c4171062-e2b4-4b60-9a5f-3e2fb32b4f68",
            "type": "Compose",
            "updated_at": "2019-10-28T07:06:20.549124",
            "url": "http://download-node-02.eng.bos.redhat.com/rhel-8/nightly/RHEL-8/RHEL-8.2.0-20191025.n.0"
        }
    ]
}

Get all jobs

Get all jobs

Endpoint:

Method: GET
Type: 
URL: https://api.distributed-ci.io/api/v1/jobs

Create a new job

Create a new job:

POST /api/v1/jobs/
{
    components: [component_id],
    topic_id: topic_id
}
response.data.job
{
    id: <job_id>
}

Current implementation also allows

POST /api/v1/jobs/schedule
{
    topic_id: topic_id
}

and will automatically associate the latest components of each component type that compose this topic, ie. latest Compose and latest hwcert for RHEL-8.2.

Endpoint:

Method: POST
Type: RAW
URL: https://api.distributed-ci.io/api/v1/jobs

Headers:

Key Value Description
Content-Type application/json

Body:

{
 "components": ["d4bcd2e2-98df-4962-b224-8d50eedaba1b"],
 "topic_id": "c4171062-e2b4-4b60-9a5f-3e2fb32b4f68"
}

Responses:

Status: Create a new job | Code: 201

{
    "job": {
        "client_version": null,
        "comment": null,
        "created_at": "2019-10-28T00:11:35.988480",
        "duration": 0,
        "etag": "325a2aba9b3ef362dc2e5e93671d76d5",
        "id": "bf878d0c-3119-4194-913b-1da1cf3a19fa",
        "previous_job_id": null,
        "product_id": "b3d8d6f3-8223-4553-bf08-9b2cecb869f2",
        "remoteci_id": "6cee7286-5d99-4a96-9949-200977f4be07",
        "state": "active",
        "status": "new",
        "team_id": "713ecb86-0157-4445-ad90-c7aa7d0306a0",
        "topic_id": "c4171062-e2b4-4b60-9a5f-3e2fb32b4f68",
        "topic_id_secondary": null,
        "update_previous_job_id": null,
        "updated_at": "2019-10-28T00:11:35.988480",
        "user_agent": "PostmanRuntime/7.18.0"
    }
}

Change a job state to pre-run

A job can have different states: ['new', 'pre-run', 'running', 'post-run', 'success', 'failure', 'killed', 'error'].
When a job is created its state is 'new'. At the end of a partner remote CI run job_state should be changed to success or failure for the created job.

Endpoint:

Method: POST
Type: RAW
URL: https://api.distributed-ci.io/api/v1/jobstates

Headers:

Key Value Description
Content-Type application/json

Body:

{
 "job_id": "bf878d0c-3119-4194-913b-1da1cf3a19fa",
 "status": "pre-run"
}

Responses:

Status: Change a job state to pre-run | Code: 201

{
    "jobstate": {
        "comment": null,
        "created_at": "2019-10-28T00:12:38.505403",
        "id": "011522e8-da95-49a1-a357-c9696f9c7519",
        "job_id": "bf878d0c-3119-4194-913b-1da1cf3a19fa",
        "status": "pre-run"
    }
}

Change a job state to running

Endpoint:

Method: POST
Type: RAW
URL: https://api.distributed-ci.io/api/v1/jobstates

Headers:

Key Value Description
Content-Type application/json

Body:

{
 "job_id": "bf878d0c-3119-4194-913b-1da1cf3a19fa",
 "status": "running"
}

Responses:

Status: Change a job state to running | Code: 201

{
    "jobstate": {
        "comment": null,
        "created_at": "2019-10-24T15:41:46.341813",
        "id": "c078619b-8712-4e68-b5ab-54e90c03295c",
        "job_id": "9943ce77-4012-4ab3-a91a-c3387acc777c",
        "status": "running"
    }
}

Change a job state to success

When a job is created it has a state 'new'. A job can have different states: ['new', 'pre-run', 'running', 'post-run', 'success', 'failure', 'killed', 'error']. At the end of a partner remote CI run job_state should be changed to success or failure for the created job. POST /api/v1/jobstates Request body: { 'job_id': , 'status': 'success' }

Endpoint:

Method: POST
Type: RAW
URL: https://api.distributed-ci.io/api/v1/jobstates

Headers:

Key Value Description
Content-Type application/json

Body:

{
 "job_id": "bf878d0c-3119-4194-913b-1da1cf3a19fa",
 "status": "success"
}

Responses:

Status: Change a job state to success | Code: 201

{
    "jobstate": {
        "comment": null,
        "created_at": "2019-10-24T15:42:50.932397",
        "id": "1135f979-35ed-4921-b310-e18076782dae",
        "job_id": "9943ce77-4012-4ab3-a91a-c3387acc777c",
        "status": "success"
    }
}

Change a job state to failure

A job can have different states: ['new', 'pre-run', 'running', 'post-run', 'success', 'failure', 'killed', 'error'].
When a job is created its state is 'new'. At the end of a partner remote CI run job_state should be changed to success or failure for the created job.

POST /api/v1/jobstates
Request body:
{
    'job_id': <job_id>, 
    'status': 'failure'
}

Endpoint:

Method: POST
Type: RAW
URL: https://api.distributed-ci.io/api/v1/jobstates

Headers:

Key Value Description
Content-Type application/json

Body:

{
 "job_id": "bf878d0c-3119-4194-913b-1da1cf3a19fa",
 "status": "failure"
}

Responses:

Status: Change a job state to failure | Code: 201

{
    "jobstate": {
        "comment": null,
        "created_at": "2019-10-24T15:43:36.102530",
        "id": "c3cb7013-4e2e-409a-99c4-d9d793adff9a",
        "job_id": "9943ce77-4012-4ab3-a91a-c3387acc777c",
        "status": "failure"
    }
}

Upload test results

Upload test results:

POST /api/v1/files
headers = {
    'DCI-JOB-ID': <job_id>,
    'DCI-NAME': <file_name>,
    'DCI-MIME': 'application/junit',
}
data = <file_content>
response.data.file
{
    id: <file_id>
}

Endpoint:

Method: POST
Type: RAW
URL: https://api.distributed-ci.io/api/v1/files

Headers:

Key Value Description
DCI-NAME test-result.log
DCI-MIME application/junit
DCI-JOB-ID bf878d0c-3119-4194-913b-1da1cf3a19fa

Body:

{
 "job_id": "bf878d0c-3119-4194-913b-1da1cf3a19fa",
 "status": "failure"
}

Responses:

Status: Upload test results | Code: 201

{
    "file": {
        "created_at": "2019-10-29T15:34:48.962810",
        "etag": "0a7200c0e3223ffcb78ace010e5ea10e",
        "id": "deba6adf-aba1-4db3-800a-aa491bde7394",
        "job_id": "bf878d0c-3119-4194-913b-1da1cf3a19fa",
        "jobstate_id": null,
        "md5": null,
        "mime": "application/junit",
        "name": "test-result.log",
        "size": "75",
        "state": "active",
        "team_id": "713ecb86-0157-4445-ad90-c7aa7d0306a0",
        "updated_at": "2019-10-29T15:34:48.962824"
    }
}