Merge branch 'master' of https://github.com/spulec/moto into 0.4.1-threadsafe

* 'master' of https://github.com/spulec/moto: (25 commits)
  Add @zkourouma to authors.
  0.4.2
  Fix bug where listener certificate was not being saved correctly when creating an elb. Added test to cover that case.
  [dynamodb2] adds lookup method to Table class
  Add IAM list_groups and list_groups_for_user. Closes #343.
  Fix for deleting Route53 record sets with set identifiers. Closes #342.
  Use dummy date instead of an invalid date
  Adding support for comments on hosted zones.
  Add availability zone support to Subnets created via CloudFormation
  Make availability zone dynamic in Subnet Response templates
  Add filter "availabilityZone" to DescribeSubnets and add availability zone support too
  allow starting without reseting
  Fix bug with empty string for instance vpc_id. Closes #337.
  Fix default security group description.
  Update responses.py
  Add @mrucci to authors.
  Fix merge conflicts.
  Add support for ELB attributes.
  cast to int when doing math.
  General cleanup.
  ...
This commit is contained in:
Jeffrey Gelens 2015-05-29 11:35:14 +02:00
commit e722b67f36
33 changed files with 1381 additions and 167 deletions

10
moto/sns/exceptions.py Normal file
View file

@ -0,0 +1,10 @@
from __future__ import unicode_literals
from moto.core.exceptions import RESTError
class SNSNotFoundError(RESTError):
code = 404
def __init__(self, message):
super(SNSNotFoundError, self).__init__(
"NotFound", message)

View file

@ -11,6 +11,7 @@ from moto.compat import OrderedDict
from moto.core import BaseBackend
from moto.core.utils import iso_8601_datetime_with_milliseconds
from moto.sqs import sqs_backends
from .exceptions import SNSNotFoundError
from .utils import make_arn_for_topic, make_arn_for_subscription
DEFAULT_ACCOUNT_ID = 123456789012
@ -93,10 +94,52 @@ class Subscription(object):
}
class PlatformApplication(object):
def __init__(self, region, name, platform, attributes):
self.region = region
self.name = name
self.platform = platform
self.attributes = attributes
@property
def arn(self):
return "arn:aws:sns:{region}:123456789012:app/{platform}/{name}".format(
region=self.region,
platform=self.platform,
name=self.name,
)
class PlatformEndpoint(object):
def __init__(self, region, application, custom_user_data, token, attributes):
self.region = region
self.application = application
self.custom_user_data = custom_user_data
self.token = token
self.attributes = attributes
self.id = uuid.uuid4()
@property
def arn(self):
return "arn:aws:sns:{region}:123456789012:endpoint/{platform}/{name}/{id}".format(
region=self.region,
platform=self.application.platform,
name=self.application.name,
id=self.id,
)
def publish(self, message):
message_id = six.text_type(uuid.uuid4())
# This is where we would actually send a message
return message_id
class SNSBackend(BaseBackend):
def __init__(self):
self.topics = OrderedDict()
self.subscriptions = OrderedDict()
self.applications = {}
self.platform_endpoints = {}
def create_topic(self, name):
topic = Topic(name, self)
@ -121,7 +164,10 @@ class SNSBackend(BaseBackend):
self.topics.pop(arn)
def get_topic(self, arn):
return self.topics[arn]
try:
return self.topics[arn]
except KeyError:
raise SNSNotFoundError("Topic with arn {0} not found".format(arn))
def set_topic_attribute(self, topic_arn, attribute_name, attribute_value):
topic = self.get_topic(topic_arn)
@ -144,11 +190,61 @@ class SNSBackend(BaseBackend):
else:
return self._get_values_nexttoken(self.subscriptions, next_token)
def publish(self, topic_arn, message):
topic = self.get_topic(topic_arn)
message_id = topic.publish(message)
def publish(self, arn, message):
try:
topic = self.get_topic(arn)
message_id = topic.publish(message)
except SNSNotFoundError:
endpoint = self.get_endpoint(arn)
message_id = endpoint.publish(message)
return message_id
def create_platform_application(self, region, name, platform, attributes):
application = PlatformApplication(region, name, platform, attributes)
self.applications[application.arn] = application
return application
def get_application(self, arn):
try:
return self.applications[arn]
except KeyError:
raise SNSNotFoundError("Application with arn {0} not found".format(arn))
def set_application_attributes(self, arn, attributes):
application = self.get_application(arn)
application.attributes.update(attributes)
return application
def list_platform_applications(self):
return self.applications.values()
def delete_platform_application(self, platform_arn):
self.applications.pop(platform_arn)
def create_platform_endpoint(self, region, application, custom_user_data, token, attributes):
platform_endpoint = PlatformEndpoint(region, application, custom_user_data, token, attributes)
self.platform_endpoints[platform_endpoint.arn] = platform_endpoint
return platform_endpoint
def list_endpoints_by_platform_application(self, application_arn):
return [
endpoint for endpoint
in self.platform_endpoints.values()
if endpoint.application.arn == application_arn
]
def get_endpoint(self, arn):
try:
return self.platform_endpoints[arn]
except KeyError:
raise SNSNotFoundError("Endpoint with arn {0} not found".format(arn))
def set_endpoint_attributes(self, arn, attributes):
endpoint = self.get_endpoint(arn)
endpoint.attributes.update(attributes)
return endpoint
sns_backends = {}
for region in boto.sns.regions():
sns_backends[region.name] = SNSBackend()

