# Event handling bundles and bodies @if minimum_version(3.9) bundle agent event_register(prefix, type, name, persistence, metadata) # @brief Register a `event_$(prefix)_$(type)_$(name)` class with meta=`metadata` # @param prefix The prefix (usually the issuing bundle name) # @param type The event type # @param name The event name # @param persistence the time, in minutes, the class should persist on disk (unless collected) # @param metadata A slist with the event metadata # # This bundle creates a class that conforms to the ad-hoc event protocol defined # herein. # # **See also:** `event_handle` { vars: "e" string => "event_$(prefix)_$(type)_$(name)"; "metadata_string" string => format("%S", metadata); classes: "$(e)" scope => "namespace", persistence => $(persistence), meta => { "event", "prefix=$(prefix)", "type=$(type)", "name=$(name)", @(metadata) }; reports: inform_mode:: "$(this.bundle): creating event $(e) persistent for $(persistence) minutes with metadata $(metadata_string)"; } body classes event_cancel_events(events) # @brief Cancel any `events` # @param events A slist of events to cancel { cancel_notkept => { @(events) }; cancel_kept => { @(events) }; cancel_repaired => { @(events) }; } bundle agent event_handle(prefix, type) # @brief Handle all the events matching `prefix` and `type` through delegation # @param prefix A prefix for the event, can be `.*` for all # @param type A type for the event, can be `.*` for all # # This bundle looks for all the event classes matching `prefix` and `type`, then # for all the bundles that have declared they can handle that prefix and type, # and then passes the corresponding event classes to each bundle. # # **See also:** `event_register` { vars: "events_prefix" slist => classesmatching("event_.*", "prefix=$(prefix)"); "events_type" slist => classesmatching("event_.*", "type=$(type)"); "events" slist => intersection(events_prefix, events_type); "events_string" string => format("%S", events); "handlers_prefix" slist => bundlesmatching("default:event_.*", format("event_prefix=(%s|ALL)", escape($(prefix)))); "handlers_type" slist => bundlesmatching("default:event_.*", format("event_type=(%s|ALL)", escape($(type)))); "handlers" slist => intersection(handlers_prefix, handlers_type); "handlers_string" string => format("%S", handlers); methods: "" usebundle => $(handlers)(@(events)), classes => event_cancel_events(@(events)); reports: inform_mode:: "$(this.bundle): with prefix $(prefix) and type $(type) found events $(events_string)"; "$(this.bundle): with prefix $(prefix) and type $(type) found handlers $(handlers_string)"; } bundle agent event_debug_handler(events) # @brief Debug all the events matching the meta tags `event_prefix` and `event_type` # @param events The list of events, passed from `event_handle` # # This is an event handler that just prints out all the events it finds. To be # registered as a handler, it must have the `meta tags` indicated below. # # **See also:** `event_handle`, `event_register` { meta: "tags" slist => { "event_handler", "event_prefix=.*", "event_type=.*" }; vars: "events_string" string => format("%S", events); "tags_string" string => format("%S", "$(this.bundle)_meta.tags"); reports: inform_mode:: "$(this.bundle): with tags $(tags_string) got events $(events_string)"; } bundle agent event_install_handler(events) # @brief Handle all the install events matching the meta tags `event_prefix` and `event_type` # @param events The list of events, passed from `event_handle` # # This is an event handler that just prints out all the install events it finds. # To be registered as a handler, it must have the `meta tags` indicated below. # The subtlety in `event_prefix=ALL` is that we want to match only # `event_handle(ANYTHING, "install")` but not `event_handle(".*", ANYTHING)`. If # you're confused, just remember: debug handlers use `event_prefix=.*` and # everything else uses `event_prefix=ALL`. # # **See also:** `event_handle`, `event_register` { meta: "tags" slist => { "event_handler", "event_prefix=ALL", "event_type=install" }; vars: "events_string" string => format("%S", events); "tags_string" string => format("%S", "$(this.bundle)_meta.tags"); reports: inform_mode:: "$(this.bundle): with tags $(tags_string) got events $(events_string)"; } bundle agent event_usage_example # @brief Simple demo of event_register and event_handle usage # # You can run it like this: `cf-agent -K ./event.cf -b event_usage_example` # Or for extra debugging, you can run it like this: `cf-agent -KI ./event.cf -b event_usage_example` # # **See also:** `event_handle`, `event_register` # # Expected output with `-KI`: # # ``` # R: event_register: creating event event_event_usage_example_restart_apache persistent for 1440 minutes with metadata { } # R: event_register: creating event event_event_usage_example_install_php persistent for 2880 minutes with metadata { } # R: event_install_handler: with tags { "event_handler", "event_prefix=ALL", "event_type=install" } got events { "event_event_usage_example_install_php" } # R: event_handle: with prefix event_usage_example and type install found events { "event_event_usage_example_install_php" } # R: event_handle: with prefix event_usage_example and type install found handlers { "default:event_install_handler" } # R: event_debug_handler: with tags { "event_handler", "event_prefix=.*", "event_type=.*" } got events { "event_event_usage_example_restart_apache", "event_event_usage_example_install_php" } # R: event_handle: with prefix .* and type .* found events { "event_event_usage_example_restart_apache", "event_event_usage_example_install_php" } # R: event_handle: with prefix .* and type .* found handlers { "default:event_debug_handler" } # ``` { vars: "empty" slist => {}; methods: # register a restart event named "apache" with persistence = 1 day "" usebundle => event_register($(this.bundle), "restart", "apache", 1440, @(empty)); # 1 day # register an install event named "php" with persistence = 2 days "" usebundle => event_register($(this.bundle), "install", "php", 2880, @(empty)); # the following can be run immediately, or up to 2 days later to collect # the install event above "" usebundle => event_handle($(this.bundle), "install"); # the following can be run immediately, or up to 1 day later to collect # the restart event above "" usebundle => event_handle(".*", ".*"); } @endif