Implementation of core AWS Mediapackage endpoints (#3762)

* write boilerplate code

* generate boilerplate code with scaffold script

* create mediapackage channel

* remove duplicate mediapackage reference

* remove Channel key from mediapackage response

* describe_channel endpoint added

* create_origin_endpoint-added

* keys changed to camel case to fix issue

* minor changes to clean up

* minor clean up again

* implement & test delete_channel

* delete origin endpoint created; WIP-tests failing

* fix delete_origin_endpoint issue

* refactor function call

* delete origin endpoint completed; test_server tests added

* implement and test describe_origin_endpoint

* update origin endpoint added

* remove print statements

* implement test_list_origin_endpoint_succeeds

* create test name changed

* create test name changed

* changes after flake8 and black run

* url assertion added to decribe origin endpoint test

* region dependent url enabled

Co-authored-by: Anya <anya.champaneria@capablue.com>
Co-authored-by: AnyaChamp <71766808+AnyaChamp@users.noreply.github.com>
This commit is contained in:
Franck Ndame 2021-03-12 14:56:25 +00:00 committed by GitHub
parent 4da11da2bf
commit 808f3c748f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 572 additions and 1 deletions

View File

@ -122,6 +122,7 @@ mock_kinesisvideoarchivedmedia = lazy_load(
mock_medialive = lazy_load(".medialive", "mock_medialive")
mock_support = lazy_load(".support", "mock_support")
mock_mediaconnect = lazy_load(".mediaconnect", "mock_mediaconnect")
mock_mediapackage = lazy_load(".mediapackage", "mock_mediapackage")
# import logging
# logging.getLogger('boto').setLevel(logging.CRITICAL)

View File

@ -79,6 +79,7 @@ BACKENDS = {
"forecast": ("forecast", "forecast_backends"),
"support": ("support", "support_backends"),
"mediaconnect": ("mediaconnect", "mediaconnect_backends"),
"mediapackage": ("mediapackage", "mediapackage_backends"),
}

View File

@ -0,0 +1,6 @@
from __future__ import unicode_literals
from .models import mediapackage_backends
from ..core.models import base_decorator
mediapackage_backend = mediapackage_backends["us-east-1"]
mock_mediapackage = base_decorator(mediapackage_backends)

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

202
moto/mediapackage/models.py Normal file
View File

@ -0,0 +1,202 @@
from __future__ import unicode_literals
from boto3 import Session
from moto.core import BaseBackend, BaseModel
from collections import OrderedDict
class Channel(BaseModel):
def __init__(self, *args, **kwargs):
self.arn = kwargs.get("arn")
self.channel_id = kwargs.get("channel_id")
self.description = kwargs.get("description")
self.tags = kwargs.get("tags")
def to_dict(self, exclude=None):
data = {
"arn": self.arn,
"id": self.channel_id,
"description": self.description,
"tags": self.tags,
}
if exclude:
for key in exclude:
del data[key]
return data
class OriginEndpoint(BaseModel):
def __init__(self, *args, **kwargs):
self.arn = kwargs.get("arn")
self.authorization = kwargs.get("authorization")
self.channel_id = kwargs.get("channel_id")
self.cmaf_package = kwargs.get("cmaf_package")
self.dash_package = kwargs.get("dash_package")
self.description = kwargs.get("description")
self.hls_package = kwargs.get("hls_package")
self.id = kwargs.get("id")
self.manifest_name = kwargs.get("manifest_name")
self.mss_package = kwargs.get("mss_package")
self.origination = kwargs.get("origination")
self.startover_window_seconds = kwargs.get("startover_window_seconds")
self.tags = kwargs.get("tags")
self.time_delay_seconds = kwargs.get("time_delay_seconds")
self.url = kwargs.get("url")
self.whitelist = kwargs.get("whitelist")
def to_dict(self):
data = {
"arn": self.arn,
"authorization": self.authorization,
"channelId": self.channel_id,
"cmafPackage": self.cmaf_package,
"dashPackage": self.dash_package,
"description": self.description,
"hlsPackage": self.hls_package,
"id": self.id,
"manifestName": self.manifest_name,
"mssPackage": self.mss_package,
"origination": self.origination,
"startoverWindowSeconds": self.startover_window_seconds,
"tags": self.tags,
"timeDelaySeconds": self.time_delay_seconds,
"url": self.url,
"whitelist": self.whitelist,
}
return data
class MediaPackageBackend(BaseBackend):
def __init__(self, region_name=None):
super(MediaPackageBackend, self).__init__()
self.region_name = region_name
def reset(self):
region_name = self.region_name
self.__dict__ = {}
self.__init__(region_name)
self._channels = OrderedDict()
self._origin_endpoints = OrderedDict()
def create_channel(self, description, id, tags):
arn = "arn:aws:mediapackage:channel:{}".format(id)
channel = Channel(
arn=arn,
description=description,
egress_access_logs={},
hls_ingest={},
channel_id=id,
ingress_access_logs={},
tags=tags,
)
self._channels[id] = channel
return channel
def list_channels(self):
channels = list(self._channels.values())
response_channels = [c.to_dict() for c in channels]
return response_channels
def describe_channel(self, id):
channel = self._channels[id]
return channel.to_dict()
def delete_channel(self, id):
channel = self._channels[id]
del self._channels[id]
return channel.to_dict()
def create_origin_endpoint(
self,
authorization,
channel_id,
cmaf_package,
dash_package,
description,
hls_package,
id,
manifest_name,
mss_package,
origination,
startover_window_seconds,
tags,
time_delay_seconds,
whitelist,
):
arn = "arn:aws:mediapackage:origin_endpoint:{}".format(id)
url = "https://origin-endpoint.mediapackage.{}.amazonaws.com/{}".format(
self.region_name, id
)
origin_endpoint = OriginEndpoint(
arn=arn,
authorization=authorization,
channel_id=channel_id,
cmaf_package=cmaf_package,
dash_package=dash_package,
description=description,
hls_package=hls_package,
id=id,
manifest_name=manifest_name,
mss_package=mss_package,
origination=origination,
startover_window_seconds=startover_window_seconds,
tags=tags,
time_delay_seconds=time_delay_seconds,
url=url,
whitelist=whitelist,
)
self._origin_endpoints[id] = origin_endpoint
return origin_endpoint
def describe_origin_endpoint(self, id):
origin_endpoint = self._origin_endpoints[id]
return origin_endpoint.to_dict()
def list_origin_endpoints(self):
origin_endpoints = list(self._origin_endpoints.values())
response_origin_endpoints = [o.to_dict() for o in origin_endpoints]
return response_origin_endpoints
def delete_origin_endpoint(self, id):
origin_endpoint = self._origin_endpoints[id]
del self._origin_endpoints[id]
return origin_endpoint.to_dict()
def update_origin_endpoint(
self,
authorization,
cmaf_package,
dash_package,
description,
hls_package,
id,
manifest_name,
mss_package,
origination,
startover_window_seconds,
time_delay_seconds,
whitelist,
):
origin_endpoint = self._origin_endpoints[id]
origin_endpoint.authorization = authorization
origin_endpoint.cmaf_package = cmaf_package
origin_endpoint.dash_package = dash_package
origin_endpoint.description = description
origin_endpoint.hls_package = hls_package
origin_endpoint.manifest_name = manifest_name
origin_endpoint.mss_package = mss_package
origin_endpoint.origination = origination
origin_endpoint.startover_window_seconds = startover_window_seconds
origin_endpoint.time_delay_seconds = time_delay_seconds
origin_endpoint.whitelist = whitelist
return origin_endpoint
mediapackage_backends = {}
for region in Session().get_available_regions("mediapackage"):
mediapackage_backends[region] = MediaPackageBackend(region)
for region in Session().get_available_regions(
"mediapackage", partition_name="aws-us-gov"
):
mediapackage_backends[region] = MediaPackageBackend(region)
for region in Session().get_available_regions("mediapackage", partition_name="aws-cn"):
mediapackage_backends[region] = MediaPackageBackend(region)

View File

@ -0,0 +1,107 @@
from __future__ import unicode_literals
from moto.core.responses import BaseResponse
from .models import mediapackage_backends
import json
class MediaPackageResponse(BaseResponse):
SERVICE_NAME = "mediapackage"
@property
def mediapackage_backend(self):
return mediapackage_backends[self.region]
def create_channel(self):
description = self._get_param("description")
id = self._get_param("id")
tags = self._get_param("tags")
channel = self.mediapackage_backend.create_channel(
description=description, id=id, tags=tags,
)
return json.dumps(channel.to_dict())
def list_channels(self):
channels = self.mediapackage_backend.list_channels()
return json.dumps(dict(channels=channels))
def describe_channel(self):
id = self._get_param("id")
return json.dumps(self.mediapackage_backend.describe_channel(id=id))
def delete_channel(self):
channel_id = self._get_param("id")
return json.dumps(self.mediapackage_backend.delete_channel(id=channel_id))
def create_origin_endpoint(self):
authorization = self._get_param("authorization")
channel_id = self._get_param("channelId")
cmaf_package = self._get_param("cmafPackage")
dash_package = self._get_param("dashPackage")
description = self._get_param("description")
hls_package = self._get_param("hlsPackage")
id = self._get_param("id")
manifest_name = self._get_param("manifestName")
mss_package = self._get_param("mssPackage")
origination = self._get_param("origination")
startover_window_seconds = self._get_int_param("startoverWindowSeconds")
tags = self._get_param("tags")
time_delay_seconds = self._get_int_param("timeDelaySeconds.member")
whitelist = self._get_list_prefix("whitelist.member")
origin_endpoint = self.mediapackage_backend.create_origin_endpoint(
authorization=authorization,
channel_id=channel_id,
cmaf_package=cmaf_package,
dash_package=dash_package,
description=description,
hls_package=hls_package,
id=id,
manifest_name=manifest_name,
mss_package=mss_package,
origination=origination,
startover_window_seconds=startover_window_seconds,
tags=tags,
time_delay_seconds=time_delay_seconds,
whitelist=whitelist,
)
return json.dumps(origin_endpoint.to_dict())
def list_origin_endpoints(self):
origin_endpoints = self.mediapackage_backend.list_origin_endpoints()
return json.dumps(dict(originEndpoints=origin_endpoints))
def describe_origin_endpoint(self):
id = self._get_param("id")
return json.dumps(self.mediapackage_backend.describe_origin_endpoint(id=id))
def delete_origin_endpoint(self):
id = self._get_param("id")
return json.dumps(self.mediapackage_backend.delete_origin_endpoint(id=id))
def update_origin_endpoint(self):
authorization = self._get_param("authorization")
cmaf_package = self._get_param("cmafPackage")
dash_package = self._get_param("dashPackage")
description = self._get_param("description")
hls_package = self._get_param("hlsPackage")
id = self._get_param("id")
manifest_name = self._get_param("manifestName")
mss_package = self._get_param("mssPackage")
origination = self._get_param("origination")
startover_window_seconds = self._get_int_param("startoverWindowSeconds")
time_delay_seconds = self._get_int_param("timeDelaySeconds")
whitelist = self._get_list_prefix("whitelist.member")
origin_endpoint = self.mediapackage_backend.update_origin_endpoint(
authorization=authorization,
cmaf_package=cmaf_package,
dash_package=dash_package,
description=description,
hls_package=hls_package,
id=id,
manifest_name=manifest_name,
mss_package=mss_package,
origination=origination,
startover_window_seconds=startover_window_seconds,
time_delay_seconds=time_delay_seconds,
whitelist=whitelist,
)
return json.dumps(origin_endpoint.to_dict())

17
moto/mediapackage/urls.py Normal file
View File

@ -0,0 +1,17 @@
from __future__ import unicode_literals
from .responses import MediaPackageResponse
url_bases = [
"https?://mediapackage.(.+).amazonaws.com",
]
response = MediaPackageResponse()
url_paths = {
"{0}/channels": response.dispatch,
"{0}/channels/(?P<channelid>[^/.]+)": response.dispatch,
"{0}/origin_endpoints": response.dispatch,
"{0}/origin_endpoints/(?P<id>[^/.]+)": response.dispatch,
}

View File

@ -16,7 +16,6 @@ def test_medialive_list_channels():
test_client = backend.test_client()
res = test_client.get("/prod/channels")
result = res.data.decode("utf-8")
result.should.contain('"channels": []')

View File

@ -0,0 +1,207 @@
from __future__ import unicode_literals
import boto3
import sure # noqa
from moto import mock_mediapackage
region = "eu-west-1"
def _create_channel_config(**kwargs):
id = kwargs.get("id", "channel-id")
description = kwargs.get("description", "Awesome channel!")
tags = kwargs.get("tags", {"Customer": "moto"})
channel_config = dict(Description=description, Id=id, Tags=tags,)
return channel_config
def _create_origin_endpoint_config(**kwargs):
authorization = kwargs.get(
"authorization",
{"CdnIdentifierSecret": "cdn-id-secret", "SecretsRoleArn": "secrets-arn"},
)
channel_id = kwargs.get("channel_id", "channel-id")
cmaf_package = kwargs.get("cmafpackage", {"HlsManifests": []})
dash_package = kwargs.get("dash_package", {"AdTriggers": []})
description = kwargs.get("description", "channel-description")
hls_package = kwargs.get("hls_package", {"AdMarkers": "NONE"})
id = kwargs.get("id", "origin-endpoint-id")
manifest_name = kwargs.get("manifest_name", "manifest-name")
mss_package = kwargs.get("mss_package", {"ManifestWindowSeconds": 1})
origination = kwargs.get("origination", "ALLOW")
startover_window_seconds = kwargs.get("startover_window_seconds", 1)
tags = kwargs.get("tags", {"Customer": "moto"})
time_delay_seconds = kwargs.get("time_delay_seconds", 1)
whitelist = kwargs.get("whitelist", ["whitelist"])
origin_endpoint_config = dict(
Authorization=authorization,
ChannelId=channel_id,
CmafPackage=cmaf_package,
DashPackage=dash_package,
Description=description,
HlsPackage=hls_package,
Id=id,
ManifestName=manifest_name,
MssPackage=mss_package,
Origination=origination,
StartoverWindowSeconds=startover_window_seconds,
Tags=tags,
TimeDelaySeconds=time_delay_seconds,
Whitelist=whitelist,
)
return origin_endpoint_config
@mock_mediapackage
def test_create_channel_succeeds():
client = boto3.client("mediapackage", region_name=region)
channel_config = _create_channel_config()
response = client.create_channel(**channel_config)
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
response["Arn"].should.equal(
"arn:aws:mediapackage:channel:{}".format(response["Id"])
)
response["Description"].should.equal("Awesome channel!")
response["Id"].should.equal("channel-id")
response["Tags"]["Customer"].should.equal("moto")
@mock_mediapackage
def test_describe_channel_succeeds():
client = boto3.client("mediapackage", region_name=region)
channel_config = _create_channel_config()
create_response = client.create_channel(**channel_config)
describe_response = client.describe_channel(Id=create_response["Id"])
describe_response["Arn"].should.equal(
"arn:aws:mediapackage:channel:{}".format(describe_response["Id"])
)
describe_response["Description"].should.equal(channel_config["Description"])
describe_response["Tags"]["Customer"].should.equal("moto")
@mock_mediapackage
def test_delete_channel_successfully_deletes():
client = boto3.client("mediapackage", region_name=region)
channel_config = _create_channel_config()
create_response = client.create_channel(**channel_config)
# Before deletion
list_response = client.list_channels()
channels_list = list_response["Channels"]
client.delete_channel(Id=create_response["Id"])
# After deletion
post_deletion_list_response = client.list_channels()
post_deletion_channels_list = post_deletion_list_response["Channels"]
len(post_deletion_channels_list).should.equal(len(channels_list) - 1)
@mock_mediapackage
def test_list_channels_succeds():
channels_list = []
client = boto3.client("mediapackage", region_name=region)
channel_config = _create_channel_config()
len(channels_list).should.equal(0)
client.create_channel(**channel_config)
list_response = client.list_channels()
channels_list = list_response["Channels"]
len(channels_list).should.equal(1)
first_channel = channels_list[0]
first_channel["Arn"].should.equal(
"arn:aws:mediapackage:channel:{}".format(first_channel["Id"])
)
first_channel["Description"].should.equal(channel_config["Description"])
first_channel["Tags"]["Customer"].should.equal("moto")
@mock_mediapackage
def test_create_origin_endpoint_succeeds():
client = boto3.client("mediapackage", region_name=region)
origin_endpoint_config = _create_origin_endpoint_config()
response = client.create_origin_endpoint(**origin_endpoint_config)
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
response["Arn"].should.equal(
"arn:aws:mediapackage:origin_endpoint:{}".format(response["Id"])
)
response["ChannelId"].should.equal(origin_endpoint_config["ChannelId"])
response["Description"].should.equal(origin_endpoint_config["Description"])
response["HlsPackage"].should.equal(origin_endpoint_config["HlsPackage"])
response["Origination"].should.equal("ALLOW")
@mock_mediapackage
def test_describe_origin_endpoint_succeeds():
client = boto3.client("mediapackage", region_name=region)
origin_endpoint_config = _create_origin_endpoint_config()
create_response = client.create_origin_endpoint(**origin_endpoint_config)
describe_response = client.describe_origin_endpoint(Id=create_response["Id"])
describe_response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
describe_response["Arn"].should.equal(
"arn:aws:mediapackage:origin_endpoint:{}".format(describe_response["Id"])
)
describe_response["ChannelId"].should.equal(origin_endpoint_config["ChannelId"])
describe_response["Description"].should.equal(origin_endpoint_config["Description"])
describe_response["HlsPackage"].should.equal(origin_endpoint_config["HlsPackage"])
describe_response["Origination"].should.equal("ALLOW")
describe_response["Url"].should.equal(
"https://origin-endpoint.mediapackage.{}.amazonaws.com/{}".format(
region, describe_response["Id"]
)
)
@mock_mediapackage
def test_delete_origin_endpoint_succeeds():
client = boto3.client("mediapackage", region_name=region)
origin_endpoint_config = _create_origin_endpoint_config()
create_response = client.create_origin_endpoint(**origin_endpoint_config)
list_response = client.list_origin_endpoints()
# Before deletion
origin_endpoints_list = list_response["OriginEndpoints"]
client.delete_origin_endpoint(Id=create_response["Id"])
# After deletion
post_deletion_list_response = client.list_origin_endpoints()
post_deletion_origin_endpoints_list = post_deletion_list_response["OriginEndpoints"]
len(post_deletion_origin_endpoints_list).should.equal(
len(origin_endpoints_list) - 1
)
@mock_mediapackage
def test_update_origin_endpoint_succeeds():
client = boto3.client("mediapackage", region_name=region)
origin_endpoint_config = _create_origin_endpoint_config()
create_response = client.create_origin_endpoint(**origin_endpoint_config)
update_response = client.update_origin_endpoint(
Id=create_response["Id"],
Description="updated-channel-description",
ManifestName="updated-manifest-name",
)
update_response["Description"].should.equal("updated-channel-description")
update_response["ManifestName"].should.equal("updated-manifest-name")
@mock_mediapackage
def test_list_origin_endpoint_succeeds():
origin_endpoints_list = []
client = boto3.client("mediapackage", region_name=region)
origin_endpoint_config = _create_origin_endpoint_config()
len(origin_endpoints_list).should.equal(0)
client.create_origin_endpoint(**origin_endpoint_config)
list_response = client.list_origin_endpoints()
origin_endpoints_list = list_response["OriginEndpoints"]
len(origin_endpoints_list).should.equal(1)
first_origin_endpoint = origin_endpoints_list[0]
first_origin_endpoint["Arn"].should.equal(
"arn:aws:mediapackage:origin_endpoint:{}".format(first_origin_endpoint["Id"])
)
first_origin_endpoint["ChannelId"].should.equal(origin_endpoint_config["ChannelId"])
first_origin_endpoint["Description"].should.equal(
origin_endpoint_config["Description"]
)
first_origin_endpoint["HlsPackage"].should.equal(
origin_endpoint_config["HlsPackage"]
)
first_origin_endpoint["Origination"].should.equal("ALLOW")

View File

@ -0,0 +1,30 @@
from __future__ import unicode_literals
import sure # noqa
import moto.server as server
from moto import mock_mediapackage
"""
Test the different server responses
"""
@mock_mediapackage
def test_mediapackage_list_channels():
backend = server.create_backend_app("mediapackage")
test_client = backend.test_client()
res = test_client.get("/channels")
result = res.data.decode("utf-8")
result.should.contain('"channels": []')
@mock_mediapackage
def test_mediapackage_list_origin_endpoints():
backend = server.create_backend_app("mediapackage")
test_client = backend.test_client()
res = test_client.get("/origin_endpoints")
result = res.data.decode("utf-8")
result.should.contain('"originEndpoints": []')