Hook

In Juju, a hook is a notification from the controller agent through the unit agent to the charm that the internal representation of Juju has changed in a way that requires a reaction from the charm so that the unit’s state and the controller’s state can be reconciled.

For a charm written with Ops, Juju hooks are translated into Ops events = ‘events’, specifically, into classes that inherit from HookEvent.

List of hooks

<action>-action

What triggers it?

A charm user invoking the action name from the Juju CLI (juju run <unit/0> foo, juju run <unit/0> <unit/1> foo).

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

All the units that the charm user has run the action on.

collect-metrics (deprecated)

Exposes metrics for external monitoring.

config-changed

What triggers it?

The config-changed hook always runs once immediately after the install hook, and likewise after the upgrade-charm hook. It also runs whenever the service configuration changes, and when recovering from transient unit agent errors.

The config-changed event is emitted in response to various events throughout a charm’s lifecycle:

  • In response to a configuration change using the GUI or CLI.

  • On networking changes (if the machine reboots and comes up with a different IP).

  • Some time between the install event and the start event in the startup phase of a charm’s lifecycle.
    (The config_changed event will ALWAYS happen at least once, when the initial configuration is accessed from the charm.)

Callbacks associated with this event should ensure the current charm configuration is properly reflected in the underlying application configuration. Invocations of associated callbacks should be idempotent and should not make changes to the environment, or restart services, unless there is a material change to the charm’s configuration, such as a change in the port exposed by the charm, addition or removal of a relation which may require a database migration or a “scale out” event for high availability, or similar.

Callbacks must not assume that the underlying applications or services have been started.

There are many situations in which config-changed can occur. In many of them, the event being fired does not mean that the config has in fact changed, though it may be useful to execute logic that checks and writes workload configuration. For example, since config-changed is guaranteed to fire once during the startup sequence, some time after install is emitted, charm authors might omit a call to write out initial workload configuration during the install hook, relying on that configuration to be written out in their config-changed handler instead.

Scenario

Example Command

Resulting Events

Create unit

juju deploy foo
juju add-unit foo

install -> config-changed -> start

Configure a unit

juju config foo bar=baz

config-changed

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

<container>-pebble-change-updated

What triggers it?

Which hooks can be guaranteed to have fired before it, if any?

Which environment variables is it executed with?

Who gets it?

<container>-pebble-check-failed

Kubernetes sidecar charms only.

Added in Juju 3.6.

What triggers it?

A Pebble check passing the failure threshold.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

<container>-pebble-check-recovered

Kubernetes sidecar charms only.

Added in Juju 3.6.

What triggers it?

A Pebble check passing after previously reaching the failure threshold.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

<container>-pebble-custom-notice

Kubernetes sidecar charms only

What triggers it?

A Pebble notice of type “custom” occurring.

Which hooks can be guaranteed to have fired before it, if any?

Which environment variables is it executed with?

Who gets it?

<container>-pebble-ready

Kubernetes sidecar charms only.

What triggers it?

The requested container being ready.

The pebble-ready event doesn’t guarantee the workload container is still up. For example, if you manually kubectl patch during (for example) install, then you may receive this event after the old workload is down but before the new one is up. For this reason it’s essential, even in pebble-ready event handlers, to catch ConnectionError when using Pebble to make container changes. There is a Container.can_connect() method, but note that this is a point-in-time check, so just because can_connect() returns True doesn’t mean it will still return True moments later. So, code defensively to avoid race conditions.

Moreover, as pod churn can occur at any moment, pebble-ready events can be received throughout any phase of a charm’s lifecycle. Each container could churn multiple times, and they all can do so independently from one another. In short, the charm should make no assumptions at all about the moment in time at which it may or may not receive pebble-ready events, or how often that can occur. The fact that the charm receives a pebble-ready event indicates that the container has just become ready (for the first time, or again, after pod churn), therefore you typically will need to reconfigure your workload from scratch every single time.

This feature of pebble-ready events make them especially suitable for a holistic handling pattern.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

<endpoint>-relation-broken

What triggers it?

  • A non-peer relation being removed;

  • a unit participating in a non-peer relation being removed, even if the relation is otherwise still alive (through other units); or

  • an application involved in a non-peer relation being removed.

This hook is fired only once per unit per relation and is the exact inverse of relation-created. relation-created indicates that relation data can be accessed; relation-broken indicates that relation data can no longer be read-written.

The hook indicates that the relation under consideration is no longer valid, and that the charm’s software must be configured as though the relation had never existed. It will only be called after every hook bound to <endpoint>-relation-departed has been run. If a hook bound to this event is being executed, it is guaranteed that no remote units are currently known locally.

It is important to note that the -broken hook might run even if no other units have ever joined the relation. This is not a bug: even if no remote units have ever joined, the fact of the unit’s participation can be detected in other hooks via the relation-ids tool, and the -broken hook needs to execute to allow the charm to clean up any optimistically-generated configuration.

Also, it’s important to internalise the fact that there may be multiple relations in play with the same name, and that they’re independent: one -broken hook does not mean that every such relation is broken.

For a peer relation, <peer relation name>-relation-broken will never fire, not even during the teardown phase.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

<endpoint>-relation-changed

What triggers it?

The relation-changed hook for a given unit always runs once immediately following the relation-joined hook for that unit, and subsequently whenever the related unit changes its settings (by calling relation-set and exiting without error). Note that immediately only applies within the context of this particular runtime relation – that is, when foo-relation-joined is run for unit bar/99 in relation id foo:123, the only guarantee is that/ the next hook to be run in relation id foo:123 will be foo-relation-changed for bar/99. Unit hooks may intervene, as may hooks for other relations, and even for other foo relations.

relation-changed is emitted when another unit involved in the relation (from either side) touches the relation data. Relation data is the way for charms to share non-sensitive information (for sensitive information, juju secrets are on their way in juju 3).

For centralized data – for example, a single password or api token that one application generates to share with another application, we suggest that charm authors use the application data, rather than individual unit data. This data can only be written to by the application leader, and each remote unit related to that application will receive a single relation-changed event when it changes.

Hooks bound to this event should be the only ones that rely on remote relation settings. They should not error if the settings are incomplete, since it can be guaranteed that when the remote unit or application changes its settings again, this event will fire once more.

Charm authors should expect this event to fire many times during an application’s life cycle. Units in an application are able to update relation data as needed, and a relation-changed event will fire every time the data in a relation changes. Since relation data can be updated on a per unit bases, a unit may receive multiple relation-changed events if it is related to multiple units in an application and all those units update their relation data.

This event is guaranteed to follow immediately after each relation-joined. So all juju commands that trigger relation-joined will also cause relation-changed to be fired. So typical scenarios include:

Scenario

Example Command

Resulting Events

Add an integration

juju integrate foo:a bar:b

(all foo and bar units)
*-relation-created -> *-relation-joined -> *-relation-changed

Additionally, a unit will receive a relation-changed event every time another unit involved in the relation changes the relation data. Suppose foo receives an event, and while handling it the following block executes:

# in charm `foo`
relation.data[self.unit]['foo'] = 'bar'  # set unit databag
if self.unit.is_leader():
    relation.data[self.app]['foo'] = 'baz'  # set app databag

When the hook returns, bar will receive a relation-changed event.

Note

Note that units only receive relation-changed events for other units’ changes. This can matter in a peer relation, where the application leader will not receive a relation-changed event for the changes that it writes to the peer relation’s application data bag. If all units, including the leader, need to react to a change in that application data, charm authors may include an inline .emit() for the <name>_relation_changed event on the leader.

When is data synchronized?
Relation data is sent to the controller at the end of the hook’s execution. If a charm author writes to local relation data multiple times during the a single hook run, the net change will be sent to the controller after the local code has finished executing. The controller inspects the data and determines whether the relation data has been changed. Related units then get the relation-changed event the next time they check in with the controller.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

<endpoint>-relation-created

What triggers it?

relation-created is a “setup” event and, emitted when an application is related to another. Its purpose is to inform the newly related charms that they are entering the relation.

If Juju is aware of the existence of the relation “early enough”, before the application has started (i.e. before the application has started, i.e., before the start has run), this event will be fired as part of the setup phase. An important consequence of this fact is, that for all peer-type relations, since juju is aware of their existence from the start, those relation-created events will always fire before start.

Similarly, if an application is being scaled up, the new unit will see relation-created events for all relations the application already has during the Setup phase.

Scenario

Example Command

Resulting Events

Integrate

juju integrate foo bar

(all foo & bar units): *-relation-created --> *-relation-joined -> *-relation-changed

Scale up an integrated app

juju add-unit -n1 foo

(new foo unit): install -> *-relation-created -> leader-settings-changed -> config-changed -> start

In the following scenario, one deploys two applications and relates them “very early on”. For example, in a single command.

