class Chef::Handler::Slack

Slack Handler goal is send messages to a Slack channel with Chef run status. It can be used as a start, failure or success handler.

Attributes

channel[R]
on_failure[R]
on_start[R]
on_success[R]
token[R]
username[R]

Public Class Methods

new(options = {}) click to toggle source
# File lib/cookbook_sdk/handlers/slack.rb, line 14
def initialize(options = {})
  @token = options.fetch(:token) { raise Exceptions::ConfigurationError, "Slack 'token' should be provided!" }
  @channel = options.fetch(:channel, '#chef')
  @username = options.fetch(:username, 'Chef')
  @on_start = options.fetch(:on_start, true)
  @on_success = options.fetch(:on_success, true)
  @on_failure = options.fetch(:on_failure, true)
end

Public Instance Methods

report() click to toggle source
# File lib/cookbook_sdk/handlers/slack.rb, line 23
def report
  options = { :pretext => "Run at #{run_status.node.name}" }

  if !run_status.is_a?(Chef::RunStatus) || elapsed_time.nil?
    report_start(options)
  elsif run_status.success?
    report_success(options)
  else
    report_failure(options)
  end
end

Private Instance Methods

exit_without_sending(handler_type) click to toggle source
# File lib/cookbook_sdk/handlers/slack.rb, line 89
def exit_without_sending(handler_type)
  Chef::Log.debug("Slack '#{handler_type}' handler is not active.")
end
report_failure(options) click to toggle source
# File lib/cookbook_sdk/handlers/slack.rb, line 55
def report_failure(options)
  return exit_without_sending('failure') unless @on_failure

  options[:title] = 'Chef run FAILED!'
  options[:color] = 'danger'
  options[:body] = "Running #{node.run_list} failed in #{run_status.elapsed_time} seconds."
  options[:fallback] = "Chef FAILED! #{run_status.node.name} failed to run #{node.run_list}" \
                         " in #{run_status.elapsed_time.to_i} seconds."
  send_attachment(options)

  return if run_status.exception.nil?
  options[:text] = '```' + run_status.formatted_exception.encode(
    'UTF-8',
    :invalid => :replace, :undef => :replace, :replace => '?'
  ) + '```'
  send_text(options)
end
report_start(options) click to toggle source
# File lib/cookbook_sdk/handlers/slack.rb, line 37
def report_start(options)
  return exit_without_sending('start') unless @on_start
  options[:title] = 'Chef run started!'
  options[:body] = "Will run #{node.run_list}"
  options[:fallback] = "Chef run started! #{run_status.node.name} will run #{node.run_list}."
  send_attachment(options)
end
report_success(options) click to toggle source
# File lib/cookbook_sdk/handlers/slack.rb, line 45
def report_success(options)
  return exit_without_sending('success') unless @on_success
  options[:title] = 'Chef run successfully!'
  options[:color] = 'good'
  options[:body] = "Just run #{node.run_list} successfully in #{run_status.elapsed_time} seconds."
  options[:fallback] = "Chef run successfully! #{run_status.node.name} run #{node.run_list} successfully"\
                         " in #{run_status.elapsed_time.to_i} seconds."
  send_attachment(options)
end
send_attachment(options) click to toggle source
# File lib/cookbook_sdk/handlers/slack.rb, line 73
def send_attachment(options)
  raise 'No message defined to be send to slack' if options[:body].nil?
  params = {
    :color => options[:color],
    :attachments => [{
      :pretext => options[:pretext],
      :title => options[:title],
      :title_link => options[:title_link],
      :color => options[:color],
      :text => options[:body],
      :fallback => options[:fallback]
    }]
  }
  send_slack_message(params)
end
send_slack_message(specif_params) click to toggle source
# File lib/cookbook_sdk/handlers/slack.rb, line 101
def send_slack_message(specif_params)
  params = { :username => @username, :channel => @channel, :token => @token }.merge(specif_params)

  uri = URI("https://hooks.slack.com/services/#{@token}")
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  begin
    req = Net::HTTP::Post.new("#{uri.path}?#{uri.query}")
    req.set_form_data(:payload => params.to_json)
    res = http.request(req)
    if res.code != '200'
      Chef::Log.error("We got an error while posting a message to Slack: #{res.code} - #{res.msg}")
    else
      Chef::Log.debug("Slack handler sent a message to channel '#{params[:channel]}'")
    end
  rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
         Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
    Chef::Log.error("An unhandled exception occurred while posting a message to Slack: #{e}")
  end
end
send_text(options) click to toggle source
# File lib/cookbook_sdk/handlers/slack.rb, line 93
def send_text(options)
  raise 'No message defined to be send to slack' if options[:text].nil?
  params = {
    :text => options[:text]
  }
  send_slack_message(params)
end