Pinpoint - initial implementation (#4911)

This commit is contained in:
Bert Blommers 2022-03-07 20:37:50 -01:00 committed by GitHub
parent a460adc940
commit f6033cddeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 923 additions and 3 deletions

View File

@ -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

View 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

View File

@ -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)

View File

@ -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())

View File

@ -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")),

View File

@ -33,6 +33,7 @@ SIGNING_ALIASES = {
"eventbridge": "events",
"execute-api": "iot",
"iotdata": "data.iot",
"mobiletargeting": "pinpoint",
}
# Some services are only recognizable by the version

View 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)

View 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
View 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
View 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
View 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,
}

View File

@ -99,6 +99,8 @@ TestAccAWSKmsSecretDataSource
TestAccAWSMq
TestAccAWSNatGateway
TestAccAWSPartition
TestAccAWSPinpointApp
TestAccAWSPinpointEventStream
TestAccAWSProvider
TestAccAWSRedshiftServiceAccount
TestAccAWSRolePolicyAttachment

View File

@ -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)

View File

View 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")

View 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"}
)

View 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")