updates the implementation of the slack backend for notifications

Use the slack_sdk instead of the deprecated slackclient. Because according to the official documentation:
>  The slackclient PyPI project is in maintenance mode now and slack-sdk project is the successor.
With this commit one UPGRADE BLOCKER from requirements/requirements.in is removed. Als the license for slack_sdk
is updated and unit tests for slack notifications backend are added.

Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at>
This commit is contained in:
Daniel Ziegenberg 2021-10-21 18:25:40 +02:00
parent 69ae731898
commit e7064868b4
No known key found for this signature in database
GPG Key ID: 7E6F98FFADBEFD39
7 changed files with 88 additions and 24 deletions

View File

@ -4856,7 +4856,7 @@ msgid "Exception connecting to PagerDuty: {}"
msgstr ""
#: awx/main/notifications/pagerduty_backend.py:87
#: awx/main/notifications/slack_backend.py:48
#: awx/main/notifications/slack_backend.py:49
#: awx/main/notifications/twilio_backend.py:47
msgid "Exception sending messages: {}"
msgstr ""

View File

@ -2,7 +2,8 @@
# All Rights Reserved.
import logging
from slackclient import SlackClient
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -28,7 +29,7 @@ class SlackBackend(AWXBaseEmailBackend, CustomNotificationBase):
self.color = hex_color
def send_messages(self, messages):
connection = SlackClient(self.token)
client = WebClient(self.token)
sent_messages = 0
for m in messages:
try:
@ -36,15 +37,15 @@ class SlackBackend(AWXBaseEmailBackend, CustomNotificationBase):
if r.startswith('#'):
r = r[1:]
if self.color:
ret = connection.api_call("chat.postMessage", channel=r, as_user=True, attachments=[{"color": self.color, "text": m.subject}])
response = client.chat_postMessage(channel=r, as_user=True, attachments=[{"color": self.color, "text": m.subject}])
else:
ret = connection.api_call("chat.postMessage", channel=r, as_user=True, text=m.subject)
logger.debug(ret)
if ret['ok']:
response = client.chat_postMessage(channel=r, as_user=True, text=m.subject)
logger.debug(response)
if response['ok']:
sent_messages += 1
else:
raise RuntimeError("Slack Notification unable to send {}: {} ({})".format(r, m.subject, ret['error']))
except Exception as e:
raise RuntimeError("Slack Notification unable to send {}: {} ({})".format(r, m.subject, response['error']))
except SlackApiError as e:
logger.error(smart_text(_("Exception sending messages: {}").format(e)))
if not self.fail_silently:
raise

View File

@ -0,0 +1,73 @@
import pytest
from unittest import mock
from django.core.mail.message import EmailMessage
import awx.main.notifications.slack_backend as slack_backend
def test_send_messages():
with mock.patch('awx.main.notifications.slack_backend.WebClient') as slack_sdk_mock:
WebClient_mock = slack_sdk_mock.return_value
WebClient_mock.chat_postMessage.return_value = {'ok': True}
backend = slack_backend.SlackBackend('slack_access_token')
message = EmailMessage(
'test subject',
'test body',
[],
[
'#random',
],
)
sent_messages = backend.send_messages(
[
message,
]
)
WebClient_mock.chat_postMessage.assert_called_once_with(channel='random', as_user=True, text='test subject')
assert sent_messages == 1
def test_send_messages_with_color():
with mock.patch('awx.main.notifications.slack_backend.WebClient') as slack_sdk_mock:
WebClient_mock = slack_sdk_mock.return_value
WebClient_mock.chat_postMessage.return_value = {'ok': True}
backend = slack_backend.SlackBackend('slack_access_token', hex_color='#006699')
message = EmailMessage(
'test subject',
'test body',
[],
[
'#random',
],
)
sent_messages = backend.send_messages(
[
message,
]
)
WebClient_mock.chat_postMessage.assert_called_once_with(channel='random', as_user=True, attachments=[{'color': '#006699', 'text': 'test subject'}])
assert sent_messages == 1
def test_send_messages_fail():
with mock.patch('awx.main.notifications.slack_backend.WebClient') as slack_sdk_mock, pytest.raises(RuntimeError, match=r'.*not_in_channel.*'):
WebClient_mock = slack_sdk_mock.return_value
WebClient_mock.chat_postMessage.return_value = {'ok': False, 'error': 'not_in_channel'}
backend = slack_backend.SlackBackend('slack_access_token')
message = EmailMessage(
'test subject',
'test body',
[],
[
'#not_existing',
],
)
sent_messages = backend.send_messages(
[
message,
]
)
WebClient_mock.chat_postMessage.assert_called_once_with(channel='not_existing', as_user=True, text='test subject')
assert sent_messages == 0

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015-2016 Slack Technologies, Inc
Copyright (c) 2015- Slack Technologies, LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE.

View File

@ -108,12 +108,6 @@ Upgrading to 4.0.0 causes error because imports changed.
ImportError: cannot import name 'KeyVaultClient'
```
### slackclient
Imports as used in `awx/main/notifications/slack_backend.py` changed
in version 2.0. This plugin code will need to change and be re-tested
as the upgrade takes place.
### django-jsonfield
Instead of calling a `loads()` operation, the returned value is casted into

View File

@ -50,7 +50,7 @@ social-auth-core==3.3.1 # see UPGRADE BLOCKERs
social-auth-app-django==3.1.0 # see UPGRADE BLOCKERs
redis
requests
slackclient==1.1.2 # see UPGRADE BLOCKERs
slack-sdk
tacacs_plus==1.0 # UPGRADE BLOCKER: auth does not work with later versions
twilio
twisted[tls]>=20.3.0 # CVE-2020-10108, CVE-2020-10109

View File

@ -320,7 +320,6 @@ requests==2.23.0
# python-dsv-sdk
# python-tss-sdk
# requests-oauthlib
# slackclient
# social-auth-core
# twilio
requests-oauthlib==1.3.0
@ -358,13 +357,12 @@ six==1.14.0
# pyrad
# pyrsistent
# python-dateutil
# slackclient
# social-auth-app-django
# social-auth-core
# tacacs-plus
# twilio
# websocket-client
slackclient==1.1.2
slack-sdk==3.11.2
# via -r /awx_devel/requirements/requirements.in
smmap==3.0.1
# via gitdb
@ -399,9 +397,7 @@ uwsgi==2.0.18
uwsgitop==0.11
# via -r /awx_devel/requirements/requirements.in
websocket-client==0.57.0
# via
# kubernetes
# slackclient
# via kubernetes
wheel==0.36.2
# via -r /awx_devel/requirements/requirements.in
xmlsec==1.3.3