add hipchat handler (#9)

* add hipchat handler

* add include for hipchat

* add handler_hipchat.sls
diff --git a/sensu/files/handlers/hipchat.json b/sensu/files/handlers/hipchat.json
new file mode 100644
index 0000000..4856c8d
--- /dev/null
+++ b/sensu/files/handlers/hipchat.json
@@ -0,0 +1,24 @@
+{%- set handler = pillar.sensu.server.handler[handler_name] %}
+{%- if handler_setting == "handler" %}
+{
+  "handlers": {
+    "hipchat": {
+      "type": "pipe",
+      "command": "/etc/sensu/handlers/hipchat.rb"
+    }
+  }
+}
+{%- endif %}
+{%- if handler_setting == "config" %}
+{
+  "hipchat": {
+    "apikey": "{{ handler.apikey }}",
+    "apiversion": "{{ handler.apiversion }}",
+    "room": "{{ handler.room }}",
+    "from": "{{ handler.from }}"{%- if handler.message_template is defined %},
+    "message_template": "optional message template erb file path - /some/path/to/template.erb",
+    "message_format": "html"
+    {%- endif %}
+  }
+}
+{%- endif %}
diff --git a/sensu/files/plugins/handlers/notification/hipchat.rb b/sensu/files/plugins/handlers/notification/hipchat.rb
new file mode 100644
index 0000000..49eebf2
--- /dev/null
+++ b/sensu/files/plugins/handlers/notification/hipchat.rb
@@ -0,0 +1,98 @@
+#!/usr/bin/env ruby
+#
+# Sensu Handler: hipchat
+#
+# This handler script is used to send notifications to Hipchat rooms.
+#
+# Input:
+#   @event - Event attributes.
+#      @event['action'] - Property to figure out the event type i.e. whether it is create or resolve.
+#      @event['check'] - Map of attributes from the check config which is calling this handler
+#      @event['client'] - Map of attributes from the client config for the clients from which this event is generated.
+#   option: json_config - By default, assumes the hipchat config parameters are in the "hipchat" top-level json key.
+#                         This command line option allows to specify a custom json key.
+#
+# Output:
+#    Green coloured notification on the Hipchat room if a resolve event is seen.
+#    Yellow coloured notification used to notify warning if a create event is seen with a status of 1
+#    Red coloured notification used to notify critical if a create event is seen with a status other than 1
+#
+# Note: The handler config is fetched and merged from all json config files. The "hipchat" json key is used by default which can
+#       be overridden with the "json_config" command line option. The hipchat room could also be configured on a per client basis
+#       by defining the "hipchat_room" attribute in the client config file. This will override the default hipchat room where the
+#       alerts are being routed to for that particular client.
+
+require 'sensu-handler'
+require 'hipchat'
+require 'timeout'
+require 'erubis'
+
+class HipChatNotif < Sensu::Handler
+  option :json_config,
+         description: 'JSON config key name',
+         short: '-j JsonKeyName',
+         long: '--json_config JsonKeyName',
+         required: false,
+         default: 'hipchat'
+
+  def event_name
+    @event['client']['name'] + '/' + @event['check']['name']
+  end
+
+  def handle
+    json_config = config[:json_config]
+    server_url = settings[json_config]['server_url'] || 'https://api.hipchat.com'
+    apiversion = settings[json_config]['apiversion'] || 'v1'
+    proxy_url = settings[json_config]['proxy_url']
+    hipchatmsg = HipChat::Client.new(settings[json_config]['apikey'], api_version: apiversion, http_proxy: proxy_url, server_url: server_url)
+    room = @event['client']['hipchat_room'] || @event['check']['hipchat_room'] || settings[json_config]['room']
+    from = settings[json_config]['from'] || 'Sensu'
+    message_template = settings[json_config]['message_template']
+    message_format = settings[json_config]['message_format'] || 'html'
+
+    # If the playbook attribute exists and is a URL, "[<a href='url'>playbook</a>]" will be output.
+    # To control the link name, set the playbook value to the HTML output you would like.
+    playbook = ''
+    if @event['check']['playbook']
+      begin
+        uri = URI.parse(@event['check']['playbook'])
+        playbook << if %w( http https ).include?(uri.scheme)
+                      "  [<a href='#{@event['check']['playbook']}'>Playbook</a>]"
+                    else
+                      "  Playbook:  #{@event['check']['playbook']}"
+                    end
+      rescue
+        playbook << "  Playbook:  #{@event['check']['playbook']}"
+      end
+    end
+
+    if message_template && File.readable?(message_template)
+      template = File.read(message_template)
+    else
+      template = '''<%=
+      [
+        @event["action"].eql?("resolve") ? "RESOLVED" : "ALERT",
+        " - [#{event_name}] - ",
+        @event["check"]["notification"] || @event["check"]["output"],
+        playbook,
+        "."
+      ].join
+      %>
+      '''
+    end
+    eruby = Erubis::Eruby.new(template)
+    message = eruby.result(binding)
+
+    begin
+      timeout(3) do
+        if @event['action'].eql?('resolve')
+          hipchatmsg[room].send(from, message, color: 'green', message_format: message_format)
+        else
+          hipchatmsg[room].send(from, message, color: @event['check']['status'] == 1 ? 'yellow' : 'red', notify: true, message_format: message_format)
+        end
+      end
+    rescue Timeout::Error
+      puts "hipchat -- timed out while attempting to message #{room}"
+    end
+  end
+end
diff --git a/sensu/server.sls b/sensu/server.sls
index 1cb6b53..4882acf 100644
--- a/sensu/server.sls
+++ b/sensu/server.sls
@@ -86,7 +86,7 @@
 
 {%- for handler_name, handler in server.get('handler', {}).iteritems() %}
 
-{%- if handler_name in ['default', 'flapjack', 'mail', 'sccd', 'stdout', 'statsd', 'slack', 'pipe', 'sfdc', 'pagerduty']  %}
+{%- if handler_name in ['default', 'flapjack', 'mail', 'sccd', 'stdout', 'statsd', 'slack', 'pipe', 'sfdc', 'pagerduty', 'hipchat']  %}
 
 {%- include "sensu/server/_handler_"+handler_name+".sls" %}
 
diff --git a/sensu/server/_handler_hipchat.sls b/sensu/server/_handler_hipchat.sls
new file mode 100644
index 0000000..e797eb3
--- /dev/null
+++ b/sensu/server/_handler_hipchat.sls
@@ -0,0 +1,35 @@
+
+/etc/sensu/conf.d/hipchat.json:
+  file.managed:
+  - source: salt://sensu/files/handlers/hipchat.json
+  - template: jinja
+  - defaults:
+    handler_name: "{{ handler_name }}"
+    handler_setting: "config"
+  - watch_in:
+    - service: service_sensu_server
+    - service: service_sensu_api
+  - require_in:
+    - file: sensu_conf_dir_clean
+
+/etc/sensu/conf.d/handler_hipchat.json:
+  file.managed:
+  - source: salt://sensu/files/handlers/hipchat.json
+  - template: jinja
+  - defaults:
+    handler_name: "{{ handler_name }}"
+    handler_setting: "handler"
+  - watch_in:
+    - service: service_sensu_server
+    - service: service_sensu_api
+  - require_in:
+    - file: sensu_conf_dir_clean
+
+/etc/sensu/handlers/hipchat.rb:
+  file.managed:
+  - source: salt://sensu/files/plugins/handlers/notification/hipchat.rb
+  - mode: 700
+  - user: sensu
+  - watch_in:
+    - service: service_sensu_server
+    - service: service_sensu_api
\ No newline at end of file