Scenario

Example Command

Resulting Events

Deploy and quickly integrate

juju deploy foo; juju deploy bar; juju integrate foo bar

(all units): same as previous case.

Starting from when *-relation-created is received, relation data can be read-written by units, up until when the corresponding *-relation-broken is received.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

<endpoint>-relation-departed

What triggers it?

-relation-departed; emitted when a unit departs from an existing relation.

The “relation-departed” hook for a given unit always runs once when a related unit is no longer related. After the “relation-departed” hook has run, no further notifications will be received from that unit; however, its settings will remain accessible via relation-get for the complete lifetime of the relation.

relation-departed is a “teardown” event, emitted when a remote unit departs a relation. This event is the exact inverse of relation-joined.

*-relation-broken events are emitted on a unit when a related application is scaled down. Suppose you have two related applications, foo and bar. If you scale down bar, all foo units will receive a *-relation-departed event. The departing unit will receive a *-relation-broken event as part of its teardown sequence. Also removing a relation altogether will trigger *-relation-departed events (followed by *-relation-broken) on all involved units.

Scenario

Example Command

Resulting Events

Unit removal

juju remove-unit --num-units 1 bar

(foo/0): *-relation-departed
(bar/0): *-relation-broken -> stop -> ...

Integration removal

juju remove-relation foo bar

(all units): *-relation-departed -> *-relation-broken

Of course, removing the application altogether, instead of a single unit, will have a similar effect and also trigger these events.

Both relation-departed and relation-broken will always fire, regardless of how the relation is terminated.

Note

For a peer relation, the relation itself will never be destroyed until the application is removed and no units remain, at which point there won’t be anything to call the relation-broken hook on anyway.

Note that on relation removal (juju remove-relation); only when all -departed hooks for such a relation and all callback methods bound to this event have been run for such a relation, the unit agent will fire relation-broken.

The relation-departed event is seen both by the leaving unit(s) and the remaining unit(s):

  • For remaining units (those which have joined and not yet departed), this event is emitted once for each departing unit and in no particular order. At the point when a remaining unit receives a relation-departed, it’s perfectly probable (although not guaranteed) that the system running that unit has already shut down.

  • For departing units, this event is emitted once for each remaining unit.

A unit’s relation settings persist beyond its own departure from the relation; the final unit to depart a relation marked for termination is responsible for destroying the relation and all associated data.

relation-changed ISN’T fired for removed relations. If you want to know when to remove a unit from your data, that would be relation-departed.

During a relation-departed hook, relation settings can still be read (with relation-get) and a relation can even still be set (with relation-set), by explicitly providing the relation ID. All units will still be able to see all other units, and any unit can call relation-set to update their own published set of data on the relation. However, data updated by the departing unit will not be published to the remaining units. This is true even if there are no units on the other side of the relation to be notified of the change.

If any affected unit publishes new data on the relation during the relation-departed hooks, the new data will NOT be see by the departing unit (it will NOT receive a relation-changed; only the remaining units will).

Note

(juju internals) When a unit’s own participation in a relation is known to be ending, the unit agent continues to uphold the guaranteed event ordering, but within those constraints, it will run the fewest possible hooks to notify the charm of the departure of each individual remote unit.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

<endpoint>-relation-joined

What triggers it?

-relation-joined; emitted when a new unit joins in an existing relation.

The “relation-joined” hook always runs once when a related unit is first seen.

relation-joined is emitted when a unit joins in an existing relation. The unit will be a local one in the case of peer relations, a remote one otherwise.

By the time this event is emitted, the only available data concerning the relation is

  • the name of the joining unit.

  • the private-address of the joining unit.

In other words, when this event is emitted the remote unit has not yet had an opportunity to write any data to the relation databag. For that, you’re going to have to wait for the first {ref}``relation-changed <event-relation-name-relation-changed> event.

From the perspective of an application called foo, which can relate to an application called bar:

Scenario

Example Command

Resulting Events

Create unit

juju integrate foo bar

*-relation-created -> *-relation-joined -> *-relation-changed

Create unit

juju add-unit bar -n 1

*-relation-joined -> *-relation-changed

Note

For a peer relation, <peer relation name>-relation-joined will be received by peers some time after a new peer unit appears. (And during its setup, that new unit will receive a <peer relation name>-relation-created).

Note