View file

@ -12,6 +12,14 @@ class SNSResponse(BaseResponse):
def backend(self):
return sns_backends[self.region]
def _get_attributes(self):
attributes = self._get_list_prefix('Attributes.entry')
return dict(
(attribute['key'], attribute['value'])
for attribute
in attributes
)
def create_topic(self):
name = self._get_param('Name')
topic = self.backend.create_topic(name)
@ -170,9 +178,11 @@ class SNSResponse(BaseResponse):
})
def publish(self):
target_arn = self._get_param('TargetArn')
topic_arn = self._get_param('TopicArn')
arn = target_arn if target_arn else topic_arn
message = self._get_param('Message')
message_id = self.backend.publish(topic_arn, message)
message_id = self.backend.publish(arn, message)
return json.dumps({
"PublishResponse": {
@ -185,19 +195,116 @@ class SNSResponse(BaseResponse):
}
})
def create_platform_application(self):
name = self._get_param('Name')
platform = self._get_param('Platform')
attributes = self._get_attributes()
platform_application = self.backend.create_platform_application(self.region, name, platform, attributes)
return json.dumps({
"CreatePlatformApplicationResponse": {
"CreatePlatformApplicationResult": {
"PlatformApplicationArn": platform_application.arn,
},
"ResponseMetadata": {
"RequestId": "384ac68d-3775-11df-8963-01868b7c937b",
}
}
})
def get_platform_application_attributes(self):
arn = self._get_param('PlatformApplicationArn')
application = self.backend.get_application(arn)
return json.dumps({
"GetPlatformApplicationAttributesResponse": {
"GetPlatformApplicationAttributesResult": {
"Attributes": application.attributes,
},
"ResponseMetadata": {
"RequestId": "384ac68d-3775-11df-8963-01868b7c937f",
}
}
})
def set_platform_application_attributes(self):
arn = self._get_param('PlatformApplicationArn')
attributes = self._get_attributes()
self.backend.set_application_attributes(arn, attributes)
return json.dumps({
"SetPlatformApplicationAttributesResponse": {
"ResponseMetadata": {
"RequestId": "384ac68d-3775-12df-8963-01868b7c937f",
}
}
})
def list_platform_applications(self):
applications = self.backend.list_platform_applications()
return json.dumps({
"ListPlatformApplicationsResponse": {
"ListPlatformApplicationsResult": {
"PlatformApplications": [{
"PlatformApplicationArn": application.arn,
"attributes": application.attributes,
} for application in applications],
"NextToken": None
},
"ResponseMetadata": {
"RequestId": "384ac68d-3775-11df-8963-01868b7c937c",
}
}
})
def delete_platform_application(self):
platform_arn = self._get_param('PlatformApplicationArn')
self.backend.delete_platform_application(platform_arn)
return json.dumps({
"DeletePlatformApplicationResponse": {
"ResponseMetadata": {
"RequestId": "384ac68d-3775-11df-8963-01868b7c937e",
}
}
})
def create_platform_endpoint(self):
application_arn = self._get_param('PlatformApplicationArn')
application = self.backend.get_application(application_arn)
custom_user_data = self._get_param('CustomUserData')
token = self._get_param('Token')
attributes = self._get_attributes()
platform_endpoint = self.backend.create_platform_endpoint(
self.region, application, custom_user_data, token, attributes)
return json.dumps({
"CreatePlatformEndpointResponse": {
"CreatePlatformEndpointResult": {
"EndpointArn": platform_endpoint.arn,
},
"ResponseMetadata": {
"RequestId": "384ac68d-3779-11df-8963-01868b7c937b",
}
}
})
def list_endpoints_by_platform_application(self):
application_arn = self._get_param('PlatformApplicationArn')
endpoints = self.backend.list_endpoints_by_platform_application(application_arn)
return json.dumps({
"ListEndpointsByPlatformApplicationResponse": {
"ListEndpointsByPlatformApplicationResult": {
"Endpoints": [
{
"Attributes": {
"Token": "TOKEN",
"Enabled": "true",
"CustomUserData": ""
},
"EndpointArn": "FAKE_ARN_ENDPOINT"
}
"Attributes": endpoint.attributes,
"EndpointArn": endpoint.arn,
} for endpoint in endpoints
],
"NextToken": None
},
@ -206,3 +313,32 @@ class SNSResponse(BaseResponse):
}
}
})
def get_endpoint_attributes(self):
arn = self._get_param('EndpointArn')
endpoint = self.backend.get_endpoint(arn)
return json.dumps({
"GetEndpointAttributesResponse": {
"GetEndpointAttributesResult": {
"Attributes": endpoint.attributes,
},
"ResponseMetadata": {
"RequestId": "384ac68d-3775-11df-8963-01868b7c937f",
}
}
})
def set_endpoint_attributes(self):
arn = self._get_param('EndpointArn')
attributes = self._get_attributes()
self.backend.set_endpoint_attributes(arn, attributes)
return json.dumps({
"SetEndpointAttributesResponse": {
"ResponseMetadata": {
"RequestId": "384bc68d-3775-12df-8963-01868b7c937f",
}
}
})