From 49045fe6807d11aa28a57f65eb38f08a887d49f3 Mon Sep 17 00:00:00 2001 From: gruebel Date: Sun, 13 Oct 2019 14:51:31 +0200 Subject: [PATCH 1/3] Add tags parameter to sqs.create_queue --- moto/sqs/models.py | 8 +++++- moto/sqs/responses.py | 13 ++++++--- tests/test_sqs/test_sqs.py | 58 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/moto/sqs/models.py b/moto/sqs/models.py index 188e25e9..260447dc 100644 --- a/moto/sqs/models.py +++ b/moto/sqs/models.py @@ -415,7 +415,7 @@ class SQSBackend(BaseBackend): self.__dict__ = {} self.__init__(region_name) - def create_queue(self, name, **kwargs): + def create_queue(self, name, tags, **kwargs): queue = self.queues.get(name) if queue: try: @@ -454,6 +454,8 @@ class SQSBackend(BaseBackend): pass queue = Queue(name, region=self.region_name, **kwargs) self.queues[name] = queue + + queue.tags = tags return queue def list_queues(self, queue_name_prefix): @@ -654,6 +656,10 @@ class SQSBackend(BaseBackend): def untag_queue(self, queue_name, tag_keys): queue = self.get_queue(queue_name) + + if len(tag_keys) == 0: + raise RESTError('InvalidParameterValue', 'Tag keys must be between 1 and 128 characters in length.') + for key in tag_keys: try: del queue.tags[key] diff --git a/moto/sqs/responses.py b/moto/sqs/responses.py index 5ddaf884..ce1dcbf8 100644 --- a/moto/sqs/responses.py +++ b/moto/sqs/responses.py @@ -33,6 +33,12 @@ class SQSResponse(BaseResponse): self._attribute = self._get_map_prefix('Attribute', key_end='.Name', value_end='.Value') return self._attribute + @property + def tags(self): + if not hasattr(self, '_tags'): + self._tags = self._get_map_prefix('Tag', key_end='.Key', value_end='.Value') + return self._tags + def _get_queue_name(self): try: queue_name = self.querystring.get('QueueUrl')[0].split("/")[-1] @@ -73,12 +79,12 @@ class SQSResponse(BaseResponse): queue_name = self._get_param("QueueName") try: - queue = self.sqs_backend.create_queue(queue_name, **self.attribute) + queue = self.sqs_backend.create_queue(queue_name, self.tags, **self.attribute) except MessageAttributesInvalid as e: return self._error('InvalidParameterValue', e.description) template = self.response_template(CREATE_QUEUE_RESPONSE) - return template.render(queue=queue, request_url=request_url) + return template.render(queue_url=queue.url(request_url)) def get_queue_url(self): request_url = urlparse(self.uri) @@ -416,8 +422,7 @@ class SQSResponse(BaseResponse): CREATE_QUEUE_RESPONSE = """ - {{ queue.url(request_url) }} - {{ queue.visibility_timeout }} + {{ queue_url }} diff --git a/tests/test_sqs/test_sqs.py b/tests/test_sqs/test_sqs.py index 56d82ea6..6d06b87c 100644 --- a/tests/test_sqs/test_sqs.py +++ b/tests/test_sqs/test_sqs.py @@ -17,6 +17,7 @@ import time import uuid from moto import settings, mock_sqs, mock_sqs_deprecated +from moto.sqs.exceptions import QueueDoesNotExist from tests.helpers import requires_boto_gte import tests.backport_assert_raises # noqa from nose.tools import assert_raises @@ -140,6 +141,22 @@ def test_create_queue_kms(): queue.attributes.get('KmsDataKeyReusePeriodSeconds').should.equal('600') +@mock_sqs +def test_create_queue_with_tags(): + client = boto3.client('sqs', region_name='us-east-1') + response = client.create_queue( + QueueName = 'test-queue-with-tags', + tags = { + 'tag_key_1': 'tag_value_1' + } + ) + queue_url = response['QueueUrl'] + + client.list_queue_tags(QueueUrl = queue_url)['Tags'].should.equal({ + 'tag_key_1': 'tag_value_1' + }) + + @mock_sqs def test_get_nonexistent_queue(): sqs = boto3.resource('sqs', region_name='us-east-1') @@ -959,6 +976,47 @@ def test_tags(): resp['Tags'].should.contain('test1') resp['Tags'].should_not.contain('test2') + # removing a non existing tag should not raise any error + client.untag_queue( + QueueUrl=queue_url, + TagKeys=[ + 'not-existing-tag' + ] + ) + client.list_queue_tags(QueueUrl=queue_url)['Tags'].should.equal({ + 'test1': 'value1' + }) + + +@mock_sqs +def test_untag_queue_errors(): + client = boto3.client('sqs', region_name='us-east-1') + + response = client.create_queue( + QueueName='test-queue-with-tags', + tags={ + 'tag_key_1': 'tag_value_1' + } + ) + queue_url = response['QueueUrl'] + + client.untag_queue.when.called_with( + QueueUrl=queue_url + '-not-existing', + TagKeys=[ + 'tag_key_1' + ] + ).should.throw( + QueueDoesNotExist + ) + + client.untag_queue.when.called_with( + QueueUrl=queue_url, + TagKeys=[] + ).should.throw( + ClientError, + 'Tag keys must be between 1 and 128 characters in length.' + ) + @mock_sqs def test_create_fifo_queue_with_dlq(): From 0d8c81a211020c873f7cafc552b5a6e133571158 Mon Sep 17 00:00:00 2001 From: gruebel Date: Sun, 13 Oct 2019 17:18:11 +0200 Subject: [PATCH 2/3] fix CloudFormation tests --- moto/sqs/models.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/moto/sqs/models.py b/moto/sqs/models.py index 260447dc..922da704 100644 --- a/moto/sqs/models.py +++ b/moto/sqs/models.py @@ -415,7 +415,7 @@ class SQSBackend(BaseBackend): self.__dict__ = {} self.__init__(region_name) - def create_queue(self, name, tags, **kwargs): + def create_queue(self, name, tags=None, **kwargs): queue = self.queues.get(name) if queue: try: @@ -455,7 +455,9 @@ class SQSBackend(BaseBackend): queue = Queue(name, region=self.region_name, **kwargs) self.queues[name] = queue - queue.tags = tags + if tags: + queue.tags = tags + return queue def list_queues(self, queue_name_prefix): From ce3f1eed66d0d435904898c0bb7a11d3f2057bf1 Mon Sep 17 00:00:00 2001 From: gruebel Date: Sun, 13 Oct 2019 20:32:53 +0200 Subject: [PATCH 3/3] fix test server error --- moto/sqs/responses.py | 6 +++++- tests/test_sqs/test_sqs.py | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/moto/sqs/responses.py b/moto/sqs/responses.py index ce1dcbf8..747fa236 100644 --- a/moto/sqs/responses.py +++ b/moto/sqs/responses.py @@ -406,7 +406,11 @@ class SQSResponse(BaseResponse): queue_name = self._get_queue_name() tag_keys = self._get_multi_param('TagKey') - self.sqs_backend.untag_queue(queue_name, tag_keys) + try: + self.sqs_backend.untag_queue(queue_name, tag_keys) + except QueueDoesNotExist as e: + return self._error('AWS.SimpleQueueService.NonExistentQueue', + e.description) template = self.response_template(UNTAG_QUEUE_RESPONSE) return template.render() diff --git a/tests/test_sqs/test_sqs.py b/tests/test_sqs/test_sqs.py index 6d06b87c..bc9fa8e4 100644 --- a/tests/test_sqs/test_sqs.py +++ b/tests/test_sqs/test_sqs.py @@ -17,7 +17,6 @@ import time import uuid from moto import settings, mock_sqs, mock_sqs_deprecated -from moto.sqs.exceptions import QueueDoesNotExist from tests.helpers import requires_boto_gte import tests.backport_assert_raises # noqa from nose.tools import assert_raises @@ -1006,7 +1005,8 @@ def test_untag_queue_errors(): 'tag_key_1' ] ).should.throw( - QueueDoesNotExist + ClientError, + "The specified queue does not exist for this wsdl version." ) client.untag_queue.when.called_with(