For a peer relation, <peer relation name>-relation-joined will only be emitted if the scale is larger than 1. In other words, applications with a scale of 1 do not see peer relation joined/departed events. If you are using peer data as a means for persistent storage, then use peer relation-created instead.

relation-joined can fire multiple times per relation, as multiple units can join, and is the exact inverse of relation-departed. That means that if you consider the full lifecycle of an application, a unit, or a model, the net difference of the number of *-relation-joined events and the number of *-relation-departed events will be zero.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

install

What triggers it?

The install hook always runs once, and only once, before any other hook.

fired when juju is done provisioning the unit.

The install event is emitted once per unit at the beginning of a charm’s lifecycle. Associated callbacks should be used to perform one-time initial setup operations and prepare the unit to execute the application. Depending on the charm, this may include installing packages, configuring the underlying machine or provisioning cloud-specific resources.

Therefore, ways to cause install to occur are:

Scenario

Example Command

Resulting Events

Create unit

juju deploy foo
juju add-unit foo

install -> config-changed

Note:

  • Typically, operations performed on install should also be considered for upgrade-charm.

  • In some cases, config-changed can be used instead of install and upgrade-charm because it is guaranteed to fire after both.

The install event is emitted once per unit at the beginning of a charm’s lifecycle. Associated callbacks should be used to perform one-time initial setup operations and prepare the unit to execute the application. Depending on the charm, this may include installing packages, configuring the underlying machine or provisioning cloud-specific resources.

Therefore, ways to cause install to occur are:

Scenario

Example Command

Resulting Events

Create unit

juju deploy foo
juju add-unit foo

install -> config-changed

Note:

  • Typically, operations performed on install should also be considered for upgrade-charm.

  • In some cases, config-changed can be used instead of install and upgrade-charm because it is guaranteed to fire after both.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

leader-deposed

What triggers it?

TBA

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

leader-elected

What triggers it?

The leader-elected event is emitted for a unit that is elected as leader. Together with leader-settings-changed, it is one of two “leadership events”. A unit receiving this event can be guaranteed that it will have leadership for approximately 30 seconds (from the moment the event is received). After that time, juju might have elected a different leader. The same holds if the unit checks leadership by Unit.is_leader(): if the result is True, then the unit can be ensured that it has leadership for the next 30s.

Leadership can change while a hook is running. (You could start a hook on unit/0 who is the leader, and while that hook is processing, you lose network connectivity for a long time [more than 30s], and then by the time the hook notices, juju has already moved on to another leader.)

Juju doesn’t guarantee that a leader will see every event: if the leader unit is overloaded long enough for the lease to expire (>30s), then juju will elect a different leader. Events that fired in between would be received units that are not leader yet or not leader anymore.

  • leader-elected is always emitted after peer-relation-created during the Startup phase. However, by the time relation-created runs, juju may already have a leader. This means that, in peer-relation-created handlers, it might already be the case that self.unit.is_leader() returns True even though the unit did not receive a leadership event yet. If the starting unit is not leader, it will receive a {ref}``leader-settings-changed <event-leader-settings-changed> instead.

Scenario

Example Command

Resulting Events

Start new unit

juju deploy foo
juju add-unit foo

(new leader) install -> (*peer)-relation-created -> leader-elected

  • During the Operation phase, leadership changes can in principle occur at any time, for example if the leader unit is unresponsive for some time. When a leader loses leadership it will only receive a leader-settings-changed event, just like all the other non-leader units. The new leader will receive leader-elected.

It is not possible to select a specific unit and ‘promote’ that unit to leader, or ‘demote’ an existing leader unit. Juju has control over which unit will become leader after the current leader is gone.

Note

However, you can cause leadership change by destroying the leader unit or killing the jujud-machine service in operator charms.

  • non-k8s models: juju remove-unit <leader_unit>

  • operator charms: juju ssh -m <id> -- systemctl stop jujud-machine-<id>

  • sidecar charms: ssh into the charm container, source the /etc/profile.d/juju-introspection.sh script, and then get access to a few cli tools, including juju_stop_unit.

That will cause the lease to expire within 60s, and another unit of the same application will be elected leader and receive leader-elected.

  • If the leader unit is removed, then one of the remaining units will be elected as leader and see the leader-elected event; all the other remaining units will see leader-settings-changed. If the leader unit was not removed, no leadership events will be fired on any units.

Note that unless there’s only one unit left, it is impossible to predict or control which one of the remaining units will be elected as the new leader.

Scenario

Example Command

Resulting Events

Current leader loses leadership

