mirror of
https://github.com/GSA/notifications-api.git
synced 2026-02-02 17:31:14 -05:00
Merge pull request #3036 from alphagov/cbc-proxy-refactor
Cbc proxy refactor
This commit is contained in:
@@ -22,7 +22,7 @@ from werkzeug.exceptions import HTTPException as WerkzeugHTTPException
|
|||||||
from werkzeug.local import LocalProxy
|
from werkzeug.local import LocalProxy
|
||||||
|
|
||||||
from app.celery.celery import NotifyCelery
|
from app.celery.celery import NotifyCelery
|
||||||
from app.clients import Clients
|
from app.clients import NotificationProviderClients
|
||||||
from app.clients.cbc_proxy import CBCProxyClient, CBCProxyNoopClient
|
from app.clients.cbc_proxy import CBCProxyClient, CBCProxyNoopClient
|
||||||
from app.clients.document_download import DocumentDownloadClient
|
from app.clients.document_download import DocumentDownloadClient
|
||||||
from app.clients.email.aws_ses import AwsSesClient
|
from app.clients.email.aws_ses import AwsSesClient
|
||||||
@@ -65,7 +65,7 @@ cbc_proxy_client = CBCProxyNoopClient()
|
|||||||
document_download_client = DocumentDownloadClient()
|
document_download_client = DocumentDownloadClient()
|
||||||
metrics = GDSMetrics()
|
metrics = GDSMetrics()
|
||||||
|
|
||||||
clients = Clients()
|
notification_provider_clients = NotificationProviderClients()
|
||||||
|
|
||||||
api_user = LocalProxy(lambda: _request_ctx_stack.top.api_user)
|
api_user = LocalProxy(lambda: _request_ctx_stack.top.api_user)
|
||||||
authenticated_service = LocalProxy(lambda: _request_ctx_stack.top.authenticated_service)
|
authenticated_service = LocalProxy(lambda: _request_ctx_stack.top.authenticated_service)
|
||||||
@@ -106,7 +106,7 @@ def create_app(application):
|
|||||||
)
|
)
|
||||||
# If a stub url is provided for SES, then use the stub client rather than the real SES boto client
|
# If a stub url is provided for SES, then use the stub client rather than the real SES boto client
|
||||||
email_clients = [aws_ses_stub_client] if application.config['SES_STUB_URL'] else [aws_ses_client]
|
email_clients = [aws_ses_stub_client] if application.config['SES_STUB_URL'] else [aws_ses_client]
|
||||||
clients.init_app(sms_clients=[firetext_client, mmg_client], email_clients=email_clients)
|
notification_provider_clients.init_app(sms_clients=[firetext_client, mmg_client], email_clients=email_clients)
|
||||||
|
|
||||||
notify_celery.init_app(application)
|
notify_celery.init_app(application)
|
||||||
encryption.init_app(application)
|
encryption.init_app(application)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ STATISTICS_DELIVERED = 'delivered'
|
|||||||
STATISTICS_FAILURE = 'failure'
|
STATISTICS_FAILURE = 'failure'
|
||||||
|
|
||||||
|
|
||||||
class Clients(object):
|
class NotificationProviderClients(object):
|
||||||
sms_clients = {}
|
sms_clients = {}
|
||||||
email_clients = {}
|
email_clients = {}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ import boto3
|
|||||||
# the preceeding Alert message in the references field
|
# the preceeding Alert message in the references field
|
||||||
|
|
||||||
|
|
||||||
|
class CBCProxyException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# Noop = no operation
|
# Noop = no operation
|
||||||
class CBCProxyNoopClient:
|
class CBCProxyNoopClient:
|
||||||
|
|
||||||
@@ -72,72 +76,53 @@ class CBCProxyClient:
|
|||||||
aws_secret_access_key=app.config['CBC_PROXY_AWS_SECRET_ACCESS_KEY'],
|
aws_secret_access_key=app.config['CBC_PROXY_AWS_SECRET_ACCESS_KEY'],
|
||||||
)
|
)
|
||||||
|
|
||||||
def send_canary(
|
def _invoke_lambda(self, function_name, payload):
|
||||||
self,
|
payload_bytes = bytes(json.dumps(payload), encoding='utf8')
|
||||||
identifier,
|
|
||||||
):
|
|
||||||
payload_bytes = bytes(json.dumps({
|
|
||||||
'identifier': identifier,
|
|
||||||
}), encoding='utf8')
|
|
||||||
|
|
||||||
result = self._lambda_client.invoke(
|
result = self._lambda_client.invoke(
|
||||||
FunctionName='canary',
|
FunctionName=function_name,
|
||||||
InvocationType='RequestResponse',
|
InvocationType='RequestResponse',
|
||||||
Payload=payload_bytes,
|
Payload=payload_bytes,
|
||||||
)
|
)
|
||||||
|
|
||||||
if result['StatusCode'] > 299:
|
if result['StatusCode'] > 299:
|
||||||
raise Exception('Could not invoke lambda')
|
raise CBCProxyException('Could not invoke lambda')
|
||||||
|
|
||||||
if 'FunctionError' in result:
|
if 'FunctionError' in result:
|
||||||
raise Exception('Function exited with unhandled exception')
|
raise CBCProxyException('Function exited with unhandled exception')
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def send_canary(
|
||||||
|
self,
|
||||||
|
identifier,
|
||||||
|
):
|
||||||
|
self._invoke_lambda(function_name='canary', payload={'identifier': identifier})
|
||||||
|
|
||||||
def send_link_test(
|
def send_link_test(
|
||||||
self,
|
self,
|
||||||
identifier,
|
identifier,
|
||||||
):
|
):
|
||||||
payload_bytes = bytes(json.dumps({
|
payload = {'message_type': 'test', 'identifier': identifier}
|
||||||
'message_type': 'test',
|
|
||||||
'identifier': identifier,
|
|
||||||
}), encoding='utf8')
|
|
||||||
|
|
||||||
result = self._lambda_client.invoke(
|
self._invoke_lambda(function_name='bt-ee-1-proxy', payload=payload)
|
||||||
FunctionName='bt-ee-1-proxy',
|
|
||||||
InvocationType='RequestResponse',
|
|
||||||
Payload=payload_bytes,
|
|
||||||
)
|
|
||||||
|
|
||||||
if result['StatusCode'] > 299:
|
|
||||||
raise Exception('Could not invoke lambda')
|
|
||||||
|
|
||||||
if 'FunctionError' in result:
|
|
||||||
raise Exception('Function exited with unhandled exception')
|
|
||||||
|
|
||||||
def create_and_send_broadcast(
|
def create_and_send_broadcast(
|
||||||
self,
|
self,
|
||||||
identifier, headline, description, areas,
|
identifier, headline, description, areas,
|
||||||
sent, expires,
|
sent, expires,
|
||||||
):
|
):
|
||||||
payload_bytes = bytes(json.dumps({
|
payload = {
|
||||||
'message_type': 'alert',
|
'message_type': 'alert',
|
||||||
'identifier': identifier,
|
'identifier': identifier,
|
||||||
'headline': headline,
|
'headline': headline,
|
||||||
'description': description,
|
'description': description,
|
||||||
'areas': areas,
|
'areas': areas,
|
||||||
'sent': sent, 'expires': expires,
|
'sent': sent,
|
||||||
}), encoding='utf8')
|
'expires': expires,
|
||||||
|
}
|
||||||
|
|
||||||
result = self._lambda_client.invoke(
|
self._invoke_lambda(function_name='bt-ee-1-proxy', payload=payload)
|
||||||
FunctionName='bt-ee-1-proxy',
|
|
||||||
InvocationType='RequestResponse',
|
|
||||||
Payload=payload_bytes,
|
|
||||||
)
|
|
||||||
|
|
||||||
if result['StatusCode'] > 299:
|
|
||||||
raise Exception('Could not invoke lambda')
|
|
||||||
|
|
||||||
if 'FunctionError' in result:
|
|
||||||
raise Exception('Function exited with unhandled exception')
|
|
||||||
|
|
||||||
# We have not implementated updating a broadcast
|
# We have not implementated updating a broadcast
|
||||||
def update_and_send_broadcast(
|
def update_and_send_broadcast(
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from notifications_utils.recipients import (
|
|||||||
)
|
)
|
||||||
from notifications_utils.template import HTMLEmailTemplate, PlainTextEmailTemplate, SMSMessageTemplate
|
from notifications_utils.template import HTMLEmailTemplate, PlainTextEmailTemplate, SMSMessageTemplate
|
||||||
|
|
||||||
from app import clients, statsd_client, create_uuid
|
from app import notification_provider_clients, statsd_client, create_uuid
|
||||||
from app.dao.notifications_dao import (
|
from app.dao.notifications_dao import (
|
||||||
dao_update_notification
|
dao_update_notification
|
||||||
)
|
)
|
||||||
@@ -144,7 +144,7 @@ def provider_to_use(notification_type, international=False):
|
|||||||
|
|
||||||
chosen_provider = random.choices(active_providers, weights=[p.priority for p in active_providers])[0]
|
chosen_provider = random.choices(active_providers, weights=[p.priority for p in active_providers])[0]
|
||||||
|
|
||||||
return clients.get_client_by_name_and_type(chosen_provider.identifier, notification_type)
|
return notification_provider_clients.get_client_by_name_and_type(chosen_provider.identifier, notification_type)
|
||||||
|
|
||||||
|
|
||||||
def get_logo_url(base_url, logo_file):
|
def get_logo_url(base_url, logo_file):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import uuid
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from app.clients.cbc_proxy import CBCProxyClient
|
from app.clients.cbc_proxy import CBCProxyClient, CBCProxyException
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='function')
|
@pytest.fixture(scope='function')
|
||||||
@@ -116,7 +116,7 @@ def test_cbc_proxy_create_and_send_handles_invoke_error(mocker, cbc_proxy):
|
|||||||
'StatusCode': 400,
|
'StatusCode': 400,
|
||||||
}
|
}
|
||||||
|
|
||||||
with pytest.raises(Exception) as e:
|
with pytest.raises(CBCProxyException) as e:
|
||||||
cbc_proxy.create_and_send_broadcast(
|
cbc_proxy.create_and_send_broadcast(
|
||||||
identifier=identifier,
|
identifier=identifier,
|
||||||
headline=headline,
|
headline=headline,
|
||||||
@@ -165,7 +165,7 @@ def test_cbc_proxy_create_and_send_handles_function_error(mocker, cbc_proxy):
|
|||||||
'FunctionError': 'something',
|
'FunctionError': 'something',
|
||||||
}
|
}
|
||||||
|
|
||||||
with pytest.raises(Exception) as e:
|
with pytest.raises(CBCProxyException) as e:
|
||||||
cbc_proxy.create_and_send_broadcast(
|
cbc_proxy.create_and_send_broadcast(
|
||||||
identifier=identifier,
|
identifier=identifier,
|
||||||
headline=headline,
|
headline=headline,
|
||||||
@@ -174,7 +174,7 @@ def test_cbc_proxy_create_and_send_handles_function_error(mocker, cbc_proxy):
|
|||||||
sent=sent, expires=expires,
|
sent=sent, expires=expires,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert e.match('Function exited with unhandled exception')
|
assert e.match('Function exited with unhandled exception')
|
||||||
|
|
||||||
ld_client_mock.invoke.assert_called_once_with(
|
ld_client_mock.invoke.assert_called_once_with(
|
||||||
FunctionName='bt-ee-1-proxy',
|
FunctionName='bt-ee-1-proxy',
|
||||||
@@ -226,12 +226,12 @@ def test_cbc_proxy_send_canary_handles_invoke_error(mocker, cbc_proxy):
|
|||||||
'StatusCode': 400,
|
'StatusCode': 400,
|
||||||
}
|
}
|
||||||
|
|
||||||
with pytest.raises(Exception) as e:
|
with pytest.raises(CBCProxyException) as e:
|
||||||
cbc_proxy.send_canary(
|
cbc_proxy.send_canary(
|
||||||
identifier=identifier,
|
identifier=identifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert e.match('Function exited with unhandled exception')
|
assert e.match('Could not invoke lambda')
|
||||||
|
|
||||||
ld_client_mock.invoke.assert_called_once_with(
|
ld_client_mock.invoke.assert_called_once_with(
|
||||||
FunctionName='canary',
|
FunctionName='canary',
|
||||||
@@ -254,12 +254,12 @@ def test_cbc_proxy_send_canary_handles_function_error(mocker, cbc_proxy):
|
|||||||
'FunctionError': 'something',
|
'FunctionError': 'something',
|
||||||
}
|
}
|
||||||
|
|
||||||
with pytest.raises(Exception) as e:
|
with pytest.raises(CBCProxyException) as e:
|
||||||
cbc_proxy.send_canary(
|
cbc_proxy.send_canary(
|
||||||
identifier=identifier,
|
identifier=identifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert e.match('Could not invoke lambda')
|
assert e.match('Function exited with unhandled exception')
|
||||||
|
|
||||||
ld_client_mock.invoke.assert_called_once_with(
|
ld_client_mock.invoke.assert_called_once_with(
|
||||||
FunctionName='canary',
|
FunctionName='canary',
|
||||||
@@ -312,12 +312,12 @@ def test_cbc_proxy_send_link_test_handles_invoke_error(mocker, cbc_proxy):
|
|||||||
'StatusCode': 400,
|
'StatusCode': 400,
|
||||||
}
|
}
|
||||||
|
|
||||||
with pytest.raises(Exception) as e:
|
with pytest.raises(CBCProxyException) as e:
|
||||||
cbc_proxy.send_link_test(
|
cbc_proxy.send_link_test(
|
||||||
identifier=identifier,
|
identifier=identifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert e.match('Function exited with unhandled exception')
|
assert e.match('Could not invoke lambda')
|
||||||
|
|
||||||
ld_client_mock.invoke.assert_called_once_with(
|
ld_client_mock.invoke.assert_called_once_with(
|
||||||
FunctionName='bt-ee-1-proxy',
|
FunctionName='bt-ee-1-proxy',
|
||||||
@@ -340,12 +340,12 @@ def test_cbc_proxy_send_link_test_handles_function_error(mocker, cbc_proxy):
|
|||||||
'FunctionError': 'something',
|
'FunctionError': 'something',
|
||||||
}
|
}
|
||||||
|
|
||||||
with pytest.raises(Exception) as e:
|
with pytest.raises(CBCProxyException) as e:
|
||||||
cbc_proxy.send_link_test(
|
cbc_proxy.send_link_test(
|
||||||
identifier=identifier,
|
identifier=identifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert e.match('Could not invoke lambda')
|
assert e.match('Function exited with unhandled exception')
|
||||||
|
|
||||||
ld_client_mock.invoke.assert_called_once_with(
|
ld_client_mock.invoke.assert_called_once_with(
|
||||||
FunctionName='bt-ee-1-proxy',
|
FunctionName='bt-ee-1-proxy',
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from freezegun import freeze_time
|
|||||||
from sqlalchemy.sql import desc
|
from sqlalchemy.sql import desc
|
||||||
|
|
||||||
from app.models import ProviderDetails, ProviderDetailsHistory
|
from app.models import ProviderDetails, ProviderDetailsHistory
|
||||||
from app import clients
|
from app import notification_provider_clients
|
||||||
from app.dao.provider_details_dao import (
|
from app.dao.provider_details_dao import (
|
||||||
get_alternative_sms_provider,
|
get_alternative_sms_provider,
|
||||||
get_provider_details_by_identifier,
|
get_provider_details_by_identifier,
|
||||||
@@ -76,7 +76,7 @@ def test_can_get_email_providers(notify_db_session):
|
|||||||
def test_should_not_error_if_any_provider_in_code_not_in_database(restore_provider_details):
|
def test_should_not_error_if_any_provider_in_code_not_in_database(restore_provider_details):
|
||||||
ProviderDetails.query.filter_by(identifier='mmg').delete()
|
ProviderDetails.query.filter_by(identifier='mmg').delete()
|
||||||
|
|
||||||
assert clients.get_sms_client('mmg')
|
assert notification_provider_clients.get_sms_client('mmg')
|
||||||
|
|
||||||
|
|
||||||
@freeze_time('2000-01-01T00:00:00')
|
@freeze_time('2000-01-01T00:00:00')
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from notifications_utils.recipients import validate_and_format_phone_number
|
|||||||
from requests import HTTPError
|
from requests import HTTPError
|
||||||
|
|
||||||
import app
|
import app
|
||||||
from app import clients, mmg_client, firetext_client
|
from app import notification_provider_clients, mmg_client, firetext_client
|
||||||
from app.dao import notifications_dao
|
from app.dao import notifications_dao
|
||||||
from app.dao.provider_details_dao import get_provider_details_by_identifier
|
from app.dao.provider_details_dao import get_provider_details_by_identifier
|
||||||
from app.delivery import send_to_providers
|
from app.delivery import send_to_providers
|
||||||
@@ -535,7 +535,10 @@ def test_update_notification_to_sending_does_not_update_status_from_a_final_stat
|
|||||||
):
|
):
|
||||||
template = create_template(sample_service)
|
template = create_template(sample_service)
|
||||||
notification = create_notification(template=template, status=starting_status)
|
notification = create_notification(template=template, status=starting_status)
|
||||||
send_to_providers.update_notification_to_sending(notification, clients.get_client_by_name_and_type("mmg", "sms"))
|
send_to_providers.update_notification_to_sending(
|
||||||
|
notification,
|
||||||
|
notification_provider_clients.get_client_by_name_and_type("mmg", "sms")
|
||||||
|
)
|
||||||
assert notification.status == expected_status
|
assert notification.status == expected_status
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user