diff options
| author | Steve Kemp <steve@steve.org.uk> | 2012-11-13 16:16:18 +0000 | 
|---|---|---|
| committer | Steve Kemp <steve@steve.org.uk> | 2012-11-13 16:16:18 +0000 | 
| commit | 723f2d471679d4f2081b8cca82346f93f906fc26 (patch) | |
| tree | e978d5ac404e5686d22bdc8717ba24de4a95ed7b /parser | |
| parent | affe98261e29ec044066c36cf625772eb0f48154 (diff) | |
  added test-case to cover basic file-parsing.
Diffstat (limited to 'parser')
| -rwxr-xr-x | parser/parser.rb | 360 | 
1 files changed, 185 insertions, 175 deletions
| 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. | 
