» Recipe: Event handler router
Typically you must configure a handler for each type of event you expect to encounter (more about events and handlers here). To change handler configuration, one must update the Serf configuration and reload the agent with a SIGHUP or a restart.
Thanks to the flexibility and open-endedness Serf offers for configuring and executing handlers, it is possible to achieve similar functionality by configuring only a single "router" handler, which never needs to be updated. This removes the orchestration work of reloading the agents by allowing one to simply drop new executables with predictable names into a directory.
Handler executables must be named by event type for this recipe to work
member-join). User events get prefixed with "user-", and queries with
What you will end up with is a directory structure that looks like this:
$ tree /etc/serf /etc/serf └── handlers ├── member-failed ├── member-join ├── member-leave ├── member-update ├── user-deploy └── query-uptime
» Handler code
The following code must be configured as the only handler for this recipe to work. It will act as a catch-all this way and be able to make decisions on what script handler to invoke based on the Serf environment variables.
#!/bin/sh HANDLER_DIR="/etc/serf/handlers" if [ "$SERF_EVENT" = "user" ]; then EVENT="user-$SERF_USER_EVENT" elif [ "$SERF_EVENT" = "query" ]; then EVENT="query-$SERF_QUERY_NAME" else EVENT=$SERF_EVENT fi HANDLER="$HANDLER_DIR/$EVENT" [ -f "$HANDLER" -a -x "$HANDLER" ] && exec "$HANDLER" || :
The pluginhook project offers an alternative way that enables multiple plugins to handle a hook, instead of only a single handler.
Using this enables a tree structure that looks like:
$ tree /etc/serf /etc/serf └── handlers ├── a-1st-plugin | ├── member-failed | ├── member-join | ├── member-leave | └── member-update ├── a-2nd-plugin | ├── member-update | ├── user-deploy | └── query-uptime └── an-nth-plugin ├── member-join └── member-leave
Using this requires only requires minor modifications to our handler script above:
#!/bin/sh HANDLER_DIR="/etc/serf/handlers" if [ "$SERF_EVENT" = "user" ]; then EVENT="user-$SERF_USER_EVENT" elif [ "$SERF_EVENT" = "query" ]; then EVENT="query-$SERF_QUERY_NAME" else EVENT=$SERF_EVENT fi cd $HANDLER_DIR pluginhook $EVENT
The serf-master project provides the same functionality but allows you to write handlers strictly in Python. Using serf-master might be a better approach if you are more comfortable with Python than Bash.