#!/usr/bin/env ruby

require File.expand_path('../../lib/riemann/tools', __FILE__)

class Riemann::Tools::Resmon
  include Riemann::Tools
  require 'nokogiri'
  require 'faraday'

  opt :resmon_hostfile, 'File with hostnames running Resmon (one URI per line)', type: :string
  opt :read_timeout, 'Faraday read timeout', type: :int, default: 2
  opt :open_timeout, 'Faraday open timeout', type: :int, default: 1
  opt :fqdn, 'Use FQDN for event host'


  def initialize
    @hosts = File.read(options[:resmon_hostfile]).split("\n")
    super
  end


  # Work out the hostname to submit with the event
  def get_event_host(host)
    unless options[:fqdn]
      return host.split('.')[0]
    end
    return host
  end

  # Handles HTTP connections and GET requests safely
  def safe_get(uri, event_host)
      # Handle connection timeouts
      response = nil
      begin
        connection = Faraday.new(uri)
        response = connection.get do |req|
          req.options[:timeout] = options[:read_timeout]
          req.options[:open_timeout] = options[:open_timeout]
        end
      rescue => e
        report(:host => event_host,
          :service => "resmon",
          :state => "critical",
          :description => "HTTP connection error: #{e.class} - #{e.message}"
        )
      end
      response
  end

  def tick
    @hosts.each do |host|

      uri = URI(host)
      event_host = get_event_host(uri.host)

      response = safe_get(uri, event_host)
      next if response.nil?

      # Handle non-200 responses
      if response.status != 200
        report(:host => event_host,
          :service => "resmon",
          :state => "critical",
          :description => "HTTP connection error: #{response.status} - #{response.body}"
        )
        next
      else
        report(:host => event_host,
          :service => "resmon",
          :state => "ok",
          :description => "Resmon connection ok"
        )
        doc = Nokogiri::XML(response.body)
      end

      doc.xpath('//ResmonResults/ResmonResult').each do |result|
        timestamp = result.xpath('last_update').first.text
        result.xpath('metric').each do |metric|
          hash = {
            host: event_host,
            service: "#{result.attributes['module'].value}`#{result.attributes['service'].value}`#{metric.attributes['name'].value}",
            time: timestamp.to_i
          }

          case metric.attributes['type'].value
            when /[iIlL]/
              hash[:metric] = metric.text.to_i
            when 'n'
              hash[:metric] = metric.text.to_f
            when 's'
              hash[:description] = metric.text
            when '0'
              raise 'dunno what 0 is yet'
          end

          report(hash)
        end
      end
    end
  end
end

Riemann::Tools::Resmon.run