Refactor sqs.get_queue_attributes & add AttributeNames handling
This commit is contained in:
parent
6573f69087
commit
c3cb411c07
@ -6065,7 +6065,7 @@
|
||||
- [X] untag_resource
|
||||
|
||||
## sqs
|
||||
80% implemented
|
||||
85% implemented
|
||||
- [X] add_permission
|
||||
- [X] change_message_visibility
|
||||
- [ ] change_message_visibility_batch
|
||||
@ -6073,7 +6073,7 @@
|
||||
- [X] delete_message
|
||||
- [ ] delete_message_batch
|
||||
- [X] delete_queue
|
||||
- [ ] get_queue_attributes
|
||||
- [X] get_queue_attributes
|
||||
- [X] get_queue_url
|
||||
- [X] list_dead_letter_source_queues
|
||||
- [X] list_queue_tags
|
||||
|
@ -454,7 +454,7 @@ class BaseResponse(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
||||
index = 1
|
||||
while True:
|
||||
value_dict = self._get_multi_param_helper(prefix + str(index))
|
||||
if not value_dict:
|
||||
if not value_dict and value_dict != '':
|
||||
break
|
||||
|
||||
values.append(value_dict)
|
||||
|
@ -86,3 +86,13 @@ class TooManyEntriesInBatchRequest(RESTError):
|
||||
'Maximum number of entries per request are 10. '
|
||||
'You have sent {}.'.format(number)
|
||||
)
|
||||
|
||||
|
||||
class InvalidAttributeName(RESTError):
|
||||
code = 400
|
||||
|
||||
def __init__(self, attribute_name):
|
||||
super(InvalidAttributeName, self).__init__(
|
||||
'InvalidAttributeName',
|
||||
'Unknown Attribute {}.'.format(attribute_name)
|
||||
)
|
||||
|
@ -23,7 +23,8 @@ from .exceptions import (
|
||||
InvalidBatchEntryId,
|
||||
BatchRequestTooLong,
|
||||
BatchEntryIdsNotDistinct,
|
||||
TooManyEntriesInBatchRequest
|
||||
TooManyEntriesInBatchRequest,
|
||||
InvalidAttributeName
|
||||
)
|
||||
|
||||
DEFAULT_ACCOUNT_ID = 123456789012
|
||||
@ -161,7 +162,7 @@ class Message(BaseModel):
|
||||
|
||||
|
||||
class Queue(BaseModel):
|
||||
base_attributes = ['ApproximateNumberOfMessages',
|
||||
BASE_ATTRIBUTES = ['ApproximateNumberOfMessages',
|
||||
'ApproximateNumberOfMessagesDelayed',
|
||||
'ApproximateNumberOfMessagesNotVisible',
|
||||
'CreatedTimestamp',
|
||||
@ -172,9 +173,9 @@ class Queue(BaseModel):
|
||||
'QueueArn',
|
||||
'ReceiveMessageWaitTimeSeconds',
|
||||
'VisibilityTimeout']
|
||||
fifo_attributes = ['FifoQueue',
|
||||
FIFO_ATTRIBUTES = ['FifoQueue',
|
||||
'ContentBasedDeduplication']
|
||||
kms_attributes = ['KmsDataKeyReusePeriodSeconds',
|
||||
KMS_ATTRIBUTES = ['KmsDataKeyReusePeriodSeconds',
|
||||
'KmsMasterKeyId']
|
||||
ALLOWED_PERMISSIONS = ('*', 'ChangeMessageVisibility', 'DeleteMessage',
|
||||
'GetQueueAttributes', 'GetQueueUrl',
|
||||
@ -191,8 +192,9 @@ class Queue(BaseModel):
|
||||
|
||||
now = unix_time()
|
||||
self.created_timestamp = now
|
||||
self.queue_arn = 'arn:aws:sqs:{0}:123456789012:{1}'.format(self.region,
|
||||
self.name)
|
||||
self.queue_arn = 'arn:aws:sqs:{0}:{1}:{2}'.format(self.region,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
self.name)
|
||||
self.dead_letter_queue = None
|
||||
|
||||
self.lambda_event_source_mappings = {}
|
||||
@ -336,17 +338,17 @@ class Queue(BaseModel):
|
||||
def attributes(self):
|
||||
result = {}
|
||||
|
||||
for attribute in self.base_attributes:
|
||||
for attribute in self.BASE_ATTRIBUTES:
|
||||
attr = getattr(self, camelcase_to_underscores(attribute))
|
||||
result[attribute] = attr
|
||||
|
||||
if self.fifo_queue:
|
||||
for attribute in self.fifo_attributes:
|
||||
for attribute in self.FIFO_ATTRIBUTES:
|
||||
attr = getattr(self, camelcase_to_underscores(attribute))
|
||||
result[attribute] = attr
|
||||
|
||||
if self.kms_master_key_id:
|
||||
for attribute in self.kms_attributes:
|
||||
for attribute in self.KMS_ATTRIBUTES:
|
||||
attr = getattr(self, camelcase_to_underscores(attribute))
|
||||
result[attribute] = attr
|
||||
|
||||
@ -491,6 +493,28 @@ class SQSBackend(BaseBackend):
|
||||
return self.queues.pop(queue_name)
|
||||
return False
|
||||
|
||||
def get_queue_attributes(self, queue_name, attribute_names):
|
||||
queue = self.get_queue(queue_name)
|
||||
|
||||
if not len(attribute_names):
|
||||
attribute_names.append('All')
|
||||
|
||||
valid_names = ['All'] + queue.BASE_ATTRIBUTES + queue.FIFO_ATTRIBUTES + queue.KMS_ATTRIBUTES
|
||||
invalid_name = next((name for name in attribute_names if name not in valid_names), None)
|
||||
|
||||
if invalid_name or invalid_name == '':
|
||||
raise InvalidAttributeName(invalid_name)
|
||||
|
||||
attributes = {}
|
||||
|
||||
if 'All' in attribute_names:
|
||||
attributes = queue.attributes
|
||||
else:
|
||||
for name in (name for name in attribute_names if name in queue.attributes):
|
||||
attributes[name] = queue.attributes.get(name)
|
||||
|
||||
return attributes
|
||||
|
||||
def set_queue_attributes(self, queue_name, attributes):
|
||||
queue = self.get_queue(queue_name)
|
||||
queue._set_attributes(attributes)
|
||||
|
@ -11,7 +11,8 @@ from .exceptions import (
|
||||
MessageAttributesInvalid,
|
||||
MessageNotInflight,
|
||||
ReceiptHandleIsInvalid,
|
||||
EmptyBatchRequest
|
||||
EmptyBatchRequest,
|
||||
InvalidAttributeName
|
||||
)
|
||||
|
||||
MAXIMUM_VISIBILTY_TIMEOUT = 43200
|
||||
@ -169,10 +170,15 @@ class SQSResponse(BaseResponse):
|
||||
def get_queue_attributes(self):
|
||||
queue_name = self._get_queue_name()
|
||||
|
||||
queue = self.sqs_backend.get_queue(queue_name)
|
||||
if self.querystring.get('AttributeNames'):
|
||||
raise InvalidAttributeName('')
|
||||
|
||||
attribute_names = self._get_multi_param('AttributeName')
|
||||
|
||||
attributes = self.sqs_backend.get_queue_attributes(queue_name, attribute_names)
|
||||
|
||||
template = self.response_template(GET_QUEUE_ATTRIBUTES_RESPONSE)
|
||||
return template.render(queue=queue)
|
||||
return template.render(attributes=attributes)
|
||||
|
||||
def set_queue_attributes(self):
|
||||
# TODO validate self.get_param('QueueUrl')
|
||||
@ -443,7 +449,7 @@ DELETE_QUEUE_RESPONSE = """<DeleteQueueResponse>
|
||||
|
||||
GET_QUEUE_ATTRIBUTES_RESPONSE = """<GetQueueAttributesResponse>
|
||||
<GetQueueAttributesResult>
|
||||
{% for key, value in queue.attributes.items() %}
|
||||
{% for key, value in attributes.items() %}
|
||||
<Attribute>
|
||||
<Name>{{ key }}</Name>
|
||||
<Value>{{ value }}</Value>
|
||||
|
@ -5,6 +5,7 @@ import os
|
||||
import boto
|
||||
import boto3
|
||||
import botocore.exceptions
|
||||
import six
|
||||
from botocore.exceptions import ClientError
|
||||
from boto.exception import SQSError
|
||||
from boto.sqs.message import RawMessage, Message
|
||||
@ -365,6 +366,98 @@ def test_delete_queue():
|
||||
queue.delete()
|
||||
|
||||
|
||||
@mock_sqs
|
||||
def test_get_queue_attributes():
|
||||
client = boto3.client('sqs', region_name='us-east-1')
|
||||
response = client.create_queue(QueueName='test-queue')
|
||||
queue_url = response['QueueUrl']
|
||||
|
||||
response = client.get_queue_attributes(QueueUrl=queue_url)
|
||||
|
||||
response['Attributes']['ApproximateNumberOfMessages'].should.equal('0')
|
||||
response['Attributes']['ApproximateNumberOfMessagesDelayed'].should.equal('0')
|
||||
response['Attributes']['ApproximateNumberOfMessagesNotVisible'].should.equal('0')
|
||||
response['Attributes']['CreatedTimestamp'].should.be.a(six.string_types)
|
||||
response['Attributes']['DelaySeconds'].should.equal('0')
|
||||
response['Attributes']['LastModifiedTimestamp'].should.be.a(six.string_types)
|
||||
response['Attributes']['MaximumMessageSize'].should.equal('65536')
|
||||
response['Attributes']['MessageRetentionPeriod'].should.equal('345600')
|
||||
response['Attributes']['QueueArn'].should.equal('arn:aws:sqs:us-east-1:123456789012:test-queue')
|
||||
response['Attributes']['ReceiveMessageWaitTimeSeconds'].should.equal('0')
|
||||
response['Attributes']['VisibilityTimeout'].should.equal('30')
|
||||
|
||||
response = client.get_queue_attributes(
|
||||
QueueUrl=queue_url,
|
||||
AttributeNames=[
|
||||
'ApproximateNumberOfMessages',
|
||||
'MaximumMessageSize',
|
||||
'QueueArn',
|
||||
'VisibilityTimeout'
|
||||
]
|
||||
)
|
||||
|
||||
response['Attributes'].should.equal({
|
||||
'ApproximateNumberOfMessages': '0',
|
||||
'MaximumMessageSize': '65536',
|
||||
'QueueArn': 'arn:aws:sqs:us-east-1:123456789012:test-queue',
|
||||
'VisibilityTimeout': '30'
|
||||
})
|
||||
|
||||
# should not return any attributes, if it was not set before
|
||||
response = client.get_queue_attributes(
|
||||
QueueUrl=queue_url,
|
||||
AttributeNames=[
|
||||
'KmsMasterKeyId'
|
||||
]
|
||||
)
|
||||
|
||||
response.should_not.have.key('Attributes')
|
||||
|
||||
|
||||
@mock_sqs
|
||||
def test_get_queue_attributes_errors():
|
||||
client = boto3.client('sqs', region_name='us-east-1')
|
||||
response = client.create_queue(QueueName='test-queue')
|
||||
queue_url = response['QueueUrl']
|
||||
|
||||
client.get_queue_attributes.when.called_with(
|
||||
QueueUrl=queue_url + '-non-existing'
|
||||
).should.throw(
|
||||
ClientError,
|
||||
'The specified queue does not exist for this wsdl version.'
|
||||
)
|
||||
|
||||
client.get_queue_attributes.when.called_with(
|
||||
QueueUrl=queue_url,
|
||||
AttributeNames=[
|
||||
'QueueArn',
|
||||
'not-existing',
|
||||
'VisibilityTimeout'
|
||||
]
|
||||
).should.throw(
|
||||
ClientError,
|
||||
'Unknown Attribute not-existing.'
|
||||
)
|
||||
|
||||
client.get_queue_attributes.when.called_with(
|
||||
QueueUrl=queue_url,
|
||||
AttributeNames=[
|
||||
''
|
||||
]
|
||||
).should.throw(
|
||||
ClientError,
|
||||
'Unknown Attribute .'
|
||||
)
|
||||
|
||||
client.get_queue_attributes.when.called_with(
|
||||
QueueUrl = queue_url,
|
||||
AttributeNames = []
|
||||
).should.throw(
|
||||
ClientError,
|
||||
'Unknown Attribute .'
|
||||
)
|
||||
|
||||
|
||||
@mock_sqs
|
||||
def test_set_queue_attribute():
|
||||
sqs = boto3.resource('sqs', region_name='us-east-1')
|
||||
|
Loading…
Reference in New Issue
Block a user