juju remove-unit foo

(new leader): leader-elected
(all other foo units): leader-settings-changed

Which hooks can be guaranteed to have fired before it, if any?

Which environment variables is it executed with?

Who gets it?

The leader unit, once Juju elects one.

leader-settings-changed

What triggers it?

The leader-settings-changed event is emitted when a leadership change occurs, all units that are not the new leader will receive the event. Also, this event is emitted if changes have been made to leader settings.

During startup sequence, for all non-leader units:

Scenario

Example Command

Resulting Events

Create unit

juju deploy foo -n 2

install -> leader-settings-changed -> config-changed -> start (non-leader)

If the leader unit is rescheduled, or removed entirely. When the new leader is elected:

Scenario

Example Command

Resulting Events

Removal of leader

juju remove-unit foo/0 (foo/0 being leader)

leader-settings-changed (for all non leaders)

Since this event needs leadership changes to trigger, check out triggers for leader-elected <6471md> as the same situations apply for leader-settings-changed.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

All follower units, when a new leader is chosen.

post-series-upgrade

Removed in Juju 4.

What triggers it?

Fired after the series upgrade has taken place.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

pre-series-upgrade

Removed in Juju 4.

What triggers it?

This event is triggered when an operator runs juju upgrade-series <machine> prepare ... from the command line. Read here to learn more about the series upgrade process. This event hook allows charm units on the machine being upgraded to do any necessary tasks prior to the upgrade process beginning (which may involve e.g. being rebooted, etc.).

Scenario

Example command

Resulting events

Upgrade series

juju upgrade-series <machine> prepare

pre-series-upgrade -> (events on pause until upgrade completes)

Notably, after this event fires and before the post-series-upgrade event fires, juju will pause events and changes for all units on the machine being upgraded. There will be no config-changed, update-status, etc. events to interrupt the upgrade process until after the upgrade process is completed via juju upgrade-series <machine> complete.

Caution

Leadership is pinned during the series upgrade process. Even if the current leader dies or is removed, re-election will not occur for applications on the upgrading machine until the series upgrade operation completes.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

remove

What triggers it?

The remove event is emitted only once per unit: when the Juju controller is ready to remove the unit completely. The stop event is emitted prior to this, and all necessary steps for handling removal should be handled there.

On Kubernetes charms, the remove event will occur on pod churn, when the unit dies. On machine charms, the stop event will be fired when a unit is put down.

Scenario

Example Command

Resulting Events

Remove unit

juju remove-unit foo/0 (on machine) or
juju remove-unit --num-units 1 foo (on k8s)

stop -> [relation/storage teardown] -> remove

Of course, removing an application altogether will result in these events firing on all units.

If the unit has any relations active or any storage attached at the time the removal occurs, these will be cleaned up (in no specific order) between stop and remove. This means the unit will receive stop -> (*-relation-broken | *-storage-detaching) -> remove.

The remove event is the last event a unit will ever see before going down, right after stop. It is exclusively fired when the unit is in the Teardown phase.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

secret-changed

What triggers it?

A secret owner publishing a new secret revision.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

All units observing a secret.

Note

Upon receiving that event (or at any time after that) an observer can choose to:

  • Start tracking the latest revision (“refresh”)

  • Inspect the latest revision values, without tracking it just yet (“peek”)

Once all observers have stopped tracking a specific outdated revision, the owner will receive a secret-remove hook to be notified of that fact, and can then remove that revision.

secret-expired

Currently supported only for charm secrets.

Added in Juju 3.0.2

What triggers it?

For a secret set up with an expiry date, the fact of the secret’s expiration time elapsing.

Which hooks can be guaranteed to have fired before it, if any?

Which environment variables is it executed with?

Who gets it?

The secret owner.

secret-remove

Currently supported only for charm secrets.

Who gets it?

The secret owner.

What triggers it?

A secret revision no longer having any observers and thus being safe to remove.

This situation can occur when:

  • All observers tracking a now-outdated revision have updated to tracking a newer one, so the old revision can be removed.

  • No observer is tracking an intermediate revision, and a newer one has already been created. So there is a orphaned revision which no observer will ever be able to peek or update to, because there is already a newer one the observer would get instead.

In short, the purpose of this event is to notify the owner of a secret that a specific revision of it is safe to remove: no charm is presently observing it or ever will be able to in the future.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

secret-rotate

Currently supported only for charm secrets.

Added in Juju 3.0.2

What triggers it?

