How to run any hook with a remote context

Hello there!

I was debugging a problem where I have a code section that is reachable both by config-changed and relation-changed. Within that code section is a relation_get() call with no arguments which works differently whether it is invoked by config-changed (usually without remote context) or relation-changed (always with remote context) hooks.

While I was investigating I got very curious if there was a way to invoke the config-changed hook with a remote context to have the code behave as I wanted without any code changes.

With the help of fellow charmers, I was able to accomplish it through the following command:

juju-run -r $(juju-run nova-compute/0 "relation-ids cloud-compute") --remote-unit nova-cloud-controller/0 nova-compute/0 ./hooks/config-changed

The command above needs to be run from within the unit you want the hook executed, as opposed to “juju run” that runs from outside of the unit.

I found the knowledge of such command to be very interesting from a developer standpoint, while it is important to note that its usage on charms can cause unexpected results, as some hooks (like config-changed) are not designed to be run with a remote context and may end up taking different actions.

Alternatively, if you find yourself in a position to run such command (or compelled to, in order to workaround an issue), I would recommend consider doing a relation-set to trigger a relation-changed hook instead if it could perhaps also address the problem, through the following command:

juju run -u nova-cloud-controller/0 "relation-set -r cloud-compute:15 a=0"

The relation-set command above will trigger a relation-changed hook with remote context, and the dummy data “a=0” should be ignored by the charm. You can later remove it by repeating the command with “a=” argument (it will trigger the relation-changed hook again).

Regards,

Rodrigo

2 Likes

There is also the juju-run utility (not to be confused with the juju run command!) within the hook context to feed information back to the controller:

I think the relation_get() call will simply read the JUJU_RELATION_ID environment variable to allow you to run it without passing it the relation ID. I think you can make it run as if it was in a *-relation-changed hook simply by setting the JUJU_RELATION_ID environment variable before running it.

I can’t tell for sure if this would help you in this particular case though.

The environment variables are only there to aid the charm. The information is not passed back via the CLI tool to the agent.
https://github.com/juju/juju/blob/develop/worker/uniter/runner/jujuc/relation-get.go

Instead, when a hook is fired, first the Agent sets up an associated context, which it uses to fill in any information not supplied by the hook tool. So it isn’t sufficient to just set env variables and then run your hook, as you have to tell the agent what context it should be in.

I know you can already use juju run --unit u/0 hooks/config-changed if you just wanted to cause the charm to run its hook in the context of a unit. We should add support for something like juju run --unit u/0 --relation-id X hooks/db-relation-changed to allow you to directly trigger other hooks in the context of a relation. As you noted we have that for juju-run when you’re already on the unit, we should just allow exposing that to the CLI.

1 Like