Add sns.tag_resource
This commit is contained in:
parent
8d527743d5
commit
726775678c
@ -5866,7 +5866,7 @@
|
||||
- [ ] update_job
|
||||
|
||||
## sns
|
||||
52% implemented
|
||||
55% implemented
|
||||
- [ ] add_permission
|
||||
- [ ] check_if_phone_number_is_opted_out
|
||||
- [ ] confirm_subscription
|
||||
@ -5897,7 +5897,7 @@
|
||||
- [X] set_subscription_attributes
|
||||
- [ ] set_topic_attributes
|
||||
- [X] subscribe
|
||||
- [ ] tag_resource
|
||||
- [x] tag_resource
|
||||
- [X] unsubscribe
|
||||
- [ ] untag_resource
|
||||
|
||||
|
@ -10,6 +10,14 @@ class SNSNotFoundError(RESTError):
|
||||
"NotFound", message)
|
||||
|
||||
|
||||
class ResourceNotFoundError(RESTError):
|
||||
code = 404
|
||||
|
||||
def __init__(self):
|
||||
super(ResourceNotFoundError, self).__init__(
|
||||
'ResourceNotFound', 'Resource does not exist')
|
||||
|
||||
|
||||
class DuplicateSnsEndpointError(RESTError):
|
||||
code = 400
|
||||
|
||||
@ -42,6 +50,14 @@ class InvalidParameterValue(RESTError):
|
||||
"InvalidParameterValue", message)
|
||||
|
||||
|
||||
class TagLimitExceededError(RESTError):
|
||||
code = 400
|
||||
|
||||
def __init__(self):
|
||||
super(TagLimitExceededError, self).__init__(
|
||||
'TagLimitExceeded', 'Could not complete request: tag quota of per resource exceeded')
|
||||
|
||||
|
||||
class InternalError(RESTError):
|
||||
code = 500
|
||||
|
||||
|
@ -18,7 +18,7 @@ from moto.awslambda import lambda_backends
|
||||
|
||||
from .exceptions import (
|
||||
SNSNotFoundError, DuplicateSnsEndpointError, SnsEndpointDisabled, SNSInvalidParameter,
|
||||
InvalidParameterValue, InternalError
|
||||
InvalidParameterValue, InternalError, ResourceNotFoundError, TagLimitExceededError
|
||||
)
|
||||
from .utils import make_arn_for_topic, make_arn_for_subscription
|
||||
|
||||
@ -504,8 +504,23 @@ class SNSBackend(BaseBackend):
|
||||
raise SNSInvalidParameter("Invalid parameter: FilterPolicy: Match value must be String, number, true, false, or null")
|
||||
|
||||
def list_tags_for_resource(self, resource_arn):
|
||||
if resource_arn not in self.topics:
|
||||
raise ResourceNotFoundError
|
||||
|
||||
return self.topics[resource_arn]._tags
|
||||
|
||||
def tag_resource(self, resource_arn, tags):
|
||||
if resource_arn not in self.topics:
|
||||
raise ResourceNotFoundError
|
||||
|
||||
updated_tags = self.topics[resource_arn]._tags.copy()
|
||||
updated_tags.update(tags)
|
||||
|
||||
if len(updated_tags) > 50:
|
||||
raise TagLimitExceededError
|
||||
|
||||
self.topics[resource_arn]._tags = updated_tags
|
||||
|
||||
|
||||
sns_backends = {}
|
||||
for region in Session().get_available_regions('sns'):
|
||||
|
@ -699,15 +699,19 @@ class SNSResponse(BaseResponse):
|
||||
def list_tags_for_resource(self):
|
||||
arn = self._get_param('ResourceArn')
|
||||
|
||||
if arn not in self.backend.topics:
|
||||
error_response = self._error('ResourceNotFound', 'Resource does not exist')
|
||||
return error_response, dict(status=404)
|
||||
|
||||
result = self.backend.list_tags_for_resource(arn)
|
||||
|
||||
template = self.response_template(LIST_TAGS_FOR_RESOURCE_TEMPLATE)
|
||||
return template.render(tags=result)
|
||||
|
||||
def tag_resource(self):
|
||||
arn = self._get_param('ResourceArn')
|
||||
tags = self._get_tags()
|
||||
|
||||
self.backend.tag_resource(arn, tags)
|
||||
|
||||
return self.response_template(TAG_RESOURCE_TEMPLATE).render()
|
||||
|
||||
|
||||
CREATE_TOPIC_TEMPLATE = """<CreateTopicResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
||||
<CreateTopicResult>
|
||||
@ -1105,3 +1109,10 @@ LIST_TAGS_FOR_RESOURCE_TEMPLATE = """<ListTagsForResourceResponse xmlns="http://
|
||||
<RequestId>97fa763f-861b-5223-a946-20251f2a42e2</RequestId>
|
||||
</ResponseMetadata>
|
||||
</ListTagsForResourceResponse>"""
|
||||
|
||||
TAG_RESOURCE_TEMPLATE = """<TagResourceResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
||||
<TagResourceResult/>
|
||||
<ResponseMetadata>
|
||||
<RequestId>fd4ab1da-692f-50a7-95ad-e7c665877d98</RequestId>
|
||||
</ResponseMetadata>
|
||||
</TagResourceResponse>"""
|
||||
|
@ -47,8 +47,8 @@ def test_create_topic_with_attributes():
|
||||
@mock_sns
|
||||
def test_create_topic_with_tags():
|
||||
conn = boto3.client("sns", region_name="us-east-1")
|
||||
conn.create_topic(
|
||||
Name='some-topic-with-attribute',
|
||||
response = conn.create_topic(
|
||||
Name='some-topic-with-tags',
|
||||
Tags=[
|
||||
{
|
||||
'Key': 'tag_key_1',
|
||||
@ -60,8 +60,7 @@ def test_create_topic_with_tags():
|
||||
}
|
||||
]
|
||||
)
|
||||
topics_json = conn.list_topics()
|
||||
topic_arn = topics_json["Topics"][0]['TopicArn']
|
||||
topic_arn = response['TopicArn']
|
||||
|
||||
conn.list_tags_for_resource(ResourceArn=topic_arn)['Tags'].should.equal([
|
||||
{
|
||||
@ -231,3 +230,134 @@ def test_add_remove_permissions():
|
||||
TopicArn=response['TopicArn'],
|
||||
Label='Test1234'
|
||||
)
|
||||
|
||||
|
||||
@mock_sns
|
||||
def test_tag_topic():
|
||||
conn = boto3.client('sns', region_name='us-east-1')
|
||||
response = conn.create_topic(
|
||||
Name = 'some-topic-with-tags'
|
||||
)
|
||||
topic_arn = response['TopicArn']
|
||||
|
||||
conn.tag_resource(
|
||||
ResourceArn=topic_arn,
|
||||
Tags=[
|
||||
{
|
||||
'Key': 'tag_key_1',
|
||||
'Value': 'tag_value_1'
|
||||
}
|
||||
]
|
||||
)
|
||||
conn.list_tags_for_resource(ResourceArn = topic_arn)['Tags'].should.equal([
|
||||
{
|
||||
'Key': 'tag_key_1',
|
||||
'Value': 'tag_value_1'
|
||||
}
|
||||
])
|
||||
|
||||
conn.tag_resource(
|
||||
ResourceArn=topic_arn,
|
||||
Tags=[
|
||||
{
|
||||
'Key': 'tag_key_2',
|
||||
'Value': 'tag_value_2'
|
||||
}
|
||||
]
|
||||
)
|
||||
conn.list_tags_for_resource(ResourceArn = topic_arn)['Tags'].should.equal([
|
||||
{
|
||||
'Key': 'tag_key_1',
|
||||
'Value': 'tag_value_1'
|
||||
},
|
||||
{
|
||||
'Key': 'tag_key_2',
|
||||
'Value': 'tag_value_2'
|
||||
}
|
||||
])
|
||||
|
||||
conn.tag_resource(
|
||||
ResourceArn = topic_arn,
|
||||
Tags = [
|
||||
{
|
||||
'Key': 'tag_key_1',
|
||||
'Value': 'tag_value_X'
|
||||
}
|
||||
]
|
||||
)
|
||||
conn.list_tags_for_resource(ResourceArn = topic_arn)['Tags'].should.equal([
|
||||
{
|
||||
'Key': 'tag_key_1',
|
||||
'Value': 'tag_value_X'
|
||||
},
|
||||
{
|
||||
'Key': 'tag_key_2',
|
||||
'Value': 'tag_value_2'
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
@mock_sns
|
||||
def test_list_tags_for_resource_error():
|
||||
conn = boto3.client('sns', region_name = 'us-east-1')
|
||||
conn.create_topic(
|
||||
Name = 'some-topic-with-tags',
|
||||
Tags = [
|
||||
{
|
||||
'Key': 'tag_key_1',
|
||||
'Value': 'tag_value_X'
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
conn.list_tags_for_resource.when.called_with(
|
||||
ResourceArn = 'not-existing-topic'
|
||||
).should.throw(
|
||||
ClientError,
|
||||
'Resource does not exist'
|
||||
)
|
||||
|
||||
|
||||
@mock_sns
|
||||
def test_tag_resource_errors():
|
||||
conn = boto3.client('sns', region_name = 'us-east-1')
|
||||
response = conn.create_topic(
|
||||
Name = 'some-topic-with-tags',
|
||||
Tags = [
|
||||
{
|
||||
'Key': 'tag_key_1',
|
||||
'Value': 'tag_value_X'
|
||||
}
|
||||
]
|
||||
)
|
||||
topic_arn = response['TopicArn']
|
||||
|
||||
conn.tag_resource.when.called_with(
|
||||
ResourceArn = 'not-existing-topic',
|
||||
Tags = [
|
||||
{
|
||||
'Key': 'tag_key_1',
|
||||
'Value': 'tag_value_1'
|
||||
}
|
||||
]
|
||||
).should.throw(
|
||||
ClientError,
|
||||
'Resource does not exist'
|
||||
)
|
||||
|
||||
too_many_tags = [{'Key': 'tag_key_{}'.format(i), 'Value': 'tag_value_{}'.format(i)} for i in range(51)]
|
||||
conn.tag_resource.when.called_with(
|
||||
ResourceArn = topic_arn,
|
||||
Tags = too_many_tags
|
||||
).should.throw(
|
||||
ClientError,
|
||||
'Could not complete request: tag quota of per resource exceeded'
|
||||
)
|
||||
|
||||
# when the request fails, the tags should not be updated
|
||||
conn.list_tags_for_resource(ResourceArn = topic_arn)['Tags'].should.equal([
|
||||
{
|
||||
'Key': 'tag_key_1',
|
||||
'Value': 'tag_value_X'
|
||||
}
|
||||
])
|
||||
|
Loading…
Reference in New Issue
Block a user