diff options
author | Patrick J Cherry <patrick@bytemark.co.uk> | 2011-04-13 17:03:16 +0100 |
---|---|---|
committer | Patrick J Cherry <patrick@bytemark.co.uk> | 2011-04-13 17:03:16 +0100 |
commit | 89a67770e66d11740948e90a41db6cee0482cf8e (patch) | |
tree | be858515fb789a89d68f94975690ab019813726c /lib/mauve/configuration.rb |
new version.
Diffstat (limited to 'lib/mauve/configuration.rb')
-rw-r--r-- | lib/mauve/configuration.rb | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/lib/mauve/configuration.rb b/lib/mauve/configuration.rb new file mode 100644 index 0000000..b11e1b5 --- /dev/null +++ b/lib/mauve/configuration.rb @@ -0,0 +1,484 @@ +# encoding: UTF-8 +require 'object_builder' +require 'mauve/server' +require 'mauve/web_interface' +require 'mauve/person' +require 'mauve/notification' +require 'mauve/alert_group' +require 'mauve/people_list' +require 'mauve/source_list' + +# Seconds, minutes, hours, days, and weeks... More than that, we +# really should not need it. +class Integer + def seconds; self; end + def minutes; self*60; end + def hours; self*3600; end + def days; self*86400; end + def weeks; self*604800; end + alias_method :day, :days + alias_method :hour, :hours + alias_method :minute, :minutes + alias_method :week, :weeks +end + +module Mauve + + ## Configuration object for Mauve. + # + # + # @TODO Write some more documentation. This is woefully inadequate. + # + # + # == How to add a new class to the configuration? + # + # - Add a method to ConfigurationBuilder such that your new object + # maybe created. Call it created_NEW_OBJ. + # + # - Create a new class inheriting from ObjectBuilder with at least a + # builder_setup() method. This should create the new object you want. + # + # - Define attributes for the new class are defined as "is_attribute". + # + # - Methods for the new class are defined as methods or missing_method + # depending on what one wishes to do. Remember to define a method + # with "instance_eval(&block)" if you want to call said block within + # the new class. + # + # - Add a "is_builder "<name>", BuilderCLASS" clause in the + # ConfigurationBuilder class. + # + # That should be it. + # + # @author Matthew Bloch, Yann Golanski + class Configuration + + class << self + attr_accessor :current + end + + attr_accessor :server + attr_accessor :last_alert_group + attr_reader :notification_methods + attr_reader :people + attr_reader :alert_groups + attr_reader :people_lists + attr_reader :source_lists + attr_reader :logger + + def initialize + @notification_methods = {} + @people = {} + @people_lists = {} + @alert_groups = [] + @source_lists = SourceList.new() + @logger = Log4r::Logger.new("Mauve") + + end + + def close + server.close + end + + end + + class LoggerOutputterBuilder < ObjectBuilder + + def builder_setup(outputter) + @outputter = outputter.capitalize+"Outputter" + + begin + Log4r.const_get(@outputter) + rescue + require "log4r/outputter/#{@outputter.downcase}" + end + + @args = {} + end + + def result + @result ||= Log4r.const_get(@outputter).new("Mauve", @args) + end + + def format(f) + result.formatter = Log4r::PatternFormatter.new(:pattern => f) + end + + def method_missing(name, value=nil) + if value.nil? + result.send(name.to_sym) + else + @args[name.to_sym] = value + end + end + + end + + class LoggerBuilder < ObjectBuilder + + is_builder "outputter", LoggerOutputterBuilder + + def builder_setup + logger = Log4r::Logger.new("Mauve") + @default_format = nil + @default_level = Log4r::RootLogger.instance.level + end + + def result + @result = Log4r::Logger['Mauve'] + end + + def default_format(f) + @default_formatter = Log4r::PatternFormatter.new(:pattern => f) + # + # Set all current outputters + # + result.outputters.each do |o| + o.formatter = @default_formatter if o.formatter.is_a?(Log4r::DefaultFormatter) + end + end + + def default_level(l) + if Log4r::Log4rTools.valid_level?(l) + @default_level = l + else + raise "Bad default level set for the logger #{l}.inspect" + end + + result.outputters.each do |o| + o.level = @default_level if o.level == Log4r::RootLogger.instance.level + end + end + + def created_outputter(outputter) + # + # Set the formatter and level for any newly created outputters + # + if @default_formatter + outputter.formatter = @default_formatter if outputter.formatter.is_a?(Log4r::DefaultFormatter) + end + + if @default_level + outputter.level = @default_level if outputter.level == Log4r::RootLogger.instance.level + end + + result.outputters << outputter + end + + end + + class ProcessorBuilder < ObjectBuilder + is_attribute "sleep_interval" + + def builder_setup + @result = Processor.instance + end + + def method_missing(name, value) + @args[name] = value + end + end + + class UDPServerBuilder < ObjectBuilder + is_attribute "port" + is_attribute "ip" + is_attribute "sleep_interval" + + def builder_setup + @result = UDPServer.instance + end + + def method_missing(name, value) + @args[name] = value + end + end + + class TimerBuilder < ObjectBuilder + is_attribute "sleep_interval" + + def builder_setup + @result = Timer.instance + end + + def method_missing(name, value) + @args[name] = value + end + + + end + + class HTTPServerBuilder < ObjectBuilder + + is_attribute "port" + is_attribute "ip" + is_attribute "document_root" + + def builder_setup + @result = HTTPServer.instance + end + + def method_missing(name, value) + @args[name] = value + end + + end + + class NotifierBuilder < ObjectBuilder + is_attribute "sleep_interval" + + def builder_setup + @result = Notifier.instance + end + + def method_missing(name, value) + @args[name] = value + end + + end + + class ServerBuilder < ObjectBuilder + + is_builder "web_interface", HTTPServerBuilder + is_builder "listener", UDPServerBuilder + is_builder "processor", ProcessorBuilder + is_builder "timer", TimerBuilder + is_builder "notifier", NotifierBuilder + + def builder_setup + @args = {} + end + + def result + @result = Mauve::Server.instance + @result.configure(@args) + @result.web_interface = @web_interface + @result + end + + def method_missing(name, value) + @args[name] = value + end + + def created_web_interface(web_interface) + @web_interface = web_interface + end + + def created_listener(listener) + @listener = listener + end + + def created_processor(processor) + @processor = processor + end + + def created_notifier(notifier) + @notifier = notifier + end + end + + class NotificationMethodBuilder < ObjectBuilder + + def builder_setup(name) + @notification_type = name.capitalize + @name = name + provider("Default") + end + + + def provider(name) + notifiers_base = Mauve::Notifiers + notifiers_type = notifiers_base.const_get(@notification_type) + @provider_class = notifiers_type.const_get(name) + end + + def result + @result ||= @provider_class.new(@name) + end + + def method_missing(name, value=nil) + if value + result.send("#{name}=".to_sym, value) + else + result.send(name.to_sym) + end + end + + end + + class PersonBuilder < ObjectBuilder + + def builder_setup(username) + @result = Person.new(username) + end + + is_block_attribute "urgent" + is_block_attribute "normal" + is_block_attribute "low" + + def all(&block); urgent(&block); normal(&block); low(&block); end + + def password (pwd) + @result.password = pwd.to_s + end + + def holiday_url (url) + @result.holiday_url = url + end + + def suppress_notifications_after(h) + raise ArgumentError.new("notification_threshold must be specified as e.g. (10 => 1.minute)") unless + h.kind_of?(Hash) && h.keys[0].kind_of?(Integer) && h.values[0].kind_of?(Integer) + @result.notification_thresholds[h.values[0]] = Array.new(h.keys[0]) + end + + end + + class NotificationBuilder < ObjectBuilder + + def builder_setup(*who) + who = who.map do |username| + #raise BuildException.new("You haven't declared who #{username} is") unless + # @context.people[username] + #@context.people[username] + if @context.people[username] + @context.people[username] + elsif @context.people_lists[username] + @context.people_lists[username] + else + raise BuildException.new("You have not declared who #{username} is") + end + end + @result = Notification.new(who, @context.last_alert_group.level) + end + + is_attribute "every" + is_block_attribute "during" + ##is_attribute "hours_in_day" + ##is_attribute "unacknowledged" + + end + + class AlertGroupBuilder < ObjectBuilder + + def builder_setup(name=anonymous_name) + @result = AlertGroup.new(name) + @context.last_alert_group = @result + end + + is_block_attribute "includes" + is_attribute "acknowledgement_time" + is_attribute "level" + + is_builder "notify", NotificationBuilder + + def created_notify(notification) + @result.notifications ||= [] + @result.notifications << notification + end + + end + + # New list of persons. + # @author Yann Golanski + class PeopleListBuilder < ObjectBuilder + + # Create a new instance and adds it. + def builder_setup(label) + pp label + @result = PeopleList.new(label) + end + + is_attribute "list" + + end + + # New list of sources. + # @author Yann Golanski + class AddSourceListBuilder < ObjectBuilder + + # Create the temporary object. + def builder_setup(label) + @result = AddSoruceList.new(label) + end + + # List of IP addresses or hostnames. + is_attribute "list" + + end + + + # this should live in AlertGroupBuilder but can't due to + # http://briancarper.net/blog/ruby-instance_eval_constant_scoping_broken + # + module ConfigConstants + URGENT = :urgent + NORMAL = :normal + LOW = :low + end + + class ConfigurationBuilder < ObjectBuilder + + include ConfigConstants + + is_builder "server", ServerBuilder + is_builder "notification_method", NotificationMethodBuilder + is_builder "person", PersonBuilder + is_builder "alert_group", AlertGroupBuilder + is_builder "people_list", PeopleListBuilder + is_builder "add_source_list", AddSourceListBuilder + is_builder "logger", LoggerBuilder + + def initialize + @context = @result = Configuration.new + # FIXME: need to test blocks that are not immediately evaluated + end + + def created_server(server) + raise ArgumentError.new("Only one 'server' clause can be specified") if + @result.server + @result.server = server + end + + def created_notification_method(notification_method) + name = notification_method.name + raise BuildException.new("Duplicate notification '#{name}'") if + @result.notification_methods[name] + @result.notification_methods[name] = notification_method + end + + def created_person(person) + name = person.username + raise BuildException.new("Duplicate person '#{name}'") if + @result.people[name] + @result.people[person.username] = person + end + + def created_alert_group(alert_group) + name = alert_group.name + raise BuildException.new("Duplicate alert_group '#{name}'") unless + @result.alert_groups.select { |g| g.name == name }.empty? + @result.alert_groups << alert_group + end + + # Create a new instance of people_list. + # + # @param [PeopleList] people_list The new list of persons. + # @return [NULL] nada. + def created_people_list(people_list) + label = people_list.label + raise BuildException.new("Duplicate people_list '#{label}'") if @result.people_lists[label] + @result.people_lists[label] = people_list + end + + # Create a new list of sources. + # + # @param [] add_source_list + # @return [NULL] nada. + def created_add_source_list(add_source_list) + @result.source_lists.create_new_list(add_source_list.label, + add_source_list.list) + end + + end + +end |