#!/usr/bin/env ruby # Copyright 2011 Marc Hedlund <marc@precipice.org> # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # oncall-email.rb -- Notify on-call people about shift start. # # Original script contributed by Jeffrey Wescott # (https://github.com/binaryfeed). Thanks! require 'psych' require 'net/smtp' require 'optparse' lib = File.expand_path(File.join(File.dirname(__FILE__), '../lib')) $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib) require 'pagerduty_tools' # Look for reporting options options = {} optparse = OptionParser.new do |opts| opts.banner = "Usage: oncall-email.rb\n" + "Send an email reminder to the on-call person (and any relevant CCs)." options[:smtp_server] = 'localhost' opts.on( '-m', '--smtp-server HOSTNAME', 'Use HOSTNAME as the SMTP server.') do |host| options[:smtp_server] = host end options[:subject] = '[PagerDuty] You are now on call' opts.on( '-s', '--subject SUBJECT', 'Use SUBJECT as the subject line of the email.') do |subject| options[:subject] = subject end options[:from_address] = 'nobody@example.com' opts.on( '-f', '--from ADDRESS', 'Use ADDERSS as the "From:" line of the email.') do |from| options[:from_address] = from end # REVIEW: Should this be an ARRAY option? options[:ccs] = [] opts.on( '-c', '--cc EMAIL', 'Send a copy of the email to EMAIL.' ) do |cc| options[:ccs] << cc end options[:message_file] = nil opts.on( '-m', '--message-file FILENAME', 'Use contents of FILENAME as the email body.') do |filename| options[:message_file] = filename end opts.on( '-p', '--policy POLICY', 'Set the Escalation Policy to display') do |policy| options[:policy] = policy end opts.on( '-h', '--help', 'Display this message' ) do puts opts exit end end optparse.parse! # Default to sending mail to the first-level assignee only, or use levels # given as arguments. mail_to_levels = ARGV.count > 0 ? ARGV : "1" # Log into PagerDuty and get the Dashboard page. pagerduty = PagerDuty::Agent.new escalation = PagerDuty::Escalation.new mail_to_levels, options[:policy] # REVIEW: don't we need one Person per level? What's this for? person = PagerDuty::Person.new # Log into PagerDuty and get the on-call info block. oncall_info = pagerduty.fetch "/on_call_info" levels = escalation.parse oncall_info.body # Get the email address for each on-call level. levels.each do |level| user = pagerduty.fetch level['person_path'] person.parse user.body level['email'] = person.email end # REVIEW: Is the 'recips' line needed? Can Net::SMTP pull addresses from the header? recips = options[:ccs] + (levels.map { |level| level['email'] }) to_line = levels.map{|level| "#{level['person']} <#{level['email']}>" }.join(", ") cc_line = options[:ccs].join(", ") header = <<HEADER_END From: PagerDuty <#{options[:from_address]}> To: #{to_line} CC: #{cc_line} Subject: #{options[:subject]} HEADER_END # REVIEW: Hmm...wonder if the email should be different for each person, telling # them what level assignment they have now. # REVIEW: Should show the full assignment list as a table. body = <<BODY_END Your PagerDuty on-call rotation has started. If you receive alerts about new incidents, please acknowledge them as soon as possible if you can respond. If not, please escalate them to the next level so they can be handled quickly. For more information about an alert, please log into our PagerDuty account at: https://#{pagerduty.domain} Thanks. BODY_END if options[:message_file] != nil body = "" File.open(options[:message_file], "r") do |file| file.each_line do |line| body += line end end end Net::SMTP.start(options[:smtp_server]) do |smtp| smtp.send_message header + body, options[:from_address], recips end exit(0)