[MMO-282] Adjust Sensu filter config for sfdc

Allow configuring a filter definition for the sfdc handler in the model.

Override the `filter_repeated()` function in sfdc plugin.  There is
little point in having this function filter out repeated alerts since
the destination because the destination is Salesforce.  Repeated alerts
will simply be appened to the same `MOS Alert`.

This also lets us configure filters entirely from the model/Sensu
config, which means we can configure these easier per-site.

As it was, if I wanted to configure the sfdc handler to not create an
alert unless it triggered three time in a row, the `filter_repeated()`
function would mask that third alert.

Change-Id: I43553fb82fcd7b296f14bf1e48e45e2215aaa534
diff --git a/sensu/files/handlers/sfdc.json b/sensu/files/handlers/sfdc.json
index d331442..362fbc4 100644
--- a/sensu/files/handlers/sfdc.json
+++ b/sensu/files/handlers/sfdc.json
@@ -7,6 +7,9 @@
       {%- if handler.mutator is defined %}
       "mutator": "{{ handler.mutator }}",
       {%- endif %}
+      {%- if handler.filter is defined %}
+      "filter": "{{ handler.filter }}",
+      {%- endif %}
       "command": "/etc/sensu/handlers/sfdc.py"
     }
   }
@@ -27,11 +30,11 @@
     {%- if handler.sfdc_https_proxy is defined %}
     "sfdc_https_proxy": "{{ handler.sfdc_https_proxy }}",
     {%- endif %}
+{%- if token_cache_file %}
+    "token_cache_file": "{{ token_cache_file }}",
+{%- endif %}
     "environment": "{{ handler.environment }}",
     "sfdc_organization_id": "{{ handler.sfdc_organization_id }}"
-{%- if token_cache_file %}
-    ,"token_cache_file": "{{ token_cache_file }}"
-{%- endif %}
   }
 }
 {%- endif %}
diff --git a/sensu/files/plugins/handlers/notification/sfdc.py b/sensu/files/plugins/handlers/notification/sfdc.py
index c6293d6..b0578e9 100755
--- a/sensu/files/plugins/handlers/notification/sfdc.py
+++ b/sensu/files/plugins/handlers/notification/sfdc.py
@@ -31,6 +31,11 @@
 
 class SfdcHandler(Handler):
 
+    def filter_repeated(self):
+        # Disable the default implementation of this so that we can manage filters
+        # completely via the model/Sensu config.
+        return False
+
     def _format_body(self, data):
         s = ""
         keys = list(data.keys())
diff --git a/tests/pillar/sensu_server.sls b/tests/pillar/sensu_server.sls
index d050bd9..b35c0a8 100644
--- a/tests/pillar/sensu_server.sls
+++ b/tests/pillar/sensu_server.sls
@@ -41,6 +41,25 @@
         domain: 'domain.cz'
       pagerduty:
         api_key: 'insert-your-key-here'
+      slack:
+        webhook_url: 'http://insert-url'
+        filter: test_filter
+      sfdc:
+        sfdc_client_id: 'client_id'
+        sfdc_client_secret: 'secret'
+        sfdc_username: 'username'
+        sfdc_password: 'password'
+        sfdc_auth_url: 'url'
+        environment: 'env'
+        sfdc_organization_id: 'org'
+        token_cache_file: "/var/run/sensu/token_cache_file"
+        filter: test_filter
+    filter:
+      test_filter:
+        negate: false
+        attributes:
+          occurrences: "eval: value == 3 || value % 20 == 0 || ':::action:::' == 'resolve'"
+
   client:
     enabled: false