When developing a charm or an integration, you often find yourself in need of directly manipulating unit statuses, relation data, or other pieces of a charm’s state
.
For example, if you’ve been fiddling with charm code or monkey-testing a development deployment and:
- a relation ends up containing corrupted data
- a charm ends up in an unexpected state
- you want to on purpose corrupt some data to see if the charm can recover
Suppose you have a model called demo-1
containing a tester
app.
If you type jhack scenario snapshot tester/0 --format json
, without arguments, you will obtain a printout containing the whole charm state: its relations (and their data), its networks, its stored state, its deferred events, containers, and so on.
To edit the relation data for some endpoint of this charm (or multiple at once, why not?), we pipe this out to a file and edit it in there:
jhack scenario snapshot tester/0 --format json --include r > ./tester-state.json
The --include r
argument means we only want to collect relation state. This significantly speeds up execution.
We change the ‘host’ value of the demo-ingress
relation’s local app databag and then run:
jhack scenario state-apply tester/0 ./tester-state.json
And the relation data gets updated!
If you want to see the commands that jhack state-apply
is emitting on your behalf to do this magic, add a --dry-run
flag and see:
Limitations and future work
Note that at the moment there are a few limitations to state-apply
:
-
additive mutations only: in order to ‘remove’ a key-value pair from a databag, you need to explicitly, manually set the value to
""
(the empty string). - I didn’t yet implement state-apply for secrets, (container) filesystem contents, deferred events and stored state.
- you can only state-apply from the perspective of a single charm! This means that if you
state-apply foo/0 ./mystate.json
, you can only mutate whatfoo/0
could mutate. This means you have to respect leadership and general databag ownership rules: you can only write app data if you’re leader, and mutating databags that belong to remote units will have no effect: you need to state-apply on that unit in order to change its side of a relation.