Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion awsimple/__version__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
__application_name__ = "awsimple"
__title__ = __application_name__
__author__ = "abel"
__version__ = "4.2.0"
__version__ = "5.0.0"
__author_email__ = "j@abel.co"
__url__ = "https://github.com/jamesabel/awsimple"
__download_url__ = "https://github.com/jamesabel/awsimple"
Expand Down
33 changes: 19 additions & 14 deletions awsimple/pubsub.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from typeguard import typechecked
from botocore.exceptions import ClientError
import strif

from .sns import SNSAccess
from .sqs import SQSPollAccess, get_all_sqs_queues
Expand Down Expand Up @@ -121,17 +122,17 @@ def run(self):


@lru_cache
def make_name_aws_safe(name: str) -> str:
def make_name_aws_safe(*args: str) -> str:
"""
Make a name safe for an SQS queue to subscribe to an SNS topic.
Make a name safe for an SQS queue to subscribe to an SNS topic. AWS has a bunch of undocumented restrictions on names, so we just hash the name to a base36 string.

:param name: input name
:params: input name(s)
:return: AWS safe name
"""
safe_name = "".join([c for c in name.strip().lower() if c.isalnum()]) # only allow alphanumeric characters
if len(safe_name) < 1:
raise ValueError(f'"{name}" is not valid after making AWS safe - result must contain at least one alphanumeric character.')
return safe_name

base36 = strif.hash_string("".join(args)).base36
assert len(base36) == 31
return base36


class PubSub(Process):
Expand All @@ -155,9 +156,10 @@ def __init__(
:param node_name: Node name (SQS queue name suffix). Defaults to a combination of computer name and username, but can be passed in for customization and/or testing.
:param sub_callback: Optional thread and process safe callback function to be called when a new message is received. The function should accept a single argument, which will be the message as a dictionary.
"""

self.channel = "ps" + make_name_aws_safe(channel) # prefix with ps (pubsub) to avoid collisions with other uses of SNS topics and SQS queues
self.node_name = make_name_aws_safe(node_name)
self.aws_resource_prefix = "ps" # for pubsub
self.channel = self.aws_resource_prefix + make_name_aws_safe(channel) # prefix with ps (pubsub) to avoid collisions with other uses of SNS topics and SQS queues
self.node_name = node_name
self.sqs_queue_name = self.aws_resource_prefix + make_name_aws_safe(self.channel, self.node_name)
self.sub_callback = sub_callback

self.profile_name = profile_name
Expand All @@ -174,8 +176,6 @@ def __init__(

def run(self):

sqs_queue_name = f"{self.channel}{self.node_name}"

sns = SNSAccess(
self.channel,
auto_create=True,
Expand All @@ -185,11 +185,16 @@ def run(self):
region_name=self.region_name,
)
sqs_metadata = _DynamoDBMetadataTable(
sqs_name, sqs_queue_name, profile_name=self.profile_name, aws_access_key_id=self.aws_access_key_id, aws_secret_access_key=self.aws_secret_access_key, region_name=self.region_name
sqs_name,
self.sqs_queue_name,
profile_name=self.profile_name,
aws_access_key_id=self.aws_access_key_id,
aws_secret_access_key=self.aws_secret_access_key,
region_name=self.region_name,
)

sqs = SQSPollAccess(
sqs_queue_name, profile_name=self.profile_name, aws_access_key_id=self.aws_access_key_id, aws_secret_access_key=self.aws_secret_access_key, region_name=self.region_name
self.sqs_queue_name, profile_name=self.profile_name, aws_access_key_id=self.aws_access_key_id, aws_secret_access_key=self.aws_secret_access_key, region_name=self.region_name
)
if not sqs.exists():
sqs.create_queue()
Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ tobool
urllib3
python-dateutil
yasf
strif
#
# examples
ismain
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
keywords=["aws", "cloud", "storage", "database", "dynamodb", "s3"],
packages=[__title__],
package_data={__title__: [readme_file_path, "py.typed"]},
install_requires=["boto3", "typeguard", "hashy>=0.1.1", "dictim", "appdirs", "tobool", "urllib3", "python-dateutil", "yasf"],
install_requires=["boto3", "typeguard", "hashy>=0.1.1", "dictim", "appdirs", "tobool", "urllib3", "python-dateutil", "yasf", "strif"],
project_urls={"Documentation": "https://awsimple.readthedocs.io/"},
classifiers=[],
python_requires=">3.10",
Expand Down
16 changes: 16 additions & 0 deletions test_awsimple/test_pubsub/test_pubsub_make_name_aws_safe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from awsimple.pubsub import make_name_aws_safe


def test_pubsub_make_name_aws_safe():

assert make_name_aws_safe("My Topic Name!") == "lc6dwk3bn32n6upqpos4ryluxluxsvd"
assert make_name_aws_safe("Topic@123") == "jwxskzojw9o2717rs24rtwqgy50v4yn"
assert make_name_aws_safe("with.a.dot") == "boo0z8dyxiirijsg69qg4g2yg3tsd7w"
assert make_name_aws_safe("a_6.3") == "d4gg6yrpd2pieqhchpz2qlc7a52shxy"
assert make_name_aws_safe("-5") == "dk1zux1ndufnok5x2v4uj3flwtzxpr6"
assert make_name_aws_safe("0") == "lasw0dw8dpjcoalne79l4km57y91kwc"
assert make_name_aws_safe("Valid_Name-123") == "5fpq80the6qly6weat39tnh57x8bjhm"
assert make_name_aws_safe("Invalid#Name$With%Special&Chars*") == "jbudqy4oq2aqhcxgs40b0nmahou3pgq"

assert make_name_aws_safe("ab") == "phbce4exwcst2t3d0hqd8k81nc27kd8"
assert make_name_aws_safe("a", "b") == "phbce4exwcst2t3d0hqd8k81nc27kd8"
23 changes: 0 additions & 23 deletions test_awsimple/test_pubsub_make_name_aws_safe.py

This file was deleted.