Event (Scenario)

Scenario > Event

In Scenario, the Event object corresponds to the homonym Juju data structure – a Juju event.

See more: Event (in Juju)

Like a Juju event, the scenario.Event data structure encapsulates some environment variables that the charm is being executed with and roughly represents the “reason why” the charm is being executed.

The fundamental piece of information carried by an Event is therefore the name of the ‘hook’ that the Juju controller has decided should be executed by this charm.

Basic usage

In many situations, the name of the event is enough for Scenario to work.

Look at the code snippet below:

from scenario import Context, State
from charm import MyCharm

ctx = Context(MyCharm)
ctx.run(event="update-status", state=State())

Context.run will first cast the string 'update-status' to an Event data structure. The following code is therefore equivalent:

from scenario import Event
...
ctx.run(event=Event("update-status"), state=State())

Event metadata: generic usage

Depending on the hook, certain additional environment variables need to be set for ops to function, just like the Juju unit agent guarantees them to be present when the charm is run for real.

For example, relation events require a JUJU_RELATION_ID envvar to be set.

In those situations, you cannot simply use strings to refer to events, but you need to provide an Event object to which you can pass some additional required metadata. Scenario’s runtime will use that information to populate the envvars that ops expects to be set.

For example, if you want to simulate relation events in Scenario, you need to:

from scenario import Event, Relation
...
relation = Relation('foo')
ctx.run(
    event=Event("foo-relation-changed", relation=relation), 
    state=State(relations=[relation])
)

The same holds for workload events and secret events.

For workload (pebble-ready) events, the reason we need to associate the container with the event is that the Framework uses an envvar (and not the event name) to determine which container the event is about. Scenario needs that information, similarly, for injecting that envvar into the charm’s runtime.

For secret events, the reason is similar: the operator framework uses several envvars set by Juju to determine the secret ID the event is about and other required metadata.

Syntactic sugar

As a way to simplify the user experience, all event types that are associated to some operator data structure can be obtained from the data structure itself.

So instead of doing

relation = Relation('foo')
relation_changed_evt = Event('foo_relation_changed', relation=relation)

you can simply:

relation_changed_evt = Relation('foo').changed_event

And similarly for Container and Secret.

Relation method event
Relation('foo').changed_event foo_relation_changed
Relation('foo').joined_event foo_relation_joined
Relation('foo').broken_event foo_relation_broken
Relation('foo').created_event foo_relation_created
Relation('foo').departed_event foo_relation_departed
Container method event
Container('foo').pebble_ready_event foo_pebble_ready
Secret method event
Secret('id').changed_event secret_changed
Secret('id').rotate_event secret_rotate
Secret('id').expired_event secret_expired
Secret('id').remove_event secret_remove