| This file describes the RESTful compile-server API. The API looks like |
| the following: |
| |
| Method URI DESCRIPTION |
| POST /builds create build |
| GET /builds/123 retrieve build info |
| DELETE /builds/123 delete build |
| GET /results/789 retrieve result info |
| GET /results/789/FILE retrieve result files |
| |
| All the individual item numbers in the URIs will be UUIDs. |
| |
| You'll notice that DELETE is missing from most the above. For now |
| anyway, we'll let the server decide when to delete the |
| containers. Also note that the server will decide when a new |
| container needs to be created (based on the build id information). |
| |
| Also note at this point that we're not going to authenticate |
| users. We're going to leave that level of authentication to a |
| front-end reverse-proxy server, rather than worry about it ourselves. |
| |
| How are we going to handle the perhaps long creation time, if we |
| have to create a new docker container for instance? It would look |
| like this: |
| |
| client: POST /builds (all the parameters, kernel version, |
| arch, etc.) |
| server: 202 Accepted - URI of queued build task (like /builds/456) |
| |
| Note that the server could return an error here, especially if the |
| architectures don't match. Also note that there could be a GET needed |
| here on the returned URI to upload a script file (if that wasn't done |
| in the POST data). |
| |
| So then how does the client know when the queued build task is |
| finished? It polls the queued build task: |
| |
| client: GET /builds/456 |
| server: 200 OK (along with buildid details) |
| |
| Eventually, the client will get the following: |
| |
| client: GET /builds/456 |
| server: 303 See Other - along with the URI of the result info. |
| |
| The client would then retrieve the result info, which will list all |
| the files produced. |
| |
| After retrieving the module (using GET), the client can delete the |
| buildid (at this point the server would also delete the linked |
| result files). |
| |
| client: DELETE /builds/456 |
| server: 300 OK |
| |
| One semi-tricky server note. Let's say a job comes in to build a |
| module for kernel X. While building a container for kernel X, a |
| second request comes in to build a module for kernel X. The server |
| should reuse the in-progress container from the first build, not |
| try to build a 2nd container for the same kernel. This implies that |
| the containers should contain a reference count. That information |
| should be persistent across server shutdown and startup, so we'll |
| need a small database. |
| |
| FIXME: at some point we'll need to add other stuff the current |
| client/server code supports, like certificates used for module |
| signing, MOK signing, etc. |
| |
| The server could support several possible "back ends": |
| |
| - LOCAL: use the kernel devel environment(s) on the local |
| machine. If nothing else, this could be used for testing the |
| server. The server wouldn't add any more kernel devel |
| environments here, but if the devel environment for kernel X is |
| already installed here, it seems odd to build a container. |
| - MOCK: build a mock "container" to build the module in |
| - DOCKER: build a docker container to build the module in |
| - VAGRANT: build a vagrant container to build the module in |
| |
| The user wouldn't be bothered with picking from these, the server will |
| decide which one to use based on which one matches up with the server |
| system. In other words, if the docker application isn't present the |
| server shouldn't try to use it. |
| |
| The server will also need to "garbage collect" at some point, |
| making sure the we only keep X containers around and deleting ones |
| that haven't been used recently. |
| |
| Here's an example run: |
| |
| - The client sends a POST /builds request: |
| |
| POST /builds kver=4.12.0-0.rc3.git0.2.fc27.x86_64&arch=x86_64&cmd_args=-vp4&cmd_args=-e&cmd_args=probe+begin+%7B+exit%28%29+%7D' |
| |
| The server responds with: |
| |
| HTTP/1.1 202 Accepted |
| Retry-After: 10 |
| Location: /builds/ad64 |
| |
| This tells the client to wait 10 seconds then do a GET on |
| /builds/ad64. |
| |
| - The client does a GET: |
| |
| GET /builds/ad64 |
| |
| The server responds with a JSON encoded body: |
| |
| HTTP/1.1 200 OK |
| Location: /builds/ad64 |
| Body: { |
| "uuid": "ad64", |
| "kver": "4.12.0-0.rc3.git0.2.fc27.x86_64", |
| "arch": "x86_64", |
| "cmd_args": [ |
| "-vp4", |
| "-e", |
| "probe begin { exit() }" |
| ] |
| } |
| |
| The client keeps doing the same GET until... |
| |
| - When the build is finished, the server will respond with a 303: |
| |
| HTTP/1.1 303 See Other |
| Location: /results/39ff |
| |
| The client then does a GET on the /results/URI: |
| |
| GET /results/39ff |
| |
| The server responds: |
| |
| HTTP/1.1 200 OK |
| Body: { |
| "uuid": "39ff", |
| "rc": 0, |
| "stdout_location": "/results/39ff/stdout", |
| "stderr_location": "/results/39ff/stderr", |
| "files": [ |
| { "location": "/results/39ff/stap_91e5911967e16d8c350000d9f1d7de71_1105.ko", "mode": 436 } |
| ] |
| } |
| |
| - The client can then to a GET on the module itself: |
| |
| GET /results/39ff/stap_91e5911967e16d8c350000d9f1d7de71_1105.ko |
| |
| The server responds (along with the module data): |
| |
| HTTP/1.1 200 OK |
| |
| - At this point the client could issue a DELETE on /builds/ad64. |