18 KiB
Snappy Ubuntu Core REST API
Version: 2.0pre0
Note: The 2.0 API is going to be very different from the 1.0; right now, not so much.
Versioning
As the API evolves, some changes are deemed backwards-compatible (such as adding methods or verbs, or adding members to the returned JSON objects) and don't warrant an endpoint change; some changes won't be backwards compatible, and will be exposed under a new endpoint.
Connecting
While it is expected to allow clients to connect using HTTPS over a
TCP socket, at this point only a UNIX socket is supported. The socket
is /run/snapd.socket.
Authentication
The API documents three levels of access: guest, authenticated and trusted. The trusted level is allowed to modify all aspects of the system, the authenticated level can query most but not all aspects, and the guest level can only query static system-level information.
Authentication over the unix socket is delegated to UNIX ACLs, and
uses SO_PEERCRED to determine privilege levels. In essence this
means that a user will be either authenticated or trusted, with
the latter restricted to the superuser.
Responses
All responses are application/json unless noted otherwise. There are
three standard return types:
- Standard return value
- Background operation
- Error
Status codes follow that of HTTP.
Standard return value
For a standard synchronous operation, the following JSON object is returned:
{
"result": {}, // Extra resource/action specific data
"status": "OK",
"status_code": 200,
"type": "sync"
}
The HTTP code will be 200 (OK), or 201 (Created, in which case the
Location HTTP header will be set), as appropriate.
Background operation
When a request results in a background operation, the HTTP code is set
to 202 (Accepted) and the Location HTTP header is set to the
operation's URL.
The body is a JSON object with the following structure:
{
"result": {
"resource": "/2.0/operations/[uuid]", // see below
"status": "running",
"created_at": "..." // and other operation fields
},
"status": "Accepted",
"status_code": 202,
"type": "async"
}
The response body is mostly provided as a user friendly way of seeing what's going on without having to pull the target operation; all information in the body can also be retrieved from the background operation URL.
Error
There are various situations in which something may immediately go wrong, in those cases, the following return value is used:
{
"result": {
"message": "human-friendly description of the cause of the error",
"kind": "store-error", // one of a list of kinds (TBD), only present iff "value" is present
"value": {"...": "..."} // kind-specific object, as required
},
"status": "Bad Request", // text description of status_code
"status_code": 400, // or 401, etc. (same as HTTP code)
"type": "error"
}
HTTP code must be one of of 400, 401, 403, 404, 405, 409, 412 or 500.
Error results will also be used in the output of async responses.
If, in implementing a client, you find yourself keying off of
message to alter the behaviour of your client to e.g. better inform
the user of the error or otherwise adapt to the error condition,
STOP and talk to us; this is where kind comes in. New entries
for kind (and associated value metadata) will be added as needed
by client implementations.
Error kinds
| kind | value description |
|---|---|
license-required |
see “A note on licenses”, below |
Timestamps
Timestamps are presented in RFC3339 format, with µs precision, and in
UTC. For example, 2009-02-13T23:31:31.234567Z.
/
Reserved for human-readable content describing the service.
/2.0/system-info
GET
- Description: Server configuration and environment information
- Access: guest
- Operation: sync
- Return: Dict with the operating system's key values.
Sample result:
{
"default_channel": "edge",
"flavor": "core",
"api_compat": "1", // increased on minor API changes
"release": "15.04",
"store": "store-id" // only if not default
}
/2.0/snaps
GET
- Description: List of snaps
- Access: authenticated
- Operation: sync
- Return: list of snaps this Ubuntu Core system can handle.
The result is a JSON object with a snaps key; its value is itself a
JSON object whose keys are qualified snap names (e.g.,
hello-world.canonical), and whose values describe that snap.
Sample result:
{
"snaps": {
"hello-world.canonical": {
"description": "hello-world",
"download_size": 22212,
"icon": "https://myapps.developer.ubuntu.com/site_media/appmedia/2015/03/hello.svg_NZLfWbh.png",
"installed_size": -1, // always -1 if not installed
"name": "hello-world",
"origin": "canonical",
"resource": "/2.0/snaps/hello-world.canonical",
"status": "not installed",
"type": "app",
"version": "1.0.18",
"channel": "stable"
},
"http.chipaca": {
"description": "HTTPie in a snap\nno description",
"download_size": 1578272,
"icon": "/2.0/icons/http.chipaca/icon",
"installed_size": 1821897,
"name": "http",
"origin": "chipaca",
"resource": "/2.0/snaps/http.chipaca",
"status": "active",
"type": "app",
"version": "3.1",
"channel": "stable"
},
"ubuntu-core.ubuntu": {
"description": "A secure, minimal transactional OS for devices and containers.",
"download_size": 19845748,
"icon": "", // core might not have an icon
"installed_size": -1, // core doesn't have installed_size (yet)
"name": "ubuntu-core",
"origin": "ubuntu",
"resource": "/2.0/snaps/ubuntu-core.ubuntu",
"status": "active",
"type": "os",
"update_available": "247",
"version": "241",
"channel": "stable"
}
},
"paging": {
"count": 3,
"page": 0,
"pages": 1
},
"sources": [
"local",
"store"
]
}
Fields
snapsstatus: can be eithernot installed,installed,active(i.e. is current),removed(but data present); there is nopurgedstate, as a purged snap is undistinguishable from a non-installed snap.name: the snap name.version: a string representing the version.icon: a url to the snap icon, possibly relative to this server.type: the type of snap; one ofapp,framework,kernel,gadget, oros.description: snap descriptioninstalled_size: for installed snaps, how much space the snap itself (not its data) uses.download_size: for not-installed snaps, how big the download will be, formatted as a decimal string.rollback_available: if present and not empty, it means the snap can be rolled back to the version specified as a value to this entry.update_available: if present and not empty, it means the snap can be updated to the version specified as a value to this entry.channel: which channel the package is currently tracking.
pagingcount: the number of snaps on this pagepage: the page number, starting from0pages: the (approximate) number of pages
sourcesa list of the sources that were queried (see thesourcesparameter, below)
Parameters [fixme: is that the right word for these?]
sources
Can be set to either local (to only list local snaps) or store (to
only list snaps from the store), or a comma-separated
combination. Defaults to local,store.
Note that excluding sources will result in incomplete (and in some
cases incorrect) information about installed packages: information
about updates will be absent if store is not included, whereas if
local is not included information about rollbacks will be missing,
and the package state for installed packages will be incorrect.
types
Restricts returned snaps to those with types included in the specified
comma-separated list. See the description of the type field of snaps in the
above section for possible values.
page
Request the given page when the server is paginating the
result. Defaults to 0.
q
If present, only list snaps that match the query.
POST
- Description: Sideload a snap to the system.
- Access: trusted
- Operation: async
- Return: background operation or standard error
Input
The snap to sideload should be provided as part of the body of a
mutlipart/form-data request. The form should have only one file. If it also
has an allow-unsigned field (with any value), the snap may be unsigned;
otherwise attempting to sideload an unsigned snap will result in a failed
background operation.
It's also possible to provide the snap as the entire body of a POST (not a
multipart request). In this case the header X-Allow-Unsigned may be used to
allow sideloading unsigned snaps.
/2.0/snaps/[name]
GET
- Description: Details for a snap
- Access: authenticated
- Operation: sync
- Return: snap details (as in
/2.0/snaps)
Parameters
sources
See sources for /2.0/snaps.
POST
- Description: Install, update, remove, purge, activate, deactivate, or rollback the snap
- Access: trusted
- Operation: async
- Return: background operation or standard error
Sample input
{
"action": "install"
}
Fields in the input object
| field | ignored except in action | description |
|---|---|---|
action |
Required; a string, one of install, update, remove, purge, activate, deactivate, or rollback. |
|
channel |
install update |
From which channel to pull the new package (and track henceforth). Channels are a means to discern the maturity of a package or the software it contains, although the exact meaning is left to the application developer. One of edge, beta, candidate, and stable which is the default. |
leave_old |
install update remove |
A boolean, equivalent to commandline's --no-gc. Default is false (do not leave old snaps around). |
license |
install update |
A JSON object with intro, license, and agreed fields, the first two of which must match the license (see the section “A note on licenses”, below). |
A note on licenses
When requesting to install a snap that requires agreeing to a license before
install succeeds, or when requesting an update to a snap with such an
agreement that has an updated license version, the initial request will fail
with an error, and the error object will contain the intro and license texts to
present to the user for their approval. An example of the command's output
field would be
"output": {
"value": {
"agreed": false,
"intro": "licensed requires that you accept the following license before continuing",
"license": "In order to use this software you must agree with us."
},
"kind": "license-required",
"message": "License agreement required."
}
/2.0/snaps/[name]/services
Query an active snap for information about its services, and alter the
state of those services. Commands under .../services will return an error if
the snap is not active.
GET
- Description: Services for a snap
- Access: authenticated
- Operation: sync
- Return: service configuration
Returns a JSON object with a result key, its value is a list of JSON objects
where the snap name is the item key. The value is another JSON object that
has three keys [op, spec, status], spec and status are JSON objects that
provide description about the service as well as its systemd unit.
Sample result:
{
"result": {
"xkcd-webserver": {
"op": "status",
"spec": {
"name": "xkcd-webserver",
"description": "A fun webserver",
"start": "bin/xkcd-webserver",
"stop-timeout": "30s",
"caps": [
"networking",
"network-service"
]
},
"status": {
"service_file_name": "xkcd-webserver_xkcd-webserver_0.5.service",
"load_state": "loaded",
"active_state": "inactive",
"sub_state": "dead",
"unit_file_state": "enabled",
"snap_name": "xkcd-webserver",
"service_name": "xkcd-webserver"
}
}
},
"status": "OK",
"status_code": 200,
"type": "sync"
}
PUT
- Description: Put all services of a snap into a specific state
- Access: trusted
- Operation: async
Sample input:
{
"action": "start|stop|restart|enable|disable"
}
/2.0/snaps/[name]/services/[name]
GET
- Description: Service for a snap
- Access: authenticated
- Operation: sync
- Return: service configuration
The result is a JSON object with a result key where the value is a JSON object
that includes a single object from the list of the upper level endpoint
(/2.0/snaps/[name]/services).
Sample result:
{
"result": {
"op": "status",
"spec": {
"name": "xkcd-webserver",
"description": "A fun webserver",
"start": "bin/xkcd-webserver",
"stop-timeout": "30s",
"caps": [
"networking",
"network-service"
]
},
"status": {
"service_file_name": "xkcd-webserver_xkcd-webserver_0.5.service",
"load_state": "loaded",
"active_state": "inactive",
"sub_state": "dead",
"unit_file_state": "enabled",
"snap_name": "xkcd-webserver",
"service_name": "xkcd-webserver"
}
},
"status": "OK",
"status_code": 200,
"type": "sync"
}
PUT
- Description: Put the service into a specific state
- Access: trusted
- Operation: async
Sample input:
{
"action": "start|stop|restart|enable|disable"
}
/2.0/snaps/[name]/services/[name]/logs
GET
- Description: Logs for the service from a snap
- Access: trusted
- Operation: sync
- Return: service logs
Sample result:
[
{
"timestamp": "1440679470679901",
"message": "something happened",
"raw": {}
},
{
"timestamp": "1440679470680968",
"message": "bla bla",
"raw": {}
}
]
/2.0/snaps/[name]/config
Query an active snap for information about its configuration, and alter that configuration. Will return an error if the snap is not active.
GET
- Description: Configuration for a snap
- Access: trusted
- Operation: sync
- Return: snap configuration
Sample result:
"config:\n ubuntu-core:\n autopilot: false\n timezone: Europe/Berlin\n hostname: localhost.localdomain\n"
Notes: user facing implementations in text form must show this data using yaml.
PUT
- Description: Set configuration for a snap
- Access: trusted
- Operation: sync
- Return: snap configuration
Sample input:
config:\n ubuntu-core:\n autopilot: true\n
Sample result:
"config:\n ubuntu-core:\n autopilot: true\n timezone: Europe/Berlin\n hostname: localhost.localdomain\n"
/2.0/operations/[uuid]
GET
- Description: background operation
- Access: trusted
- Operation: sync
- Return: dict representing a background operation
Sample result:
{
"created_at": "1415639996123456", // Creation timestamp
"output": {},
"resource": "/2.0/snaps/camlistore.sergiusens",
"status": "running", // or “succeeded” or “failed”
"updated_at": "1415639996451214" // Last update timestamp
}
DELETE
- Description: If the operation has completed,
DELETEwill remove the entry. Otherwise it is an error. - Access: trusted
- Operation: sync
- Return: standard return value or standard error
/2.0/icons/[name]/icon
GET
-
Description: Get an icon from a snap installed on the system. The response will be the raw contents of the icon file; the content-type will be set accordingly and the Content-Disposition header will specify the filename.
This fetches the icon from the snap itself.
-
Access: guest
This is not a standard return type.
/2.0/assertions
POST
- Description: Tries to add an assertion to the system assertion database.
- Authorization: trusted
- Operation: sync
The body of the request provides the assertion to add. The assertion may also be a newer revision of a preexisting assertion that it will replace.
To succeed the assertion must be valid, its signature verified with a known public key and the assertion consistent with and its prerequisite in the database.
/2.0/assertions/[assertionType]
GET
- Description: Get all the assertions in the system assertion database of the given type matching the header filters passed as query parameters
- Access: authenticated
- Operation: sync
- Return: stream of assertions
The response is a stream of assertions separated by double newlines. The X-Ubuntu-Assertions-Count header is set to the number of returned assertions, 0 or more.
/2.0/interfaces
GET
- Description: Get all the plugs and information about the slots connected to them.
- Access: authenticated
- Operation: sync
- Return: array of plugs containing array of slots using each interface.
Sample result:
[
{
“snap”: "canonical-pi2",
“interface”: "bool-file",
“plug”: "pin-13",
“label”: "Pin 13",
“connections”: [
{"snap": "keyboard-lights", "slot": "capslock-led"}
]
}
]
POST
- Description: Issue an action to the interface system
- Access: authenticated
- Operation: sync
- Return: nothing
Available actions are:
- connect: connect the plug to the given slot.
- disconnect: disconnect the given plug from the given slot.
Sample input:
{
“action”: “connect”,
“plug”: {“snap”: “canonical-pi2”, “plug”: “pin-13”},
“slot”: {“snap”: “keyboard-lights”, “slot”: “capslock-led”}
}