For a secret with a rotation policy, the secret’s rotation policy elapsing – the hook keeps firing until the secret has been rotated.

Which hooks can be guaranteed to have fired before it, if any?

Which environment variables is it executed with?

Who gets it?

The secret owner.

start

What triggers it?

A unit’s initialization being complete.

This can occur:

  • when the unit is being created

  • (Kubernetes:) on pod churn

  • (Kubernetes:) on cluster reboot

  • on charm upgrades

For Kubernetes charms, this occurs on pod churn as well.

Note

Callback methods bound to the event should be used to ensure that the charm’s software is in a running state. Note that the charm’s software should be configured to persist in a started state without further intervention from Juju or an administrator.

Note

In kubernetes sidecar charms, Juju provides no ordering guarantees regarding start and *-pebble-ready.

Which hooks can be guaranteed to have fired before it, if any?

The config-changed hook. (The start hook is fired immediately after.)

Which environment variables is it executed with?

Who gets it?

Any unit.

stop

What triggers it?

The Juju controller being ready to destroy the unit.

This can occur:

  • when the unit is being removed (whether explicitly or through the application as a whole being removed)

  • (Kubernetes:) on pod churn

The stop hook is the one-before-last hook the unit will receive before being destroyed (the last one being remove).

Note

When handling the stop event, charms should gracefully terminate all services for the supported application and update any relevant cluster/leader information to remove or update any data relating to the current unit. Additionally, the charm should ensure that the software will not automatically start again on reboot.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

Any unit.

<storage>-storage-attached

What triggers it?

A storage volume having been attached to the charm’s host machine or container and being ready to be interacted with.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

<storage>-storage-detaching

What triggers it?

A request to detach storage having been processed.

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

TBA

update-status

What triggers it?

Nothing in particular – this hooks is fired automatically by Juju at regular intervals (default: 5m; can be changed, e.g., juju model-config update-status-hook-interval=1m).

Note

This event can be used to monitor the health of deployed charms and determine the status of long running tasks (such as package installation), updating the status message reported to Juju accordingly.

Historically, this hook was intended to allow authors to run code that gets the “health” of the application. However, health checks can also be specified via Pebble.

Since the update-status interval is model-wide (not per application) and is set by the user (for example, it can be set to once per hour), charms should not rely on it for critical operations.

In integration tests, unless specifically testing the update-status hook, you may want to “disable” it so it doesn’t interfere with the test. This can be achieved by setting the interval to e.g. 1h at the beginning of the test.

Which hooks can be guaranteed to have fired before it, if any?

As it is triggered periodically, the update-status can happen in-between any other charm events.

Which environment variables is it executed with?

TBA

Who gets it?

TBA

By default, the update-status event is triggered by the Juju controller at 5-minute intervals.

upgrade-charm

What triggers it?

The upgrade-charm hook always runs once immediately after the charm directory contents have been changed by an unforced charm upgrade operation, and may do so after a forced upgrade; but will not be run after a forced upgrade from an existing error state. (Consequently, neither will the config-changed hook that would ordinarily follow the upgrade-charm.

The event is emitted after the new charm code has been unpacked - therefore this event is handled by the callback method bound to the event in the new codebase.

The associated callback should be used to reconcile the current state written by an older version into whatever form is required by the current charm version. An example of a reconciliation that needs to take place is to migrate an old relation data schema to a new one.

Important

  • Typically, operations performed on upgrade-charm should also be considered for install.

  • In some cases, config-changed can be used instead of install and upgrade-charm because it is guaranteed to fire after both.

  • Note that you cannot upgrade a Charmhub charm to the same version. However, upgrading a local charm from path works (and goes through the entire upgrade sequence) even if the charm is exactly the same.

Scenario

Example command

Resulting events

Upgrade Kubernetes charm

juju refresh

stop (old charm) -> upgrade-charm (new charm) -> config-changed -> leader-settings-changed (if the unit is not the leader) -> start -> *-pebble-ready

Upgrade machine charm

juju refresh

upgrade-charm -> config-changed -> leader-settings-changed (if the unit is not the leader) -> start

Attach resource

juju attach-resource foo bar=baz

(same as upgrade)

Important

An upgrade does NOT trigger any relation hooks (unless relation data is intentionally modified in one of the upgrade sequence hooks).

Which hooks can be guaranteed to have fired before it, if any?

TBA

Which environment variables is it executed with?

TBA

Who gets it?

Any unit.