Repository: PrefectHQ/prefect

Issue:
Add proxies to slack_notifier
## Current behavior
`prefect.utilities.notifications.slack_notifier` sends requests to the Slack webhook using `requests.post` without allowing  `proxies={"http": "0.123.456.789"}` to be passed, which is problematic when Internet access must be done through a proxy.

 It is possible to go around this by setting HTTP_PROXY / HTTPS_PROXY environment variables, but this is not ideal / possible when running on private infrastructure which by default does not access the Internet and should not have these variables set.



## Proposed behavior
Add an optional `proxies` argument to `prefect.utilities.notifications.slack_notifier` which gets passed to `requests.post`.



## Example
To use Slack notifications from Prefect running on private infrastructure.


Discussion:

Resolving patch:
diff --git a/src/prefect/utilities/notifications/notifications.py b/src/prefect/utilities/notifications/notifications.py
--- a/src/prefect/utilities/notifications/notifications.py
+++ b/src/prefect/utilities/notifications/notifications.py
@@ -252,6 +252,7 @@ def slack_notifier(
     only_states: list = None,
     webhook_secret: str = None,
     backend_info: bool = True,
+    proxies: dict = None,
 ) -> "prefect.engine.state.State":
     """
     Slack state change handler; requires having the Prefect slack app installed.  Works as a
@@ -274,6 +275,9 @@ def slack_notifier(
             webhook URL; defaults to `"SLACK_WEBHOOK_URL"`
         - backend_info (bool, optional): Whether to supply slack notification with urls
             pointing to backend pages; defaults to True
+        - proxies (dict), optional): `dict` with "http" and/or "https" keys, passed to
+         `requests.post` - for situations where a proxy is required to send requests to the
+          Slack webhook
 
     Returns:
         - State: the `new_state` object that was provided
@@ -310,7 +314,7 @@ def add(x, y):
     import requests
 
     form_data = slack_message_formatter(tracked_obj, new_state, backend_info)
-    r = requests.post(webhook_url, json=form_data)
+    r = requests.post(webhook_url, json=form_data, proxies=proxies)
     if not r.ok:
         raise ValueError("Slack notification for {} failed".format(tracked_obj))
     return new_state


Test patch:
diff --git a/tests/utilities/notifications/test_notifications.py b/tests/utilities/notifications/test_notifications.py
--- a/tests/utilities/notifications/test_notifications.py
+++ b/tests/utilities/notifications/test_notifications.py
@@ -260,6 +260,16 @@ def test_slack_notifier_is_curried_and_uses_only_states(monkeypatch, state):
     assert ok.called is isinstance(state, TriggerFailed)
 
 
+def test_slack_notifier_uses_proxies(monkeypatch):
+    post = MagicMock(ok=True)
+    monkeypatch.setattr(requests, "post", post)
+    state = Failed(message="1", result=0)
+    with set_temporary_config({"cloud.use_local_secrets": True}):
+        with prefect.context(secrets=dict(SLACK_WEBHOOK_URL="")):
+            slack_notifier(Task(), "", state, proxies={"http": "some.proxy.I.P"})
+    assert post.call_args[1]["proxies"] == {"http": "some.proxy.I.P"}
+
+
 def test_gmail_notifier_sends_simple_email(monkeypatch):
     smtp = MagicMock()
     sendmail = MagicMock()