Current version: 0.1.0
This library provides an API server intended for use in an OS that is primarily accessible through the API. It's intended to be the primary way to read and modify OS settings, to update services based on those settings, and more generally to learn about and change the state of the system.
The server listens to HTTP requests on a Unix-domain socket. There is no built-in authentication - local access to the socket should be limited to processes and containers that should be able to configure the system. Remote access should only be allowed through an authenticated control channel such as SSH or SSM.
We present an HTTP interface to configurable settings and other state. The interface is documented in OpenAPI format in openapi.yaml.
The Settings APIs are particularly important.
You can GET settings from the /settings
endpoint.
You can also PATCH changes to the /settings
endpoint.
Settings are stored as a pending transaction until a commit API is called.
Pending settings can be retrieved from /tx
to see what will change.
Upon making a /tx/commit
POST call, the pending transaction is made live.
Upon making an /tx/apply
POST call, an external settings applier tool is called to apply the changes to the system and restart services as necessary.
There's also /tx/commit_and_apply
to do both, which is the most common case.
If you don't specify a transaction, the "default" transaction is used, so you usually don't have to think about it.
If you want to group changes into transactions yourself, you can add a tx
parameter to the APIs mentioned above.
For example, if you want the name "FOO", you can PATCH
to /settings?tx=FOO
and POST
to /tx/commit_and_apply?tx=FOO
.
Requests are directed by server::router
.
server::controller
maps requests into our data model.
The API is driven by a data model (similar to a schema) defined in Rust. (See the models directory for model definitions and more documentation.) All input is deserialized into model types, and all output is serialized from model types, so we can be more confident that data is in the format we expect.
The data model describes system settings, services using those settings, and configuration files used by those services. It also has a more general structure for metadata. Metadata entries can be stored for any data field in the model.
Data from the model is stored in a key/value data store. Keys are dotted strings like "settings.service.abc". This naturally implies some grouping and hierarchy of the data, corresponding to the model.
The current data store implementation maps keys to filesystem paths and stores the value in a file.
Metadata about a data key is stored in a file at the data key path + "." + the metadata key.
The default data store location is /var/lib/bottlerocket/datastore/current
, and the filesystem format makes it fairly easy to inspect.
For more detail, see datastore.
- Data store locking is coarse; read requests can happen in parallel, but a write request will block everything else.
- There's no support for rolling back commits.
- There are no metrics.
You can start the API server from the apiserver
directory with a command like:
cargo run -- --datastore-path /tmp/bottlerocket/data --socket-path /tmp/bottlerocket/api.sock --log-level debug
Then, from another shell, you can query or modify data.
See ../../apiclient/README.md
for client examples.
This text was generated using cargo-readme, and includes the rustdoc from src/lib.rs
.