-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use Pinpoint by default #2173
Use Pinpoint by default #2173
Conversation
Co-authored-by: Jimmy Royer <[email protected]>
Co-authored-by: Jimmy Royer <[email protected]>
Co-authored-by: Jimmy Royer <[email protected]>
Co-authored-by: Jimmy Royer <[email protected]>
Co-authored-by: Jimmy Royer <[email protected]>
Co-authored-by: Jimmy Royer <[email protected]>
from tests.conftest import set_config_values | ||
|
||
|
||
@pytest.mark.serial |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's some sort of race condition in our tests that I couldn't figure out :/ If these two tests are not run serially then something resets the config variables that they change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be a great topic for a code review session. It seems we have a misunderstanding on our some of our test concurrency is setup and fails when they should be successful. We can put our mind to it and try to brainstorm on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave some more thoughts to this and one thing I wish we could do better is OOP in our code base. We barely have much and this could be our focus on code reviews session. We rely a lot on environment variables which is not a good practice in general, as the code relies on environment rather than configuration of the logic to run. Encapsulating the pool config in an object would make this easier probably to run instead of relying on environments. Do you know what I mean here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do pull the env vars out of the env and put into the Config
object, but we should make sure that we always read that object and never the env vars directly (which I think we're pretty good at?). I think that there's magic going on behind the scenes though (with flask, for example), where it takes vars directly from the env :/
In this case, though, in the test I made serial the app wasn't using the values of Config
that I added in the test setup 😞 Which - how can that happen?
except Exception as e: | ||
self.statsd_client.incr("clients.sns.error") | ||
raise str(e) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This stuff was redundant and also the raise didn't work! You can't raise a string, just some subclass of Exception
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pylint for the win! I feel bad we had that for that long in the code. The whole error management does look weird in retrospective, thank you for refactoring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha, I didn't find it with pylint but by accidentally triggering the error locally (I was trying to send to a USA number without setting the AWS_US_TOLL_FREE_NUMBER
variable)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. I thought it might be pylint because the latter did raise it as a potential problem when I looked at this code locally in vscode.
if template_id is not None and str(template_id) in self.current_app.config["AWS_PINPOINT_SC_TEMPLATE_IDS"]: | ||
pool_id = self.current_app.config["AWS_PINPOINT_SC_POOL_ID"] | ||
else: | ||
pool_id = self.current_app.config["AWS_PINPOINT_DEFAULT_POOL_ID"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if the pool_id is None
? Is a random OriginationIdentity
would be used then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the OriginationIdentity
is None
in the boto call then the call returns an error
Invalid type for parameter OriginationIdentity, value: None, type: <class 'NoneType'>, valid types: <class 'str'>
But as you mention below, we catch that case in our code and fall back to SNS.
@@ -267,6 +267,7 @@ class Config(object): | |||
AWS_SES_SECRET_KEY = os.getenv("AWS_SES_SECRET_KEY") | |||
AWS_PINPOINT_REGION = os.getenv("AWS_PINPOINT_REGION", "us-west-2") | |||
AWS_PINPOINT_SC_POOL_ID = os.getenv("AWS_PINPOINT_SC_POOL_ID", None) | |||
AWS_PINPOINT_DEFAULT_POOL_ID = os.getenv("AWS_PINPOINT_DEFAULT_POOL_ID", None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we really want None
here as a fallback default, or rather prevent the server from booting up to prevent a misconfiguration. It depends how OriginationIdentity
set to None
in the send_text_message
call behaves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok reading the code further, it seems that a None
value would route the SNS implementation to get used instead. I got this right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah exactly. A None
value will break the Pinpoint send, so right now we route to SNS. In the future we may want to throw an error instead (ie when we insist on Pinooint for everything). Right now it allows production to ignore pinpoint entirely since we don't have it set there yet.
) -> Any: | ||
""" | ||
Get the provider to use for sending the notification. | ||
SMS that are being sent with a dedicated number or to a US number should not use Pinpoint. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the documentation and typing annotations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured I had added enough new logic to this function that some documentation was useful 😬
with pytest.raises(ValueError) as excinfo: | ||
aws_pinpoint_client.send_sms(to, content, reference) | ||
|
||
assert "No valid numbers found for SMS delivery" in str(excinfo.value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have a warning alert in TF specifically for this one? 🤔 I guess it might fall into celery errors but these might be generic enough that we don't always check on these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
possibly, though this is a bit of a strange test - testing that if the notification has an invalid phone number in it then we get a log. Agree though that this is a strange thing that we'd like surfaced immediately though. Basically it means that we screwed up the phone number and AWS doesn't recognize it. So, for example, we start sending texts to a new country and our number formatter messes up. Yeah, I'll add a warning for these 👍
assert provider.name == "sns" | ||
|
||
@pytest.mark.parametrize("sc_pool_id, default_pool_id", [(None, "default_pool_id"), ("sc_pool_id", None)]) | ||
def test_should_use_sns_if_pinpoint_not_configured(self, restore_provider_details, notify_api, sc_pool_id, default_pool_id): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it
@@ -51,6 +51,53 @@ | |||
from tests.conftest import set_config_values | |||
|
|||
|
|||
class TestProviderToUse: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice set of tests!
Co-authored-by: Jimmy Royer <[email protected]>
Co-authored-by: Jimmy Royer <[email protected]>
Co-authored-by: Jimmy Royer <[email protected]>
eec25fc
to
91aca6a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! can't wait to have more of the pool config going forward!
Summary | Résumé
Use Pinpoint by default to send the non-shortcode SMS using the default pool.
Exceptions are notifications sent from a dedicated long code and notifications sent to American phone numbers. These will still be sent by SNS.
Related Issues | Cartes liées
Test instructions | Instructions pour tester la modification
AWS_PINPOINT_SC_POOL_ID
,AWS_PINPOINT_DEFAULT_POOL_ID
, andAWS_US_TOLL_FREE_NUMBER
environment variables to the values in stagingAWS_PINPOINT_SC_TEMPLATE_IDS
to a list of some sms template ids (from your local install). Just one is okSMS can be sent with:
AWS Pinpoint request finished in ...
and SMS will be sent from the SC pool number or the default pool number as appropriate.AWS SNS request finished in ...
Tests:
AWS_PINPOINT_SC_POOL_ID
orAWS_PINPOINT_DEFAULT_POOL_ID
toNone
, restart both your terminal window and celery, and send to yourself. It should send using SNS.Release Instructions | Instructions pour le déploiement
None.
Note in particular that if the pool_id variables are not sent then we default to just using SNS.
Reviewer checklist | Liste de vérification du réviseur