From 723f2d471679d4f2081b8cca82346f93f906fc26 Mon Sep 17 00:00:00 2001 From: Steve Kemp Date: Tue, 13 Nov 2012 16:16:18 +0000 Subject: added test-case to cover basic file-parsing. --- parser/parser.rb | 360 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 185 insertions(+), 175 deletions(-) (limited to 'parser') diff --git a/parser/parser.rb b/parser/parser.rb index a3f7246..4612001 100755 --- a/parser/parser.rb +++ b/parser/parser.rb @@ -29,15 +29,13 @@ require 'json' # # TODO: # -# 1. Break parse_file down into repeated calls to parse_line, to allow test -# cases to be written. +# 1. Explicitly abort and panic on malformed lines. # -# 2. Explicitly abort and panic on malformed lines. +# 2. Implement HTTP-fetching for macro-bodies. # -# 3. Implement HTTP-fetching for macro-bodies. # # Steve -# -- +# -- # class MonitorConfig @@ -65,8 +63,7 @@ class MonitorConfig @file = filename if ( @file.nil? || ( ! File.exists?( @file) ) ) - puts "Missing configuration file" - exit( 0 ) + raise ArgumentError, "Missing configuration file!" end end @@ -112,6 +109,10 @@ class MonitorConfig + def macros + @MACROS + end + # # Is the given string of text a macro? # @@ -129,208 +130,217 @@ class MonitorConfig end - - - # - # Parse the configuration file, named in our constructor. + # Parse a single line from the configuration file. # - def parse_file() + def parse_line( line ) + # - # Parse the configuration file on the command line + # A blank line, or a comment may be skipped. # - File.open( @file, "r").each_line do |line| - - # - # A blank line, or a comment may be skipped. - # - next if ( ( line =~ /^#/ ) || ( line.length < 1 ) ) + return if ( ( line =~ /^#/ ) || ( line.length < 1 ) ) - # specification of mauve-server to which we should raise our alerts to. - next if ( line =~ /Mauve\s+server(.*)source/ ) - - - # - # Look for macro definitions, inline - # - if ( line =~ /^([A-Z]_+)\s+are\s+fetched\s+from\s+([^\s]+)\.?/ ) - define_macro( line ) + # + # The specification of mauve-server to which we should raise our alerts to. + # + return if ( line =~ /Mauve\s+server(.*)source/ ) - elsif ( line =~ /^([0-9A-Z_]+)\s+(is|are)\s+/ ) - define_macro( line ) - elsif ( line =~ /\s+must\s+ping/ ) + # + # Look for macro definitions, inline + # + if ( line =~ /^([A-Z]_+)\s+are\s+fetched\s+from\s+([^\s]+)\.?/ ) + define_macro( line ) - # - # Target - # - targets = Array.new + elsif ( line =~ /^([0-9A-Z_]+)\s+(is|are)\s+/ ) + define_macro( line ) - # - # Fallback target is the first token on the line - # - target = line.split( /\s+/)[0] + elsif ( line =~ /\s+must\s+ping/ ) + # + # Target + # + targets = Array.new - # - # If the target is a macro - # - if ( is_macro?( target ) ) - targets = get_macro_targets(target) + # + # Fallback target is the first token on the line + # + target = line.split( /\s+/)[0] + + + # + # If the target is a macro + # + if ( is_macro?( target ) ) + targets = get_macro_targets(target) + else + targets.push( target ) + end + + # + # The alert-failure message + # + alert = "Ping failed" + if ( line =~ /otherwise '([^']+)'/ ) + alert=$1.dup + end + + # + # Store the test(s) + # + targets.each do |host| + test = { + :target_host => host, + :test_type => "ping", + :test_alert => alert + } + + if ( !ENV['DUMP'].nil? ) + puts ( test.to_json ) else - targets.push( target ) + @queue.put( test.to_json ) end - - # - # The alert-failure message - # - alert = "Ping failed" - if ( line =~ /otherwise '([^']+)'/ ) - alert=$1.dup - end - + end + + elsif ( line =~ /\s+must\s+run\s+([^\s]+)\s+/i ) + + # + # Get the service we're testing, and remove any trailing "." + # + # This handles the case of: + # + # LINN_HOSTS must run ssh. + # + service = $1.dup + service.chomp!(".") + + # + # Target of the service-test. + # + targets = Array.new + target = line.split( /\s+/)[0] + + # + # If the target is a macro + # + if ( is_macro?( target ) ) + targets = get_macro_targets( target ) + else + targets.push( target ) + end + + # + # Alert text + # + alert = "#{service} failed" + if ( line =~ /otherwise '([^']+)'/ ) + alert=$1.dup + end + + # + # All our service tests require a port - we setup the defaults here, + # but the configuration file will allow users to specify an alternative + # via " on XXX ". + # + case service + when /ssh/ then + port=22 + when /jabber/ then + port=5222 + when /ldap/ then + port=389 + when /^https$/ then + port=443 + when /^http$/ then + port=80 + when /rsync/i then + port=873 + when /ftp/i then + port=21 + when /telnet/i then + port=23 + when /smtp/i then + port=25 + end + + # + # But allow that to be changed + # + # e.g. + # + # must run ssh on 33 otherwise .. + # must run ftp on 44 otherwise .. + # must run http on 8000 otherwise .. + # + if ( line =~ /\s+on\s+([0-9]+)/ ) + port = $1.dup + end + + targets.each do |host| + + test = { + :target_host => host, + :test_type => service, + :test_port => port, + :test_alert => alert + } + # - # Store the test(s) + # HTTP-tests will include the expected result in one of two + # forms: # - targets.each do |host| - test = { - :target_host => host, - :test_type => "ping", - :test_alert => alert - } - - if ( !ENV['DUMP'].nil? ) - puts ( test.to_json ) - else - @queue.put( test.to_json ) - end - end - - elsif ( line =~ /\s+must\s+run\s+([^\s]+)\s+/i ) - + # must run http with status 200 # - # Get the service we're testing, and remove any trailing "." + # must run http with content 'text' # - # This handles the case of: + # If those are sepcified then include them here. # - # LINN_HOSTS must run ssh. + # Note we're deliberately fast and loose here - which allows both to be specified # - service = $1.dup - service.chomp!(".") - + # http://example.vm/ must run http with status 200 and content 'OK' otherwise 'boo!'. # - # Target of the service-test. # - targets = Array.new - target = line.split( /\s+/)[0] + if ( line =~ /\s+with\s+status\s+([0-9]+)\s+/ ) + test[:http_status]=$1.dup + end + if ( line =~ /\s+with\s+content\s+'([^']+)'/ ) + test[:http_text]=$1.dup + end # - # If the target is a macro + # We've parsed(!) the line. Either output the JSON to the console + # or add to the queue. # - if ( is_macro?( target ) ) - targets = get_macro_targets( target ) + if ( !ENV['DUMP'].nil? ) + puts ( test.to_json ) else - targets.push( target ) + @queue.put( test.to_json ) end + end + else + puts "Unknown line: #{line}" if ( line.length > 2 ) + end + end - # - # Alert text - # - alert = "#{service} failed" - if ( line =~ /otherwise '([^']+)'/ ) - alert=$1.dup - end - # - # All our service tests require a port - we setup the defaults here, - # but the configuration file will allow users to specify an alternative - # via " on XXX ". - # - case service - when /ssh/ then - port=22 - when /jabber/ then - port=5222 - when /ldap/ then - port=389 - when /^https$/ then - port=443 - when /^http$/ then - port=80 - when /rsync/i then - port=873 - when /ftp/i then - port=21 - when /telnet/i then - port=23 - when /smtp/i then - port=25 - end + # + # Parse the configuration file, named in our constructor. + # + def parse_file() + # + # Parse the configuration file on the command line + # + File.open( @file, "r").each_line do |line| + parse_line( line) + end + end - # - # But allow that to be changed - # - # e.g. - # - # must run ssh on 33 otherwise .. - # must run ftp on 44 otherwise .. - # must run http on 8000 otherwise .. - # - if ( line =~ /\s+on\s+([0-9]+)/ ) - port = $1.dup - end - targets.each do |host| - - test = { - :target_host => host, - :test_type => service, - :test_port => port, - :test_alert => alert - } - - # - # HTTP-tests will include the expected result in one of two - # forms: - # - # must run http with status 200 - # - # must run http with content 'text' - # - # If those are sepcified then include them here. - # - # Note we're deliberately fast and loose here - which allows both to be specified - # - # http://example.vm/ must run http with status 200 and content 'OK' otherwise 'boo!'. - # - # - if ( line =~ /\s+with\s+status\s+([0-9]+)\s+/ ) - test[:http_status]=$1.dup - end - if ( line =~ /\s+with\s+content\s+'([^']+)'/ ) - test[:http_text]=$1.dup - end - - # - # We've parsed(!) the line. Either output the JSON to the console - # or add to the queue. - # - if ( !ENV['DUMP'].nil? ) - puts ( test.to_json ) - else - @queue.put( test.to_json ) - end - end +end - else - puts "Unknown line: #{line}" if ( line.length > 2 ) - end - end - end -end # # Entry-point to our code. -- cgit v1.2.1