diff options
| author | Steve Kemp <steve@steve.org.uk> | 2012-11-22 16:35:32 +0000 | 
|---|---|---|
| committer | Steve Kemp <steve@steve.org.uk> | 2012-11-22 16:35:32 +0000 | 
| commit | e09de14c2b7164b82b2c79aee5b9c4424d43093e (patch) | |
| tree | 445d1ebdf7e4b49824553480161c24478f6bba5f /lib/custodian | |
| parent | 16552979333ca759de6aba535b4e6b46a5070f2c (diff) | |
  Updated to rename the class.
Diffstat (limited to 'lib/custodian')
| -rw-r--r-- | lib/custodian/parser.rb | 513 | 
1 files changed, 258 insertions, 255 deletions
| diff --git a/lib/custodian/parser.rb b/lib/custodian/parser.rb index 7f5838e..cd53e1b 100644 --- a/lib/custodian/parser.rb +++ b/lib/custodian/parser.rb @@ -4,16 +4,16 @@ require 'net/https'  require 'uri' -require 'custodian/protocoltest/tcp.rb' -require 'custodian/protocoltest/dns.rb' -require 'custodian/protocoltest/ftp.rb' -require 'custodian/protocoltest/http.rb' -require 'custodian/protocoltest/jabber.rb' -require 'custodian/protocoltest/ldap.rb' -require 'custodian/protocoltest/ping.rb' -require 'custodian/protocoltest/rsync.rb' -require 'custodian/protocoltest/ssh.rb' -require 'custodian/protocoltest/smtp.rb' +require 'custodian/protocoltest/tcp' +require 'custodian/protocoltest/dns' +require 'custodian/protocoltest/ftp' +require 'custodian/protocoltest/http' +require 'custodian/protocoltest/jabber' +require 'custodian/protocoltest/ldap' +require 'custodian/protocoltest/ping' +require 'custodian/protocoltest/rsync' +require 'custodian/protocoltest/ssh' +require 'custodian/protocoltest/smtp'  require 'custodian/testfactory' @@ -34,353 +34,356 @@ require 'custodian/testfactory'  # Steve  # --  # -class MonitorConfig +module Custodian -  # -  # A hash of macros we found. -  # -  attr_reader :MACROS +  class Parser -  # -  # The filename that we're going to parse. -  # -  attr_reader :filename +    # +    # A hash of macros we found. +    # +    attr_reader :MACROS -  # -  # Timeout period, in seconds, that we encode into test objects. -  # -  attr_reader :timeout +    # +    # The filename that we're going to parse. +    # +    attr_reader :filename -  # -  # An array of test-objects, which are subclasses of our test-factory. -  # -  attr_reader :jobs +    # +    # Timeout period, in seconds, that we encode into test objects. +    # +    attr_reader :timeout +    # +    # An array of test-objects, which are subclasses of our test-factory. +    # +    attr_reader :jobs -  # -  # Constructor -  # -  def initialize( filename ) +    # +    # Constructor +    # +    def initialize( filename ) -    @MACROS  = Hash.new() -    @jobs    = Array.new() -    @file    = filename -    @timeout = 60 -    raise ArgumentError, "Missing configuration file!" if ( @file.nil? ) -    raise ArgumentError, "File not found: #{@file}" unless ( File.exists?( @file) ) -  end +      @MACROS  = Hash.new() +      @jobs    = Array.new() +      @file    = filename +      @timeout = 60 +      raise ArgumentError, "Missing configuration file!" if ( @file.nil? ) +      raise ArgumentError, "File not found: #{@file}" unless ( File.exists?( @file) ) +    end -  # -  # Retrieve a HTTP page from the web - this is used for macro-expansion -  # -  # NOTE:  This came from sentinel. -  # -  def getURL (uri_str) -    begin -      uri_str = 'http://' + uri_str unless uri_str.match(/^http/) -      url = URI.parse(uri_str) -      http = Net::HTTP.new(url.host, url.port) -      http.open_timeout = @timeout -      http.read_timeout = @timeout -      if (url.scheme == "https") -        http.use_ssl = true -        http.verify_mode = OpenSSL::SSL::VERIFY_NONE -      end +    # +    # Retrieve a HTTP page from the web - this is used for macro-expansion +    # +    # NOTE:  This came from sentinel. +    # +    def getURL (uri_str) +      begin +        uri_str = 'http://' + uri_str unless uri_str.match(/^http/) +        url = URI.parse(uri_str) +        http = Net::HTTP.new(url.host, url.port) +        http.open_timeout = @timeout +        http.read_timeout = @timeout + +        if (url.scheme == "https") +          http.use_ssl = true +          http.verify_mode = OpenSSL::SSL::VERIFY_NONE +        end -      response = nil +        response = nil -      if nil == url.query -        response = http.start { http.get(url.path) } -      else -        response = http.start { http.get("#{url.path}?#{url.query}") } -      end +        if nil == url.query +          response = http.start { http.get(url.path) } +        else +          response = http.start { http.get("#{url.path}?#{url.query}") } +        end -      if ( response.code.to_i != 200 ) -        puts "Status code of #{uri_str} was #{response.code}" -        puts "ABORTING" -        exit( 0 ) -      end +        if ( response.code.to_i != 200 ) +          puts "Status code of #{uri_str} was #{response.code}" +          puts "ABORTING" +          exit( 0 ) +        end -      case response -      when Net::HTTPRedirection -      then -        newURL = response['location'].match(/^http/)? -        response['Location']:uri_str+response['Location'] -        return( getURL(newURL) ) -      else -        return response.body -      end +        case response +        when Net::HTTPRedirection +        then +          newURL = response['location'].match(/^http/)? +          response['Location']:uri_str+response['Location'] +          return( getURL(newURL) ) +        else +          return response.body +        end -    rescue Errno::EHOSTUNREACH => ex -      raise ex, "no route to host" -    rescue Timeout::Error => ex -      raise ex, "timeout" -    rescue Errno::ECONNREFUSED => ex -      raise ex, "connection refused" +      rescue Errno::EHOSTUNREACH => ex +        raise ex, "no route to host" +      rescue Timeout::Error => ex +        raise ex, "timeout" +      rescue Errno::ECONNREFUSED => ex +        raise ex, "connection refused" +      end      end -  end - - - -  # -  #  Define a macro, from the configuration file. -  # -  def define_macro( line ) -    name = nil -    val  = Array.new -    # -    #  Get the name of the macro. -    # -    name = $1.dup if ( line =~ /^([0-9A-Z_]+)\s+/ )      # -    #  Get the value +    #  Define a macro, from the configuration file.      # -    if ( line =~ /fetched\s+from\s+(.*)[\r\n\.]*$/ ) +    def define_macro( line ) +      name = nil +      val  = Array.new        # -      #  HTTP-fetch +      #  Get the name of the macro.        # -      uri = $1.dup.chomp(".") - -      text = getURL(uri) -      text.split( /[\r\n]/ ).each do |line| -        val.push( line ) if ( line.length() > 0) -      end +      name = $1.dup if ( line =~ /^([0-9A-Z_]+)\s+/ ) -    elsif ( line =~ /\s(is|are)\s+(.*)\.+$/ )        # -      #  Literal list of hosts +      #  Get the value        # -      hosts = $2.dup +      if ( line =~ /fetched\s+from\s+(.*)[\r\n\.]*$/ ) -      # -      #  If there is " and " then tokenize -      # -      if ( hosts =~ /\s+and\s+/ ) -        tmp = hosts.split( /\s+and\s+/ ) -        tmp.each do |entry| -          val.push( entry ) -        end -      else          # -        # Otherwise a single host +        #  HTTP-fetch          # -        val.push( hosts ) -      end -    end +        uri = $1.dup.chomp(".") -    if ( is_macro?( name ) ) -      raise ArgumentError, "The macro #{name} is already defined" -    end +        text = getURL(uri) +        text.split( /[\r\n]/ ).each do |line| +          val.push( line ) if ( line.length() > 0) +        end -    @MACROS[name] = val - -    true -  end +      elsif ( line =~ /\s(is|are)\s+(.*)\.+$/ ) +        # +        #  Literal list of hosts +        # +        hosts = $2.dup +        # +        #  If there is " and " then tokenize +        # +        if ( hosts =~ /\s+and\s+/ ) +          tmp = hosts.split( /\s+and\s+/ ) +          tmp.each do |entry| +            val.push( entry ) +          end +        else +          # +          # Otherwise a single host +          # +          val.push( hosts ) +        end +      end +      if ( is_macro?( name ) ) +        raise ArgumentError, "The macro #{name} is already defined" +      end -  # -  #  Return a hash of our current macro-definitions. -  # -  #  This is used only by the test-suite. -  # -  def macros -    @MACROS -  end +      @MACROS[name] = val +      true +    end -  # -  # Is the given string of text a macro? -  # -  def is_macro?( name ) -    !(@MACROS[name]).nil? -  end +    # +    #  Return a hash of our current macro-definitions. +    # +    #  This is used only by the test-suite. +    # +    def macros +      @MACROS +    end -  # -  # Return an array of hosts if the given string was a macro identifier. -  # -  def get_macro_targets( name ) -    @MACROS[name] -  end +    # +    # Is the given string of text a macro? +    # +    def is_macro?( name ) +      !(@MACROS[name]).nil? +    end -  # -  #  Return multiple copies of a line for each macro-target -  # -  def expand_macro( input ) -    r = Array.new() -    if ( input =~ /^(\S+)\s+(.*)$/ ) -      macro=$1.dup -      rest=$2.dup +    # +    # Return an array of hosts if the given string was a macro identifier. +    # +    def get_macro_targets( name ) +      @MACROS[name]      end -    if ( is_macro?( macro ) ) -      get_macro_targets(macro).each do |host| -        r.push( "#{host} #{rest}" ) -      end -    else -      r.push( input ) -    end -    r -  end +    # +    #  Return multiple copies of a line for each macro-target +    # +    def expand_macro( input ) +      r = Array.new() -  # -  # Parse a single line from the configuration file. -  # -  def parse_line( line ) +      if ( input =~ /^(\S+)\s+(.*)$/ ) +        macro=$1.dup +        rest=$2.dup +      end -    line.chomp! if ( !line.nil? ) -    # -    # A blank line, or a comment may be skipped. -    # -    return nil if ( ( line.nil? ) || ( line =~ /^#/ ) || ( line.length < 1 ) ) +      if ( is_macro?( macro ) ) +        get_macro_targets(macro).each do |host| +          r.push( "#{host} #{rest}" ) +        end +      else +        r.push( input ) +      end -    # -    # The specification of mauve-server to which we should raise our alerts to. -    # -    return nil if ( line =~ /Mauve\s+server(.*)source/ ) +      r +    end      # -    #  Look for macro definitions, inline +    # Parse a single line from the configuration file.      # -    if ( line =~ /^([0-9A-Z]_+)\s+are\s+fetched\s+from\s+([^\s]+)\.?/ ) -      define_macro( line ) +    def parse_line( line ) -    elsif ( line =~ /^([0-9A-Z_]+)\s+(is|are)\s+/ ) -      define_macro( line ) +      line.chomp! if ( !line.nil? ) -    elsif ( line =~ /^(\S+)\s+must\s+ping(.*)/ ) -      # -      #  Ping is a special case because the configuration file entry -      # would read: -      # -      #  $FOO must ping otherwise ...        # -      #  All other tests are of the form: +      # A blank line, or a comment may be skipped.        # -      #  $FOO must run XXX ... otherwise ... -      # -      #  If we clevery rewrite the line into: -      # -      #  ... must run ping ... +      return nil if ( ( line.nil? ) || ( line =~ /^#/ ) || ( line.length < 1 ) ) +        # -      #  We can avoid duplicating the macro-expansion, etc. +      # The specification of mauve-server to which we should raise our alerts to.        # -      pre  = $1.dup -      post = $2.dup -      new_line = "#{pre} must run ping #{post}" -      return( parse_line( new_line ) ) +      return nil if ( line =~ /Mauve\s+server(.*)source/ ) -    elsif ( line =~ /^\S+\s+must\s+run\s+([^\s]+)(\s+|\.|$)/i )        # -      # Expand the macro if we should +      #  Look for macro definitions, inline        # -      tests = expand_macro( line ) +      if ( line =~ /^([0-9A-Z]_+)\s+are\s+fetched\s+from\s+([^\s]+)\.?/ ) +        define_macro( line ) -      # -      # The array of objects we will return to the caller. -      # -      ret = Array.new() +      elsif ( line =~ /^([0-9A-Z_]+)\s+(is|are)\s+/ ) +        define_macro( line ) -      # -      # For each host in our possibly-macro-expanded list: -      # -      tests.each do |macro_expanded| +      elsif ( line =~ /^(\S+)\s+must\s+ping(.*)/ ) +        # +        #  Ping is a special case because the configuration file entry +        # would read: +        # +        #  $FOO must ping otherwise ... +        # +        #  All other tests are of the form: +        # +        #  $FOO must run XXX ... otherwise ... +        # +        #  If we clevery rewrite the line into: +        # +        #  ... must run ping ... +        # +        #  We can avoid duplicating the macro-expansion, etc. +        # +        pre  = $1.dup +        post = $2.dup +        new_line = "#{pre} must run ping #{post}" +        return( parse_line( new_line ) ) + +      elsif ( line =~ /^\S+\s+must\s+run\s+([^\s]+)(\s+|\.|$)/i ) + +        # +        # Expand the macro if we should +        # +        tests = expand_macro( line ) + +        # +        # The array of objects we will return to the caller. +        # +        ret = Array.new() -        job = nil +        # +        # For each host in our possibly-macro-expanded list: +        # +        tests.each do |macro_expanded| -        begin -          job = Custodian::TestFactory.create( macro_expanded ) -          ret.push( job ) -        rescue => ex -          puts "ERROR: #{ex}" -          return nil +          job = nil + +          begin +            job = Custodian::TestFactory.create( macro_expanded ) +            ret.push( job ) +          rescue => ex +            puts "ERROR: #{ex}" +            return nil +          end          end -      end -      ret -    else -      raise ArgumentError, "Unknown line: '#{line}'" +        ret +      else +        raise ArgumentError, "Unknown line: '#{line}'" +      end      end -  end -  # -  # Parse the configuration file which was named in our constructor. -  # -  # This updates our @jobs array with the tests - and optionally -  # invokes our callback. -  # -  def parse_file( &callback ) -      # -    #  Parse the configuration file on the command line +    # Parse the configuration file which was named in our constructor.      # -    File.open( @file, "r").each_line do |line| - -      ret = parse_line( line) +    # This updates our @jobs array with the tests - and optionally +    # invokes our callback. +    # +    def parse_file( &callback )        # -      #  The return value from the parse_line method -      # is either: -      # -      #  Array -> An array of test-objects. +      #  Parse the configuration file on the command line        # -      #  nil   -> The line was a macro. -      #         or -      #           The line was a comment. -      # -      # -      if ( ret.kind_of?( Array ) ) -        ret.each do |probe| -          @jobs.push( probe ) -        end -      end +      File.open( @file, "r").each_line do |line| -      # -      # If there was an optional callback then invoke it -      # with the newly added job/jobs. -      # -      if ( block_given? ) +        ret = parse_line( line) + +        # +        #  The return value from the parse_line method +        # is either: +        # +        #  Array -> An array of test-objects. +        # +        #  nil   -> The line was a macro. +        #         or +        #           The line was a comment. +        # +        #          if ( ret.kind_of?( Array ) )            ret.each do |probe| -            yield probe.to_s +            @jobs.push( probe ) +          end +        end + +        # +        # If there was an optional callback then invoke it +        # with the newly added job/jobs. +        # +        if ( block_given? ) +          if ( ret.kind_of?( Array ) ) +            ret.each do |probe| +              yield probe.to_s +            end            end          end        end      end -  end -end +  end +end | 
