#!/usr/bin/ruby

require 'symbiosis/monitor/check'

# Check that dovecot is running and responding on TCP
class DovecotCheck < Symbiosis::Monitor::Check
  def initialize(connections)
    super pid_file: '/var/run/dovecot/master.pid',
          init_script: '/etc/init.d/dovecot',
          unit_name: 'dovecot',
          connections: connections
  end

  def do_tcpresponse_check(responses)
    bad = responses.find { |r| r =~ /^(\S+\s+)?(-ERR|NO|BAD)/ }
    raise "Unexpected response '#{bad}'" unless bad.nil?
  end
end

def imap(proto)
  Symbiosis::Monitor::TCPConnection.new(
    'localhost',
    proto,
    [/^. OK/, "s CAPABILITY\r\n", /^s OK/, "s LOGOUT\r\n", /^s OK/],
    'imaps' == proto
  )
end

def pop3(proto)
  Symbiosis::Monitor::TCPConnection.new(
    'localhost',
    proto,
    [nil, "AUTH\r\n", /^\.\s*$/, "QUIT\r\n", nil],
    'pop3s' == proto
  )
end

def sieve
  # This is a regex that matches the response that signals the end of what
  # the server says.
  resp = /^(OK|NO|BYE)/

  Symbiosis::Monitor::TCPConnection.new(
    'localhost',
    'sieve',
    [resp, "LOGOUT\r\n", resp]
  )
end

protocols = []
File.readlines('/etc/dovecot/dovecot.conf').each do |l|
  if l =~ /^\s*protocols\s*=\s*((?:\w+\s+)+)/
    protocols = Regexp.last_match(1).split(/\s+/)
  end
end

connections = protocols.map do |proto|
  case proto
  when /^imaps?$/
    imap(proto)
  when /^pop3s?$/
    pop3(proto)
  when 'managesieve'
    sieve
  else
    warn "Unknown protocol #{proto}"
    nil
  end
end

connections.reject!(&:nil?)

exit DovecotCheck.new(connections).do_check if $PROGRAM_NAME == __FILE__

# vim: softtabstop=0 expandtab shiftwidth=2 smarttab:
