Pinpoint - initial implementation (#4911)
This commit is contained in:
parent
a460adc940
commit
f6033cddeb
@ -3839,6 +3839,131 @@
|
||||
- [X] update_policy
|
||||
</details>
|
||||
|
||||
## pinpoint
|
||||
<details>
|
||||
<summary>10% implemented</summary>
|
||||
|
||||
- [X] create_app
|
||||
- [ ] create_campaign
|
||||
- [ ] create_email_template
|
||||
- [ ] create_export_job
|
||||
- [ ] create_import_job
|
||||
- [ ] create_in_app_template
|
||||
- [ ] create_journey
|
||||
- [ ] create_push_template
|
||||
- [ ] create_recommender_configuration
|
||||
- [ ] create_segment
|
||||
- [ ] create_sms_template
|
||||
- [ ] create_voice_template
|
||||
- [ ] delete_adm_channel
|
||||
- [ ] delete_apns_channel
|
||||
- [ ] delete_apns_sandbox_channel
|
||||
- [ ] delete_apns_voip_channel
|
||||
- [ ] delete_apns_voip_sandbox_channel
|
||||
- [X] delete_app
|
||||
- [ ] delete_baidu_channel
|
||||
- [ ] delete_campaign
|
||||
- [ ] delete_email_channel
|
||||
- [ ] delete_email_template
|
||||
- [ ] delete_endpoint
|
||||
- [X] delete_event_stream
|
||||
- [ ] delete_gcm_channel
|
||||
- [ ] delete_in_app_template
|
||||
- [ ] delete_journey
|
||||
- [ ] delete_push_template
|
||||
- [ ] delete_recommender_configuration
|
||||
- [ ] delete_segment
|
||||
- [ ] delete_sms_channel
|
||||
- [ ] delete_sms_template
|
||||
- [ ] delete_user_endpoints
|
||||
- [ ] delete_voice_channel
|
||||
- [ ] delete_voice_template
|
||||
- [ ] get_adm_channel
|
||||
- [ ] get_apns_channel
|
||||
- [ ] get_apns_sandbox_channel
|
||||
- [ ] get_apns_voip_channel
|
||||
- [ ] get_apns_voip_sandbox_channel
|
||||
- [X] get_app
|
||||
- [ ] get_application_date_range_kpi
|
||||
- [X] get_application_settings
|
||||
- [X] get_apps
|
||||
- [ ] get_baidu_channel
|
||||
- [ ] get_campaign
|
||||
- [ ] get_campaign_activities
|
||||
- [ ] get_campaign_date_range_kpi
|
||||
- [ ] get_campaign_version
|
||||
- [ ] get_campaign_versions
|
||||
- [ ] get_campaigns
|
||||
- [ ] get_channels
|
||||
- [ ] get_email_channel
|
||||
- [ ] get_email_template
|
||||
- [ ] get_endpoint
|
||||
- [X] get_event_stream
|
||||
- [ ] get_export_job
|
||||
- [ ] get_export_jobs
|
||||
- [ ] get_gcm_channel
|
||||
- [ ] get_import_job
|
||||
- [ ] get_import_jobs
|
||||
- [ ] get_in_app_messages
|
||||
- [ ] get_in_app_template
|
||||
- [ ] get_journey
|
||||
- [ ] get_journey_date_range_kpi
|
||||
- [ ] get_journey_execution_activity_metrics
|
||||
- [ ] get_journey_execution_metrics
|
||||
- [ ] get_push_template
|
||||
- [ ] get_recommender_configuration
|
||||
- [ ] get_recommender_configurations
|
||||
- [ ] get_segment
|
||||
- [ ] get_segment_export_jobs
|
||||
- [ ] get_segment_import_jobs
|
||||
- [ ] get_segment_version
|
||||
- [ ] get_segment_versions
|
||||
- [ ] get_segments
|
||||
- [ ] get_sms_channel
|
||||
- [ ] get_sms_template
|
||||
- [ ] get_user_endpoints
|
||||
- [ ] get_voice_channel
|
||||
- [ ] get_voice_template
|
||||
- [ ] list_journeys
|
||||
- [X] list_tags_for_resource
|
||||
- [ ] list_template_versions
|
||||
- [ ] list_templates
|
||||
- [ ] phone_number_validate
|
||||
- [X] put_event_stream
|
||||
- [ ] put_events
|
||||
- [ ] remove_attributes
|
||||
- [ ] send_messages
|
||||
- [ ] send_otp_message
|
||||
- [ ] send_users_messages
|
||||
- [X] tag_resource
|
||||
- [X] untag_resource
|
||||
- [ ] update_adm_channel
|
||||
- [ ] update_apns_channel
|
||||
- [ ] update_apns_sandbox_channel
|
||||
- [ ] update_apns_voip_channel
|
||||
- [ ] update_apns_voip_sandbox_channel
|
||||
- [X] update_application_settings
|
||||
- [ ] update_baidu_channel
|
||||
- [ ] update_campaign
|
||||
- [ ] update_email_channel
|
||||
- [ ] update_email_template
|
||||
- [ ] update_endpoint
|
||||
- [ ] update_endpoints_batch
|
||||
- [ ] update_gcm_channel
|
||||
- [ ] update_in_app_template
|
||||
- [ ] update_journey
|
||||
- [ ] update_journey_state
|
||||
- [ ] update_push_template
|
||||
- [ ] update_recommender_configuration
|
||||
- [ ] update_segment
|
||||
- [ ] update_sms_channel
|
||||
- [ ] update_sms_template
|
||||
- [ ] update_template_active_version
|
||||
- [ ] update_voice_channel
|
||||
- [ ] update_voice_template
|
||||
- [ ] verify_otp_message
|
||||
</details>
|
||||
|
||||
## polly
|
||||
<details>
|
||||
<summary>55% implemented</summary>
|
||||
@ -5569,7 +5694,6 @@
|
||||
- personalize-events
|
||||
- personalize-runtime
|
||||
- pi
|
||||
- pinpoint
|
||||
- pinpoint-email
|
||||
- pinpoint-sms-voice
|
||||
- pricing
|
||||
|
153
docs/docs/services/pinpoint.rst
Normal file
153
docs/docs/services/pinpoint.rst
Normal file
@ -0,0 +1,153 @@
|
||||
.. _implementedservice_pinpoint:
|
||||
|
||||
.. |start-h3| raw:: html
|
||||
|
||||
<h3>
|
||||
|
||||
.. |end-h3| raw:: html
|
||||
|
||||
</h3>
|
||||
|
||||
========
|
||||
pinpoint
|
||||
========
|
||||
|
||||
.. autoclass:: moto.pinpoint.models.PinpointBackend
|
||||
|
||||
|start-h3| Example usage |end-h3|
|
||||
|
||||
.. sourcecode:: python
|
||||
|
||||
@mock_pinpoint
|
||||
def test_pinpoint_behaviour:
|
||||
boto3.client("pinpoint")
|
||||
...
|
||||
|
||||
|
||||
|
||||
|start-h3| Implemented features for this service |end-h3|
|
||||
|
||||
- [X] create_app
|
||||
- [ ] create_campaign
|
||||
- [ ] create_email_template
|
||||
- [ ] create_export_job
|
||||
- [ ] create_import_job
|
||||
- [ ] create_in_app_template
|
||||
- [ ] create_journey
|
||||
- [ ] create_push_template
|
||||
- [ ] create_recommender_configuration
|
||||
- [ ] create_segment
|
||||
- [ ] create_sms_template
|
||||
- [ ] create_voice_template
|
||||
- [ ] delete_adm_channel
|
||||
- [ ] delete_apns_channel
|
||||
- [ ] delete_apns_sandbox_channel
|
||||
- [ ] delete_apns_voip_channel
|
||||
- [ ] delete_apns_voip_sandbox_channel
|
||||
- [X] delete_app
|
||||
- [ ] delete_baidu_channel
|
||||
- [ ] delete_campaign
|
||||
- [ ] delete_email_channel
|
||||
- [ ] delete_email_template
|
||||
- [ ] delete_endpoint
|
||||
- [X] delete_event_stream
|
||||
- [ ] delete_gcm_channel
|
||||
- [ ] delete_in_app_template
|
||||
- [ ] delete_journey
|
||||
- [ ] delete_push_template
|
||||
- [ ] delete_recommender_configuration
|
||||
- [ ] delete_segment
|
||||
- [ ] delete_sms_channel
|
||||
- [ ] delete_sms_template
|
||||
- [ ] delete_user_endpoints
|
||||
- [ ] delete_voice_channel
|
||||
- [ ] delete_voice_template
|
||||
- [ ] get_adm_channel
|
||||
- [ ] get_apns_channel
|
||||
- [ ] get_apns_sandbox_channel
|
||||
- [ ] get_apns_voip_channel
|
||||
- [ ] get_apns_voip_sandbox_channel
|
||||
- [X] get_app
|
||||
- [ ] get_application_date_range_kpi
|
||||
- [X] get_application_settings
|
||||
- [X] get_apps
|
||||
|
||||
Pagination is not yet implemented
|
||||
|
||||
|
||||
- [ ] get_baidu_channel
|
||||
- [ ] get_campaign
|
||||
- [ ] get_campaign_activities
|
||||
- [ ] get_campaign_date_range_kpi
|
||||
- [ ] get_campaign_version
|
||||
- [ ] get_campaign_versions
|
||||
- [ ] get_campaigns
|
||||
- [ ] get_channels
|
||||
- [ ] get_email_channel
|
||||
- [ ] get_email_template
|
||||
- [ ] get_endpoint
|
||||
- [X] get_event_stream
|
||||
- [ ] get_export_job
|
||||
- [ ] get_export_jobs
|
||||
- [ ] get_gcm_channel
|
||||
- [ ] get_import_job
|
||||
- [ ] get_import_jobs
|
||||
- [ ] get_in_app_messages
|
||||
- [ ] get_in_app_template
|
||||
- [ ] get_journey
|
||||
- [ ] get_journey_date_range_kpi
|
||||
- [ ] get_journey_execution_activity_metrics
|
||||
- [ ] get_journey_execution_metrics
|
||||
- [ ] get_push_template
|
||||
- [ ] get_recommender_configuration
|
||||
- [ ] get_recommender_configurations
|
||||
- [ ] get_segment
|
||||
- [ ] get_segment_export_jobs
|
||||
- [ ] get_segment_import_jobs
|
||||
- [ ] get_segment_version
|
||||
- [ ] get_segment_versions
|
||||
- [ ] get_segments
|
||||
- [ ] get_sms_channel
|
||||
- [ ] get_sms_template
|
||||
- [ ] get_user_endpoints
|
||||
- [ ] get_voice_channel
|
||||
- [ ] get_voice_template
|
||||
- [ ] list_journeys
|
||||
- [X] list_tags_for_resource
|
||||
- [ ] list_template_versions
|
||||
- [ ] list_templates
|
||||
- [ ] phone_number_validate
|
||||
- [X] put_event_stream
|
||||
- [ ] put_events
|
||||
- [ ] remove_attributes
|
||||
- [ ] send_messages
|
||||
- [ ] send_otp_message
|
||||
- [ ] send_users_messages
|
||||
- [X] tag_resource
|
||||
- [X] untag_resource
|
||||
- [ ] update_adm_channel
|
||||
- [ ] update_apns_channel
|
||||
- [ ] update_apns_sandbox_channel
|
||||
- [ ] update_apns_voip_channel
|
||||
- [ ] update_apns_voip_sandbox_channel
|
||||
- [X] update_application_settings
|
||||
- [ ] update_baidu_channel
|
||||
- [ ] update_campaign
|
||||
- [ ] update_email_channel
|
||||
- [ ] update_email_template
|
||||
- [ ] update_endpoint
|
||||
- [ ] update_endpoints_batch
|
||||
- [ ] update_gcm_channel
|
||||
- [ ] update_in_app_template
|
||||
- [ ] update_journey
|
||||
- [ ] update_journey_state
|
||||
- [ ] update_push_template
|
||||
- [ ] update_recommender_configuration
|
||||
- [ ] update_segment
|
||||
- [ ] update_sms_channel
|
||||
- [ ] update_sms_template
|
||||
- [ ] update_template_active_version
|
||||
- [ ] update_voice_channel
|
||||
- [ ] update_voice_template
|
||||
- [ ] verify_otp_message
|
||||
|
@ -107,6 +107,7 @@ mock_mediastoredata = lazy_load(
|
||||
mock_mq = lazy_load(".mq", "mock_mq", boto3_name="mq")
|
||||
mock_opsworks = lazy_load(".opsworks", "mock_opsworks")
|
||||
mock_organizations = lazy_load(".organizations", "mock_organizations")
|
||||
mock_pinpoint = lazy_load(".pinpoint", "mock_pinpoint")
|
||||
mock_polly = lazy_load(".polly", "mock_polly")
|
||||
mock_ram = lazy_load(".ram", "mock_ram")
|
||||
mock_rds = lazy_load(".rds", "mock_rds", warn_repurpose=True)
|
||||
|
@ -37,6 +37,9 @@ class Policy:
|
||||
" for the Lambda function or alias. Call the GetFunction or the GetAlias API to retrieve"
|
||||
" the latest RevisionId for your resource."
|
||||
)
|
||||
# Remove #LATEST from the Resource (Lambda ARN)
|
||||
if policy.statements[0].get("Resource", "").endswith("$LATEST"):
|
||||
policy.statements[0]["Resource"] = policy.statements[0]["Resource"][0:-8]
|
||||
self.statements.append(policy.statements[0])
|
||||
self.revision = str(uuid.uuid4())
|
||||
|
||||
|
@ -95,6 +95,7 @@ backend_url_patterns = [
|
||||
("mq", re.compile("https?://mq\\.(.+)\\.amazonaws\\.com")),
|
||||
("opsworks", re.compile("https?://opsworks\\.us-east-1\\.amazonaws.com")),
|
||||
("organizations", re.compile("https?://organizations\\.(.+)\\.amazonaws\\.com")),
|
||||
("pinpoint", re.compile("https?://pinpoint\\.(.+)\\.amazonaws\\.com")),
|
||||
("polly", re.compile("https?://polly\\.(.+)\\.amazonaws.com")),
|
||||
("ram", re.compile("https?://ram\\.(.+)\\.amazonaws.com")),
|
||||
("rds", re.compile("https?://rds\\.(.+)\\.amazonaws\\.com")),
|
||||
|
@ -33,6 +33,7 @@ SIGNING_ALIASES = {
|
||||
"eventbridge": "events",
|
||||
"execute-api": "iot",
|
||||
"iotdata": "data.iot",
|
||||
"mobiletargeting": "pinpoint",
|
||||
}
|
||||
|
||||
# Some services are only recognizable by the version
|
||||
|
5
moto/pinpoint/__init__.py
Normal file
5
moto/pinpoint/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
"""pinpoint module initialization; sets value for base decorator."""
|
||||
from .models import pinpoint_backends
|
||||
from ..core.models import base_decorator
|
||||
|
||||
mock_pinpoint = base_decorator(pinpoint_backends)
|
20
moto/pinpoint/exceptions.py
Normal file
20
moto/pinpoint/exceptions.py
Normal file
@ -0,0 +1,20 @@
|
||||
"""Exceptions raised by the pinpoint service."""
|
||||
from moto.core.exceptions import JsonRESTError
|
||||
|
||||
|
||||
class PinpointExceptions(JsonRESTError):
|
||||
pass
|
||||
|
||||
|
||||
class ApplicationNotFound(PinpointExceptions):
|
||||
code = 404
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("NotFoundException", "Application not found")
|
||||
|
||||
|
||||
class EventStreamNotFound(PinpointExceptions):
|
||||
code = 404
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("NotFoundException", "Resource not found")
|
155
moto/pinpoint/models.py
Normal file
155
moto/pinpoint/models.py
Normal file
@ -0,0 +1,155 @@
|
||||
from datetime import datetime
|
||||
from moto.core import ACCOUNT_ID, BaseBackend, BaseModel
|
||||
from moto.core.utils import BackendDict, unix_time
|
||||
from moto.utilities.tagging_service import TaggingService
|
||||
from uuid import uuid4
|
||||
|
||||
from .exceptions import ApplicationNotFound, EventStreamNotFound
|
||||
|
||||
|
||||
class App(BaseModel):
|
||||
def __init__(self, name):
|
||||
self.application_id = str(uuid4()).replace("-", "")
|
||||
self.arn = (
|
||||
f"arn:aws:mobiletargeting:us-east-1:{ACCOUNT_ID}:apps/{self.application_id}"
|
||||
)
|
||||
self.name = name
|
||||
self.created = unix_time()
|
||||
self.settings = AppSettings()
|
||||
self.event_stream = None
|
||||
|
||||
def get_settings(self):
|
||||
return self.settings
|
||||
|
||||
def update_settings(self, settings):
|
||||
self.settings.update(settings)
|
||||
return self.settings
|
||||
|
||||
def delete_event_stream(self):
|
||||
stream = self.event_stream
|
||||
self.event_stream = None
|
||||
return stream
|
||||
|
||||
def get_event_stream(self):
|
||||
if self.event_stream is None:
|
||||
raise EventStreamNotFound()
|
||||
return self.event_stream
|
||||
|
||||
def put_event_stream(self, stream_arn, role_arn):
|
||||
self.event_stream = EventStream(stream_arn, role_arn)
|
||||
return self.event_stream
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
"Arn": self.arn,
|
||||
"Id": self.application_id,
|
||||
"Name": self.name,
|
||||
"CreationDate": self.created,
|
||||
}
|
||||
|
||||
|
||||
class AppSettings(BaseModel):
|
||||
def __init__(self):
|
||||
self.settings = dict()
|
||||
self.last_modified = unix_time()
|
||||
|
||||
def update(self, settings):
|
||||
self.settings = settings
|
||||
self.last_modified = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%fZ")
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
"CampaignHook": self.settings.get("CampaignHook", {}),
|
||||
"CloudWatchMetricsEnabled": self.settings.get(
|
||||
"CloudWatchMetricsEnabled", False
|
||||
),
|
||||
"LastModifiedDate": self.last_modified,
|
||||
"Limits": self.settings.get("Limits", {}),
|
||||
"QuietTime": self.settings.get("QuietTime", {}),
|
||||
}
|
||||
|
||||
|
||||
class EventStream(BaseModel):
|
||||
def __init__(self, stream_arn, role_arn):
|
||||
self.stream_arn = stream_arn
|
||||
self.role_arn = role_arn
|
||||
self.last_modified = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%fZ")
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
"DestinationStreamArn": self.stream_arn,
|
||||
"RoleArn": self.role_arn,
|
||||
"LastModifiedDate": self.last_modified,
|
||||
}
|
||||
|
||||
|
||||
class PinpointBackend(BaseBackend):
|
||||
"""Implementation of Pinpoint APIs."""
|
||||
|
||||
def __init__(self, region_name=None):
|
||||
self.region_name = region_name
|
||||
self.apps = {}
|
||||
self.tagger = TaggingService()
|
||||
|
||||
def reset(self):
|
||||
"""Re-initialize all attributes for this instance."""
|
||||
region_name = self.region_name
|
||||
self.__dict__ = {}
|
||||
self.__init__(region_name)
|
||||
|
||||
def create_app(self, name, tags):
|
||||
app = App(name)
|
||||
self.apps[app.application_id] = app
|
||||
tags = self.tagger.convert_dict_to_tags_input(tags)
|
||||
self.tagger.tag_resource(app.arn, tags)
|
||||
return app
|
||||
|
||||
def delete_app(self, application_id):
|
||||
self.get_app(application_id)
|
||||
return self.apps.pop(application_id)
|
||||
|
||||
def get_app(self, application_id):
|
||||
if application_id not in self.apps:
|
||||
raise ApplicationNotFound()
|
||||
return self.apps[application_id]
|
||||
|
||||
def get_apps(self):
|
||||
"""
|
||||
Pagination is not yet implemented
|
||||
"""
|
||||
return self.apps.values()
|
||||
|
||||
def update_application_settings(self, application_id, settings):
|
||||
app = self.get_app(application_id)
|
||||
return app.update_settings(settings)
|
||||
|
||||
def get_application_settings(self, application_id):
|
||||
app = self.get_app(application_id)
|
||||
return app.get_settings()
|
||||
|
||||
def list_tags_for_resource(self, resource_arn):
|
||||
tags = self.tagger.get_tag_dict_for_resource(resource_arn)
|
||||
return {"tags": tags}
|
||||
|
||||
def tag_resource(self, resource_arn, tags):
|
||||
tags = TaggingService.convert_dict_to_tags_input(tags)
|
||||
self.tagger.tag_resource(resource_arn, tags)
|
||||
|
||||
def untag_resource(self, resource_arn, tag_keys):
|
||||
self.tagger.untag_resource_using_names(resource_arn, tag_keys)
|
||||
return
|
||||
|
||||
def put_event_stream(self, application_id, stream_arn, role_arn):
|
||||
app = self.get_app(application_id)
|
||||
return app.put_event_stream(stream_arn, role_arn)
|
||||
|
||||
def get_event_stream(self, application_id):
|
||||
app = self.get_app(application_id)
|
||||
return app.get_event_stream()
|
||||
|
||||
def delete_event_stream(self, application_id):
|
||||
app = self.get_app(application_id)
|
||||
return app.delete_event_stream()
|
||||
|
||||
|
||||
pinpoint_backends = BackendDict(PinpointBackend, "pinpoint")
|
161
moto/pinpoint/responses.py
Normal file
161
moto/pinpoint/responses.py
Normal file
@ -0,0 +1,161 @@
|
||||
"""Handles incoming pinpoint requests, invokes methods, returns responses."""
|
||||
import json
|
||||
|
||||
from functools import wraps
|
||||
from moto.core.responses import BaseResponse
|
||||
from urllib.parse import unquote
|
||||
from .exceptions import PinpointExceptions
|
||||
from .models import pinpoint_backends
|
||||
|
||||
|
||||
def error_handler(f):
|
||||
@wraps(f)
|
||||
def _wrapper(*args, **kwargs):
|
||||
try:
|
||||
return f(*args, **kwargs)
|
||||
except PinpointExceptions as e:
|
||||
return e.code, e.get_headers(), e.get_body()
|
||||
|
||||
return _wrapper
|
||||
|
||||
|
||||
class PinpointResponse(BaseResponse):
|
||||
"""Handler for Pinpoint requests and responses."""
|
||||
|
||||
@property
|
||||
def pinpoint_backend(self):
|
||||
"""Return backend instance specific for this region."""
|
||||
return pinpoint_backends[self.region]
|
||||
|
||||
@error_handler
|
||||
def app(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "DELETE":
|
||||
return self.delete_app()
|
||||
if request.method == "GET":
|
||||
return self.get_app()
|
||||
|
||||
def apps(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "GET":
|
||||
return self.get_apps()
|
||||
if request.method == "POST":
|
||||
return self.create_app()
|
||||
|
||||
def app_settings(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "GET":
|
||||
return self.get_application_settings()
|
||||
if request.method == "PUT":
|
||||
return self.update_application_settings()
|
||||
|
||||
@error_handler
|
||||
def eventstream(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "DELETE":
|
||||
return self.delete_event_stream()
|
||||
if request.method == "GET":
|
||||
return self.get_event_stream()
|
||||
if request.method == "POST":
|
||||
return self.put_event_stream()
|
||||
|
||||
def tags(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
if request.method == "DELETE":
|
||||
return self.untag_resource()
|
||||
if request.method == "GET":
|
||||
return self.list_tags_for_resource()
|
||||
if request.method == "POST":
|
||||
return self.tag_resource()
|
||||
|
||||
def create_app(self):
|
||||
params = json.loads(self.body)
|
||||
name = params.get("Name")
|
||||
tags = params.get("tags", {})
|
||||
app = self.pinpoint_backend.create_app(name=name, tags=tags)
|
||||
return 201, {}, json.dumps(app.to_json())
|
||||
|
||||
def delete_app(self):
|
||||
application_id = self.path.split("/")[-1]
|
||||
app = self.pinpoint_backend.delete_app(application_id=application_id,)
|
||||
return 200, {}, json.dumps(app.to_json())
|
||||
|
||||
def get_app(self):
|
||||
application_id = self.path.split("/")[-1]
|
||||
app = self.pinpoint_backend.get_app(application_id=application_id,)
|
||||
return 200, {}, json.dumps(app.to_json())
|
||||
|
||||
def get_apps(self):
|
||||
apps = self.pinpoint_backend.get_apps()
|
||||
resp = {"Item": [a.to_json() for a in apps]}
|
||||
return 200, {}, json.dumps(resp)
|
||||
|
||||
def update_application_settings(self):
|
||||
application_id = self.path.split("/")[-2]
|
||||
settings = json.loads(self.body)
|
||||
app_settings = self.pinpoint_backend.update_application_settings(
|
||||
application_id=application_id, settings=settings
|
||||
)
|
||||
app_settings = app_settings.to_json()
|
||||
app_settings["ApplicationId"] = application_id
|
||||
return 200, {}, json.dumps(app_settings)
|
||||
|
||||
def get_application_settings(self):
|
||||
application_id = self.path.split("/")[-2]
|
||||
app_settings = self.pinpoint_backend.get_application_settings(
|
||||
application_id=application_id,
|
||||
)
|
||||
app_settings = app_settings.to_json()
|
||||
app_settings["ApplicationId"] = application_id
|
||||
return 200, {}, json.dumps(app_settings)
|
||||
|
||||
def list_tags_for_resource(self):
|
||||
resource_arn = unquote(self.path).split("/tags/")[-1]
|
||||
tags = self.pinpoint_backend.list_tags_for_resource(resource_arn=resource_arn,)
|
||||
return 200, {}, json.dumps(tags)
|
||||
|
||||
def tag_resource(self):
|
||||
resource_arn = unquote(self.path).split("/tags/")[-1]
|
||||
tags = json.loads(self.body).get("tags", {})
|
||||
self.pinpoint_backend.tag_resource(
|
||||
resource_arn=resource_arn, tags=tags,
|
||||
)
|
||||
return 200, {}, "{}"
|
||||
|
||||
def untag_resource(self):
|
||||
resource_arn = unquote(self.path).split("/tags/")[-1]
|
||||
tag_keys = self.querystring.get("tagKeys")
|
||||
self.pinpoint_backend.untag_resource(
|
||||
resource_arn=resource_arn, tag_keys=tag_keys,
|
||||
)
|
||||
return 200, {}, "{}"
|
||||
|
||||
def put_event_stream(self):
|
||||
application_id = self.path.split("/")[-2]
|
||||
params = json.loads(self.body)
|
||||
stream_arn = params.get("DestinationStreamArn")
|
||||
role_arn = params.get("RoleArn")
|
||||
event_stream = self.pinpoint_backend.put_event_stream(
|
||||
application_id=application_id, stream_arn=stream_arn, role_arn=role_arn
|
||||
)
|
||||
resp = event_stream.to_json()
|
||||
resp["ApplicationId"] = application_id
|
||||
return 200, {}, json.dumps(resp)
|
||||
|
||||
def get_event_stream(self):
|
||||
application_id = self.path.split("/")[-2]
|
||||
event_stream = self.pinpoint_backend.get_event_stream(
|
||||
application_id=application_id,
|
||||
)
|
||||
resp = event_stream.to_json()
|
||||
resp["ApplicationId"] = application_id
|
||||
return 200, {}, json.dumps(resp)
|
||||
|
||||
def delete_event_stream(self):
|
||||
application_id = self.path.split("/")[-2]
|
||||
event_stream = self.pinpoint_backend.delete_event_stream(
|
||||
application_id=application_id,
|
||||
)
|
||||
resp = event_stream.to_json()
|
||||
resp["ApplicationId"] = application_id
|
||||
return 200, {}, json.dumps(resp)
|
18
moto/pinpoint/urls.py
Normal file
18
moto/pinpoint/urls.py
Normal file
@ -0,0 +1,18 @@
|
||||
"""pinpoint base URL and path."""
|
||||
from .responses import PinpointResponse
|
||||
|
||||
url_bases = [
|
||||
r"https?://pinpoint\.(.+)\.amazonaws\.com",
|
||||
]
|
||||
|
||||
|
||||
response = PinpointResponse()
|
||||
|
||||
|
||||
url_paths = {
|
||||
"{0}/v1/apps$": response.apps,
|
||||
"{0}/v1/apps/(?P<app_id>[^/]+)$": response.app,
|
||||
"{0}/v1/apps/(?P<app_id>[^/]+)/eventstream": response.eventstream,
|
||||
"{0}/v1/apps/(?P<app_id>[^/]+)/settings$": response.app_settings,
|
||||
"{0}/v1/tags/(?P<app_arn>.+)$": response.tags,
|
||||
}
|
@ -99,6 +99,8 @@ TestAccAWSKmsSecretDataSource
|
||||
TestAccAWSMq
|
||||
TestAccAWSNatGateway
|
||||
TestAccAWSPartition
|
||||
TestAccAWSPinpointApp
|
||||
TestAccAWSPinpointEventStream
|
||||
TestAccAWSProvider
|
||||
TestAccAWSRedshiftServiceAccount
|
||||
TestAccAWSRolePolicyAttachment
|
||||
|
@ -26,7 +26,7 @@ def test_policy():
|
||||
"FunctionName": "function_name",
|
||||
"Principal": {"Service": "events.amazonaws.com"},
|
||||
"Effect": "Allow",
|
||||
"Resource": "arn:$LATEST",
|
||||
"Resource": "arn",
|
||||
"Sid": "statement0",
|
||||
"Condition": {
|
||||
"ArnLike": {
|
||||
@ -40,7 +40,7 @@ def test_policy():
|
||||
expected.should.be.equal(policy.statements[0])
|
||||
|
||||
sid = statement.get("StatementId", None)
|
||||
if sid == None:
|
||||
if sid is None:
|
||||
raise "TestCase.statement does not contain StatementId"
|
||||
|
||||
policy.del_statement(sid)
|
||||
|
0
tests/test_pinpoint/__init__.py
Normal file
0
tests/test_pinpoint/__init__.py
Normal file
129
tests/test_pinpoint/test_pinpoint.py
Normal file
129
tests/test_pinpoint/test_pinpoint.py
Normal file
@ -0,0 +1,129 @@
|
||||
"""Unit tests for pinpoint-supported APIs."""
|
||||
import boto3
|
||||
import pytest
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from moto import mock_pinpoint
|
||||
|
||||
# See our Development Tips on writing tests for hints on how to write good tests:
|
||||
# http://docs.getmoto.org/en/latest/docs/contributing/development_tips/tests.html
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_create_app():
|
||||
client = boto3.client("pinpoint", region_name="us-east-1")
|
||||
resp = client.create_app(CreateApplicationRequest={"Name": "myfirstapp"})
|
||||
|
||||
resp.should.have.key("ApplicationResponse")
|
||||
resp["ApplicationResponse"].should.have.key("Arn")
|
||||
resp["ApplicationResponse"].should.have.key("Id")
|
||||
resp["ApplicationResponse"].should.have.key("Name").equals("myfirstapp")
|
||||
resp["ApplicationResponse"].should.have.key("CreationDate")
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_delete_app():
|
||||
client = boto3.client("pinpoint", region_name="ap-southeast-1")
|
||||
creation = client.create_app(CreateApplicationRequest={"Name": "myfirstapp"})[
|
||||
"ApplicationResponse"
|
||||
]
|
||||
app_id = creation["Id"]
|
||||
|
||||
deletion = client.delete_app(ApplicationId=app_id)["ApplicationResponse"]
|
||||
deletion.should.equal(creation)
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
client.get_app(ApplicationId=app_id)
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("NotFoundException")
|
||||
err["Message"].should.equal("Application not found")
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_get_app():
|
||||
client = boto3.client("pinpoint", region_name="eu-west-1")
|
||||
resp = client.create_app(CreateApplicationRequest={"Name": "myfirstapp"})
|
||||
app_id = resp["ApplicationResponse"]["Id"]
|
||||
|
||||
resp = client.get_app(ApplicationId=app_id)
|
||||
|
||||
resp.should.have.key("ApplicationResponse")
|
||||
resp["ApplicationResponse"].should.have.key("Arn")
|
||||
resp["ApplicationResponse"].should.have.key("Id")
|
||||
resp["ApplicationResponse"].should.have.key("Name").equals("myfirstapp")
|
||||
resp["ApplicationResponse"].should.have.key("CreationDate")
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_get_apps_initial():
|
||||
client = boto3.client("pinpoint", region_name="us-east-1")
|
||||
resp = client.get_apps()
|
||||
|
||||
resp.should.have.key("ApplicationsResponse")
|
||||
resp["ApplicationsResponse"].should.equal({"Item": []})
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_get_apps():
|
||||
client = boto3.client("pinpoint", region_name="us-east-1")
|
||||
resp = client.create_app(CreateApplicationRequest={"Name": "myfirstapp"})
|
||||
app_id = resp["ApplicationResponse"]["Id"]
|
||||
|
||||
resp = client.get_apps()
|
||||
|
||||
resp.should.have.key("ApplicationsResponse").should.have.key("Item").length_of(1)
|
||||
resp["ApplicationsResponse"]["Item"][0].should.have.key("Arn")
|
||||
resp["ApplicationsResponse"]["Item"][0].should.have.key("Id").equals(app_id)
|
||||
resp["ApplicationsResponse"]["Item"][0].should.have.key("Name").equals("myfirstapp")
|
||||
resp["ApplicationsResponse"]["Item"][0].should.have.key("CreationDate")
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_update_application_settings():
|
||||
client = boto3.client("pinpoint", region_name="eu-west-1")
|
||||
resp = client.create_app(CreateApplicationRequest={"Name": "myfirstapp"})
|
||||
app_id = resp["ApplicationResponse"]["Id"]
|
||||
|
||||
resp = client.update_application_settings(
|
||||
ApplicationId=app_id,
|
||||
WriteApplicationSettingsRequest={
|
||||
"CampaignHook": {"LambdaFunctionName": "lfn"},
|
||||
"CloudWatchMetricsEnabled": True,
|
||||
"EventTaggingEnabled": True,
|
||||
"Limits": {"Daily": 42},
|
||||
},
|
||||
)
|
||||
|
||||
resp.should.have.key("ApplicationSettingsResource")
|
||||
app_settings = resp["ApplicationSettingsResource"]
|
||||
app_settings.should.have.key("ApplicationId").equals(app_id)
|
||||
app_settings.should.have.key("CampaignHook").equals({"LambdaFunctionName": "lfn"})
|
||||
app_settings.should.have.key("Limits").equals({"Daily": 42})
|
||||
app_settings.should.have.key("LastModifiedDate")
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_get_application_settings():
|
||||
client = boto3.client("pinpoint", region_name="ap-southeast-1")
|
||||
resp = client.create_app(CreateApplicationRequest={"Name": "myfirstapp"})
|
||||
app_id = resp["ApplicationResponse"]["Id"]
|
||||
|
||||
client.update_application_settings(
|
||||
ApplicationId=app_id,
|
||||
WriteApplicationSettingsRequest={
|
||||
"CampaignHook": {"LambdaFunctionName": "lfn"},
|
||||
"CloudWatchMetricsEnabled": True,
|
||||
"EventTaggingEnabled": True,
|
||||
"Limits": {"Daily": 42},
|
||||
},
|
||||
)
|
||||
|
||||
resp = client.get_application_settings(ApplicationId=app_id)
|
||||
|
||||
resp.should.have.key("ApplicationSettingsResource")
|
||||
app_settings = resp["ApplicationSettingsResource"]
|
||||
app_settings.should.have.key("ApplicationId").equals(app_id)
|
||||
app_settings.should.have.key("CampaignHook").equals({"LambdaFunctionName": "lfn"})
|
||||
app_settings.should.have.key("Limits").equals({"Daily": 42})
|
||||
app_settings.should.have.key("LastModifiedDate")
|
73
tests/test_pinpoint/test_pinpoint_application_tags.py
Normal file
73
tests/test_pinpoint/test_pinpoint_application_tags.py
Normal file
@ -0,0 +1,73 @@
|
||||
"""Unit tests for pinpoint-supported APIs."""
|
||||
import boto3
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
|
||||
from moto import mock_pinpoint
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_list_tags_for_resource_empty():
|
||||
client = boto3.client("pinpoint", region_name="ap-southeast-1")
|
||||
resp = client.create_app(CreateApplicationRequest={"Name": "myfirstapp"})
|
||||
app_arn = resp["ApplicationResponse"]["Arn"]
|
||||
|
||||
resp = client.list_tags_for_resource(ResourceArn=app_arn)
|
||||
resp.should.have.key("TagsModel").equals({"tags": {}})
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_list_tags_for_resource():
|
||||
client = boto3.client("pinpoint", region_name="ap-southeast-1")
|
||||
resp = client.create_app(
|
||||
CreateApplicationRequest={
|
||||
"Name": "myfirstapp",
|
||||
"tags": {"key1": "value1", "key2": "value2"},
|
||||
}
|
||||
)
|
||||
app_arn = resp["ApplicationResponse"]["Arn"]
|
||||
|
||||
resp = client.list_tags_for_resource(ResourceArn=app_arn)
|
||||
resp.should.have.key("TagsModel")
|
||||
resp["TagsModel"].should.have.key("tags").equals(
|
||||
{"key1": "value1", "key2": "value2"}
|
||||
)
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_tag_resource():
|
||||
client = boto3.client("pinpoint", region_name="us-east-1")
|
||||
resp = client.create_app(CreateApplicationRequest={"Name": "myfirstapp"})
|
||||
app_arn = resp["ApplicationResponse"]["Arn"]
|
||||
|
||||
client.tag_resource(
|
||||
ResourceArn=app_arn, TagsModel={"tags": {"key1": "value1", "key2": "value2"}}
|
||||
)
|
||||
|
||||
resp = client.list_tags_for_resource(ResourceArn=app_arn)
|
||||
resp.should.have.key("TagsModel")
|
||||
resp["TagsModel"].should.have.key("tags").equals(
|
||||
{"key1": "value1", "key2": "value2"}
|
||||
)
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_untag_resource():
|
||||
client = boto3.client("pinpoint", region_name="eu-west-1")
|
||||
resp = client.create_app(
|
||||
CreateApplicationRequest={"Name": "myfirstapp", "tags": {"key1": "value1"}}
|
||||
)
|
||||
app_arn = resp["ApplicationResponse"]["Arn"]
|
||||
|
||||
client.tag_resource(
|
||||
ResourceArn=app_arn, TagsModel={"tags": {"key2": "value2", "key3": "value3"}}
|
||||
)
|
||||
|
||||
client.untag_resource(
|
||||
ResourceArn=app_arn, TagKeys=["key2"],
|
||||
)
|
||||
|
||||
resp = client.list_tags_for_resource(ResourceArn=app_arn)
|
||||
resp.should.have.key("TagsModel")
|
||||
resp["TagsModel"].should.have.key("tags").equals(
|
||||
{"key1": "value1", "key3": "value3"}
|
||||
)
|
74
tests/test_pinpoint/test_pinpoint_event_stream.py
Normal file
74
tests/test_pinpoint/test_pinpoint_event_stream.py
Normal file
@ -0,0 +1,74 @@
|
||||
"""Unit tests for pinpoint-supported APIs."""
|
||||
import boto3
|
||||
import pytest
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from moto import mock_pinpoint
|
||||
|
||||
# See our Development Tips on writing tests for hints on how to write good tests:
|
||||
# http://docs.getmoto.org/en/latest/docs/contributing/development_tips/tests.html
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_put_event_stream():
|
||||
client = boto3.client("pinpoint", region_name="eu-west-1")
|
||||
resp = client.create_app(CreateApplicationRequest={"Name": "myfirstapp"})
|
||||
app_id = resp["ApplicationResponse"]["Id"]
|
||||
|
||||
resp = client.put_event_stream(
|
||||
ApplicationId=app_id,
|
||||
WriteEventStream={"DestinationStreamArn": "kinesis:arn", "RoleArn": "iam:arn"},
|
||||
)
|
||||
|
||||
resp.should.have.key("EventStream")
|
||||
resp["EventStream"].should.have.key("ApplicationId").equals(app_id)
|
||||
resp["EventStream"].should.have.key("DestinationStreamArn").equals("kinesis:arn")
|
||||
resp["EventStream"].should.have.key("LastModifiedDate")
|
||||
resp["EventStream"].should.have.key("RoleArn").equals("iam:arn")
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_get_event_stream():
|
||||
client = boto3.client("pinpoint", region_name="us-east-1")
|
||||
resp = client.create_app(CreateApplicationRequest={"Name": "myfirstapp"})
|
||||
app_id = resp["ApplicationResponse"]["Id"]
|
||||
|
||||
client.put_event_stream(
|
||||
ApplicationId=app_id,
|
||||
WriteEventStream={"DestinationStreamArn": "kinesis:arn", "RoleArn": "iam:arn"},
|
||||
)
|
||||
|
||||
resp = client.get_event_stream(ApplicationId=app_id)
|
||||
|
||||
resp.should.have.key("EventStream")
|
||||
resp["EventStream"].should.have.key("ApplicationId").equals(app_id)
|
||||
resp["EventStream"].should.have.key("DestinationStreamArn").equals("kinesis:arn")
|
||||
resp["EventStream"].should.have.key("LastModifiedDate")
|
||||
resp["EventStream"].should.have.key("RoleArn").equals("iam:arn")
|
||||
|
||||
|
||||
@mock_pinpoint
|
||||
def test_delete_event_stream():
|
||||
client = boto3.client("pinpoint", region_name="us-east-1")
|
||||
resp = client.create_app(CreateApplicationRequest={"Name": "myfirstapp"})
|
||||
app_id = resp["ApplicationResponse"]["Id"]
|
||||
|
||||
client.put_event_stream(
|
||||
ApplicationId=app_id,
|
||||
WriteEventStream={"DestinationStreamArn": "kinesis:arn", "RoleArn": "iam:arn"},
|
||||
)
|
||||
|
||||
resp = client.delete_event_stream(ApplicationId=app_id)
|
||||
|
||||
resp.should.have.key("EventStream")
|
||||
resp["EventStream"].should.have.key("ApplicationId").equals(app_id)
|
||||
resp["EventStream"].should.have.key("DestinationStreamArn").equals("kinesis:arn")
|
||||
resp["EventStream"].should.have.key("LastModifiedDate")
|
||||
resp["EventStream"].should.have.key("RoleArn").equals("iam:arn")
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
client.get_event_stream(ApplicationId=app_id)
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("NotFoundException")
|
||||
err["Message"].should.equal("Resource not found")
|
Loading…
Reference in New Issue
Block a user