How to add an action to a charm

See also: Action

Contents:

  1. Define an action
  2. Observe the corresponding action event and define the event handler
  3. Verify the action

Define an action

In the charmcraft.yaml file of the charm, add an action definition. At the very minimum, make sure to include a name. The example below defines an action called snapshot which can be used to take a snapshot and save it to a file via the filename param.

actions:
  snapshot:
    description: Take a snapshot of the database.
    params:
      filename:
        type: string
        description: The name of the snapshot file.

See more: File charmcraft.yaml > actions

Observe the corresponding action event and define the event handler

In the src/charm.py file, in the __init__ function of your charm, set up an observer for the action event associated with your action and pair that with an event handler. For example, given the actions.yaml from the previous step:

self.framework.observe(self.on.grant_admin_role_action, self._on_grant_admin_role_action)

See more: Event <action name>-action

Now, in the body of the charm definition, define the action event handler. For example:

def _on_grant_admin_role_action(self, event):
    """Handle the grant-admin-role action."""
    # Fetch the user parameter from the ActionEvent params dict
    user = event.params["user"]
    # Do something useful with it
    cmd = ["/usr/bin/myapp", "roles", "system_admin", user]
    # Set a log message for the action
    event.log(f"Running this command: {' '.join(cmd)}")
    granted = subprocess.run(cmd, capture_output=True)
    if granted.returncode != 0:
        # Fail the action if there is an error
        event.fail(
            f"Failed to run '{' '.join(cmd)}'. Output was:\n{granted.stderr.decode('utf-8')}"
        )
    else:
        # Set the results of the action
        msg = f"Ran grant-admin-role for user '{user}'"
        event.set_results({"result": msg})

Verify the action

To verify that the action works as intended, pack your charm, update it in the Juju model, and run:

juju run <unit> grant-admin-role user=<the desired user>

See more: Juju | How to manage actions > Run an action

When you run an action via juju run, you either select a specific unit to run the action, or all units in your Juju application. Inside the unit(s) that will run the action, how the action is run depends on the type of the charm. If your charm is a machine charm, actions are executed on the same machine as the application. If your charm is a Kubernetes charm implementing the sidecar pattern, the charm action is run in the charm container.

Contributors: @mmkay

Last updated 2 months ago. Help improve this document in the forum.