Juju Charms `basic` Layer Hooks

I have had a difficult time trying to figure out how to properly implement a Juju charm using the newer reactive model. The online documentation is incomplete and sometimes incorrect. There are very few examples available.

We developed a charm that deployed a VM into a MaaS server. Once we got it working, we handed it off to QA. Complaint: When they executed juju remove-application, the container for the charm was destroyed, but the VM persisted. They asked me to add support for destroying the VM, too. Sounds reasonable.

If you’ve played with reactive charms, you know that they are built from layers. Each layer provides its own set of capabilities. Most reactive charms are built on the basic layer. I searched a bit and found that there is a set of hooks available in the basic layer:

  • config-changed
  • install
  • leader-elected
  • leader-settings-changed
  • start
  • stop
  • upgrade-charm
  • update-status
  • pre-series-upgrade
  • post-series-upgrade

Each of these hooks is called when certain events or conditions occur with the charm. In the context of the task at hand, the stop hook gets called when the application is being removed, a.k.a. destroyed. The solution, then, is to create a function in reactive/app-name-here.py. The difficult part of the solution is finding out what the code should look like.

After much searching and trial and error, I came across something in the github repository for the reactive package itself. It ended up being a simple, two-line solution in reactive/app-name-here.py:

...
from reactive import hook
...

...
@hook('stop')
def my_destroy_function():
    # Define function here
...

That’s it. All that searching and failing. All one needs to do is import reactive.hook, then decorate the appropriate functions with the name of the hooks they react to. Yeesh. I wish the Juju Charms documentation included practical examples.