Add Pagerduty integration for Sensu
diff --git a/sensu/files/handlers/pagerduty.json b/sensu/files/handlers/pagerduty.json
new file mode 100644
index 0000000..3a0be25
--- /dev/null
+++ b/sensu/files/handlers/pagerduty.json
@@ -0,0 +1,27 @@
+{%- set handler = pillar.sensu.server.handler[handler_name] %}
+{%- if handler_setting == "handler" %}
+{
+  "handlers": {
+    "pagerduty": {
+      "type": "pipe",
+      {%- if handler.mutator is defined %}
+      "mutator": "{{ handler.mutator }}",
+      {%- endif %}
+      "command": "/etc/sensu/handlers/handler-pagerduty.rb",
+      "severities": [
+        "ok",
+        "critical",
+        "warning",
+        "unknown"
+      ]
+    }
+  }
+}
+{%- endif %}
+{%- if handler_setting == "config" %}
+{
+  "pagerduty": {
+    "api_key": "{{ handler.api_key }}"
+  }
+}
+{%- endif %}
\ No newline at end of file
diff --git a/sensu/files/plugins/handlers/notification/pagerduty.rb b/sensu/files/plugins/handlers/notification/pagerduty.rb
new file mode 100644
index 0000000..0c3d46e
--- /dev/null
+++ b/sensu/files/plugins/handlers/notification/pagerduty.rb
@@ -0,0 +1,112 @@
+#!/usr/bin/env ruby
+#
+# This handler creates and resolves PagerDuty incidents, refreshing
+# stale incident details every 30 minutes
+#
+# Copyright 2011 Sonian, Inc <chefs@sonian.net>
+#
+# Released under the same terms as Sensu (the MIT license); see LICENSE
+# for details.
+#
+# Note: The sensu api token could also be configured on a per client or per check basis.
+#       By defining the "pager_team" attribute in the client config file or the check config.
+#       The override order will be client > check > json_config
+#
+# Dependencies:
+#
+#   sensu-plugin >= 1.0.0
+#
+
+require 'sensu-handler'
+require 'pagerduty'
+
+#
+# Pagerduty
+#
+class PagerdutyHandler < Sensu::Handler
+  option :json_config,
+         description: 'Config Name',
+         short: '-j JsonConfig',
+         long: '--json_config JsonConfig',
+         required: false,
+         default: 'pagerduty'
+
+  def incident_key
+    source = @event['check']['source'] || @event['client']['name']
+    incident_id = [source, @event['check']['name']].join('/')
+    dedup_rules = settings[json_config]['dedup_rules'] || {}
+    dedup_rules.each do |key, val|
+      incident_id = incident_id.gsub(Regexp.new(key), val)
+    end
+    incident_id
+  end
+
+  def json_config
+    @json_config ||= config[:json_config]
+  end
+
+  def api_key
+    @api_key ||=
+      if @event['client']['pager_team']
+        settings[json_config][@event['client']['pager_team']]['api_key']
+      elsif @event['check']['pager_team']
+        settings[json_config][@event['check']['pager_team']]['api_key']
+      else
+        settings[json_config]['api_key']
+      end
+  end
+
+  def proxy_settings
+    proxy_settings = {}
+
+    proxy_settings['proxy_host']     = settings[json_config]['proxy_host']     || nil
+    proxy_settings['proxy_port']     = settings[json_config]['proxy_port']     || 3128
+    proxy_settings['proxy_username'] = settings[json_config]['proxy_username'] || ''
+    proxy_settings['proxy_password'] = settings[json_config]['proxy_password'] || ''
+
+    proxy_settings
+  end
+
+  def contexts
+    @contexts ||= @event['check']['pagerduty_contexts'] || []
+  end
+
+  def handle(pd_client = nil)
+    incident_key_prefix = settings[json_config]['incident_key_prefix']
+    description_prefix = settings[json_config]['description_prefix']
+    proxy_settings = proxy_settings()
+    begin
+      timeout(5) do
+        if proxy_settings['proxy_host']
+          pagerduty = pd_client || Pagerduty.new(api_key,
+                                                 proxy_host: proxy_settings['proxy_host'],
+                                                 proxy_port: proxy_settings['proxy_port'],
+                                                 proxy_username: proxy_settings['proxy_username'],
+                                                 proxy_password: proxy_settings['proxy_password'])
+        else
+          pagerduty = pd_client || Pagerduty.new(api_key)
+        end
+
+        begin
+          case @event['action']
+          when 'create'
+            pagerduty.trigger([description_prefix, event_summary].compact.join(' '),
+                              incident_key: [incident_key_prefix, incident_key].compact.join(''),
+                              details: @event,
+                              contexts: contexts)
+          when 'resolve'
+            pagerduty.get_incident([incident_key_prefix, incident_key].compact.join('')).resolve(
+              [description_prefix, event_summary].compact.join(' '), @event
+            )
+          end
+          puts 'pagerduty -- ' + @event['action'].capitalize + 'd incident -- ' + incident_key
+        rescue Net::HTTPServerException => error
+          puts 'pagerduty -- failed to ' + @event['action'] + ' incident -- ' + incident_key + ' -- ' +
+               error.response.code + ' ' + error.response.message + ': ' + error.response.body
+        end
+      end
+    rescue Timeout::Error
+      puts 'pagerduty -- timed out while attempting to ' + @event['action'] + ' a incident -- ' + incident_key
+    end
+  end
+end
diff --git a/sensu/server.sls b/sensu/server.sls
index 237a6ca..1cb6b53 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']  %}
+{%- if handler_name in ['default', 'flapjack', 'mail', 'sccd', 'stdout', 'statsd', 'slack', 'pipe', 'sfdc', 'pagerduty']  %}
 
 {%- include "sensu/server/_handler_"+handler_name+".sls" %}
 
diff --git a/sensu/server/_handler_pagerduty.sls b/sensu/server/_handler_pagerduty.sls
new file mode 100644
index 0000000..700bfde
--- /dev/null
+++ b/sensu/server/_handler_pagerduty.sls
@@ -0,0 +1,42 @@
+
+gem_sensu_pagerduty:
+  gem.installed:
+  - name: pagerduty
+  - gem_bin: /opt/sensu/embedded/bin/gem
+
+/etc/sensu/conf.d/pagerduty.json:
+  file.managed:
+  - source: salt://sensu/files/handlers/pagerduty.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_pagerduty.json:
+  file.managed:
+  - source: salt://sensu/files/handlers/pagerduty.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/pagerduty.rb:
+  file.managed:
+  - source: salt://sensu/files/plugins/handlers/notification/pagerduty.rb
+  - mode: 700
+  - user: sensu
+  - watch_in:
+    - service: service_sensu_server
+    - service: service_sensu_api
+  - require:
+    - gem_sensu_pagerduty
\ No newline at end of file
diff --git a/tests/pillar/sensu_server.sls b/tests/pillar/sensu_server.sls
index 80431c9..d050bd9 100644
--- a/tests/pillar/sensu_server.sls
+++ b/tests/pillar/sensu_server.sls
@@ -2,7 +2,7 @@
   server:
     enabled: true
     keepalive_warning: 20
-    keepalive_critical: 60        
+    keepalive_critical: 60
     mine_checks: true
     database:
       engine: redis
@@ -24,6 +24,7 @@
         set:
         - mail
         - pipe
+        - pagerduty
       stdout:
         enabled: true
       pipe:
@@ -38,6 +39,8 @@
         authentication: cram_md5
         encryption: ssl
         domain: 'domain.cz'
+      pagerduty:
+        api_key: 'insert-your-key-here'
   client:
     enabled: false