Juju is all about events. Juju commands such as config
and relate
subscribe a given charm to some Juju events. And that has nothing to do with ops
.
Charms are short-lived processes. A charm is “woken up” (actually, started) by a Juju event. Charms themselves don’t really subscribe to anything: a framework.observe
call never leaves the charm; it is Juju (and perhaps to some degree pebble, when pebble “notices” become available?) that really “subscribes” and “wakes up” everything.
It is the world that has been pulled over your eyes to blind you from the truth. (The Matrix)
When ops
-based charms enter their __init__
, it’s already after ops has parsed some envvars and figured out the context. The familiar framework.observe(..., ...)
calls in charm code are just an abstraction for switch-case
. For trivial charms, it’s brilliant; for what we’re trying to accomplish, it doesn’t seem to scale:
- Hooks are processed in the order of the
observe
statements, but it’s quite implicit and bears unexpected behavior when someone refactors and changes some previously assumed order. - Emission of custom events often introduces unexpected ordering issues.
It seems that charming could be greatly simplified if charm.py
could be as simple as:
from ops.juju_context import (
context_from_environ,
PebbleReadyContext,
RelationChangedContext,
)
def update_cert(context):
def _update_sys():
context.container("workload_name").exec(
["update-ca-certificates", "--fresh"]
).wait()
if context.is_a(PebbleReadyContext.kind("workload_name")):
_update_sys()
elif context.is_a(RelationChangedContext.kind("tls-certificates")):
context.container("workload_name").push(
"/some/where.cert",
context.relation.data["foo"],
)
_update_sys()
def main():
context = context_from_environ()
if context.is_in([PebbleReadyContext, RelationChangedContext]):
update_cert(context)
if __name__ == "__main__":
main()
This way,
- Execution order is explicit.
- Hook context can be easily propagated downstream, so hook filtering (“observe”) can be done both upstream and downstream.
- Writing idempotent charms is more obvious.
- (Bonus) Clearer separation between Juju and
ops
.
If you find this intriguing, please join the conversation here or there.