Juju relation order and waiting?

I am now working with relating my first two charms

Charm 1 - contains a server that will listen on 1 of 2 possible ports at any time… 4001 or 4002. I can successfully detect the state, when it is listening to 1 or none of these ports… and want to pass on that port in my relation… let’s call it Charm1_Port

Charm 2 - contains a basic type of server (not HTTP, but Thrift)… which when related with Charm 1, will retrieve the Charm1_IP, and Charm1_Port

MY issue now is… when I do

juju relate charm1 charm2

All the config of charm2 seems to run all the way to the end… BEFORE charm 1 has even had a chance once to set relation-set … so everything is coming back empty.

What is the thing I should do if I am using just bash hooks here ? Sleep the charm 2 relation-* hooks ??

Are you writing a classic charm, a reactive charm, or a charm with the new operator framework?

Under the hood what you want to do is have Charm1 update its relation data with the port once it detects that it has a port. This will cause a relation-changed hook to fire on Charm2 – you can hang any additional setup off that hook, with no sleeps required.

This process is abstracted away in the reactive and operator frameworks, but the principal is the same: Charm1 should update the relation data, and Charm2 should have an event that fires when the relation data changes.

It is a “Classic” bash hooks charm for now… I started with Operator but it was a bit overkill to start with…

here is Charm1s hook mysocket-relation-created and I simply doubled up and copied it to mysocket-relation-joined as well…

on charm1

#!/bin/sh

juju-log -l "INFO" "CREATED : We are attempting to set relations under created!"

relation-set hostname=$(unit-get private-address)

if lsof -Pi :4002 -sTCP:LISTEN -t >/dev/null ; then
        echo "4002 running"
        relation-set port=4002
	juju-log -l "WARNING" "CREATED: We relation-set port"
fi
if lsof -Pi :4001 -sTCP:LISTEN -t >/dev/null ; then
        echo "4001 running"
        relation-set port=4001
	juju-log -l "WARNING" "CREATED: We relation-set port"
fi

our_host=$(relation-get hostname)
second_try=$(unit-get private-address)

juju-log -l "WARNING" "CREATED: We set host in created! $our_host"
juju-log -l "WARNING" "CREATED: We set host in created! $second_try"

and indeed I have a matching relation hook for charm2 on both joined and created…

is the doubling of this relation-set causing the issues? If I sleep charm2s relation hooks things go great… but if I drop the sleep… charm1 just cannot barrel ahead … and gets passed over too late to affect the relation-get <var_name>

on charm2

mysocket-relation-changed/created/joined

#!/bin/bash

sleep 10

juju-log -l "INFO" "<name_of_hook_here> called with $JUJU_REMOTE_UNIT remote unit"

charm1_server_address=$(relation-get hostname)
juju-log -l "WARNING" "<name_of_hook_here> We got a server address $charm1_server_address"
config-set server_address $charm1_server_address

active_port=$(relation-get port)

if [ -z $active_port ] ; then
	juju-log -l "WARNING" "<name_of_hook_here> no active port"
else
	juju-log -l "WARNING" "<name_of_hook_here> We got a active port $active_port"
	config-set active_port $active_port
fi

juju-log -l "WARNING" "<name_of_hook_here> hostname seen as $hostname"

EDIT: By the way… I am also looking at how you set variables from bash hooks … I thought it would be config-set but it says that command is not found

I want to store these relation get results somehow so that the Thrift server in Charm 2 can either be rebooted/retarted with new parameters at its runtime… or I edit key value pairs in the config file, and my server reads that as its config… either way is fine for me really…

I think after some debugging I am getting the hang of it

So in charm 1’s relation-created I need to set all the relation set variables… I CANNOT rely on them to be in charm2’s relation-created… instead wait until both of those are done, then in relation joined I can know… both created stages have completed and this I can retrieve any configs set for the relation…

EDIT: Nope… seems I need the 5 second sleep or else the data is not there

You relation-change/created/joined script on charm 2 should work. It will run whenever a relation is added, or the relation data is updated. What you want to do is make sure that the script exits cleanly (and thus does not create an error) when the port doesn’t exist yet. You also may need to restart your service for the config to take effect.

Keep in mind that those scripts will run whenever the hook is invoked in juju. The relation created hook will run only once. But the relation changed script will run whenever the relation data is updated.

1 Like