Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add transaction support to API #715

Merged
merged 6 commits into from
Feb 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,17 +197,26 @@ This can include any number of settings changes.
apiclient -m PATCH -u /settings -d '{"timezone": "America/Thunder_Bay"}'
```

This will *stage* the setting in a "pending" area.
You can see all the pending settings like this:
This will *stage* the setting in a "pending" area - a transaction.
You can see all your pending settings like this:
tjkirch marked this conversation as resolved.
Show resolved Hide resolved
```
apiclient -u /settings/pending
apiclient -u /tx
```

To *commit* the settings, and let the system apply them to any relevant configuration files or services, do this:
```
apiclient -m POST -u /settings/commit_and_apply
apiclient -m POST -u /tx/commit_and_apply
```

Behind the scenes, these commands are working with the "default" transaction.
This keeps the interface simple.
System services use their own transactions, so you don't have to worry about conflicts.
For example, there's a "thar-boot" transaction used to coordinate changes at startup.

If you want to group sets of changes yourself, pick a transaction name and append a `tx` parameter to the URLs 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`.
(Transactions are created automatically when used, and are cleaned up on reboot.)

For more details on using the client, see the [apiclient documentation](workspaces/api/apiclient/).

#### Using user data
Expand Down
16 changes: 5 additions & 11 deletions extras/host-containers/thar-control/enable-admin-container
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ error() {
cat >&2 <<-EOF
You can manually enable the admin container like this:
apiclient -u /settings -m PATCH -d '{"host-containers": {"admin": {"enabled": true}}}'
apiclient -u /settings/commit_and_apply -m POST
apiclient -u /tx/commit_and_apply -m POST
EOF
exit 1
}
Expand All @@ -14,22 +14,16 @@ if ! command -v apiclient >/dev/null 2>&1; then
error "can't find 'apiclient'"
fi

echo "Checking whether there are pending settings; we don't want to silently commit other changes"
PENDING="$(apiclient -u /settings/pending)"
rc="${?}"
if [ "${rc}" -ne 0 ]; then
error "apiclient returned ${rc} - couldn't check pending settings, so we don't know if it's safe to commit changes for enabling admin container.\nTry to check what's pending with \`apiclient -u /settings/pending\`"
elif [ "${PENDING}" != "{}" ]; then
error "found pending settings in API, cowardly refusing to commit them.\nYou can commit them yourself with \`apiclient -u /settings/commit_and_apply -m POST\` and try again.\nPending settings: ${PENDING}"
fi
# Use our own transaction so we don't interfere with other changes
TX="enable-admin-container"
tjkirch marked this conversation as resolved.
Show resolved Hide resolved

echo "Setting admin container to enabled"
if ! apiclient -v -u /settings -m PATCH -d '{"host-containers": {"admin": {"enabled": true}}}'; then
if ! apiclient -v -u "/settings?tx=${TX}" -m PATCH -d '{"host-containers": {"admin": {"enabled": true}}}'; then
error "failed to change enabled setting of admin container"
fi

echo "Committing and applying changes"
if ! apiclient -v -u /settings/commit_and_apply -m POST; then
if ! apiclient -v -u "/tx/commit_and_apply?tx=${TX}" -m POST; then
error "failed to commit and apply settings"
fi

Expand Down
8 changes: 4 additions & 4 deletions workspaces/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ storewolf ensures the default values (defined in [defaults.toml](../models/defau
First, it has to create the data store directories and symlinks if they don’t exist.
Then, it goes key-by-key through the defaults, and if a key isn’t already set, sets it with the default value.

The settings are written to the *pending* section of the data store, meaning they’re not available until committed later by [settings-committer](#settings-committer).
The settings are written to the *pending* section of the data store, in a "thar-boot" transaction, which is used for startup coordination.
This means they’re not available until committed later by [settings-committer](#settings-committer).

If there are any pending settings in the data store, they’re discarded.
We’re unable to guarantee users that any pending settings they haven’t committed will survive a reboot, because we have to be able to commit changes ourselves during the boot process (see later services), and we don’t yet have a way of separating transactions.
If there are any pending transactions in the data store when storewolf starts, they’re discarded.

### apiserver

Expand Down Expand Up @@ -101,7 +101,7 @@ Pluto generates settings needed for Kubernetes configuration, for example cluste

[Further docs](settings-committer/)

This binary sends a commit request to the API, which moves all the pending settings from the above services into the live part of the data store.
This binary sends a commit request to the API (by default for the "thar-boot" transaction) which moves all the pending settings from the above services into the live part of the data store.
It's called as a prerequisite of other services, like [sundog](#sundog) and [settings-applier](#settings-applier), that rely on settings being committed.

### settings-applier
Expand Down
11 changes: 9 additions & 2 deletions workspaces/api/apiclient/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,23 @@ Getting settings:

```
apiclient -m GET -u /settings
apiclient -m GET -u /settings/pending
```

Changing settings:

```
apiclient -X PATCH -u /settings -d '{"timezone": "OldLosAngeles"}'
apiclient -m POST -u /settings/commit_and_apply
apiclient -m POST -u /tx/commit_and_apply
```

You can also check what you've changed but not commited by looking at the pending transaction:

```
apiclient -m GET -u /tx
```

(You can group changes into transactions by adding a parameter like `?tx=FOO` to the calls above.)

## apiclient library

The apiclient library provides simple, synchronous methods to query an HTTP API over a
Expand Down
11 changes: 9 additions & 2 deletions workspaces/api/apiclient/README.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,23 @@ Getting settings:

```
apiclient -m GET -u /settings
apiclient -m GET -u /settings/pending
```

Changing settings:

```
apiclient -X PATCH -u /settings -d '{"timezone": "OldLosAngeles"}'
apiclient -m POST -u /settings/commit_and_apply
apiclient -m POST -u /tx/commit_and_apply
```

You can also check what you've changed but not commited by looking at the pending transaction:

```
apiclient -m GET -u /tx
```

(You can group changes into transactions by adding a parameter like `?tx=FOO` to the calls above.)

## apiclient library

{{readme}}
Expand Down
14 changes: 9 additions & 5 deletions workspaces/api/apiserver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@ The interface is documented in [OpenAPI format](https://swagger.io/docs/specific
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 pending until a commit API is called.
Pending settings can be retrieved from `/settings/pending` to see what will change.
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 `commit` API call, pending settings are made live.
Upon making an `apply` API call, an external settings applier tool is called to apply the changes to the system and restart services as necessary.
There's also a `commit_and_apply` API to do both, which is the most common case.
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.
Expand Down
Loading