Add support and unittests for Route53 tags
This commit is contained in:
parent
97513590c8
commit
9a7556b3af
@ -1,5 +1,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
import uuid
|
||||
from jinja2 import Template
|
||||
|
||||
@ -226,6 +228,7 @@ class Route53Backend(BaseBackend):
|
||||
def __init__(self):
|
||||
self.zones = {}
|
||||
self.health_checks = {}
|
||||
self.resource_tags = defaultdict(dict)
|
||||
|
||||
def create_hosted_zone(self, name, private_zone, comment=None):
|
||||
new_id = get_random_hex()
|
||||
@ -233,6 +236,25 @@ class Route53Backend(BaseBackend):
|
||||
self.zones[new_id] = new_zone
|
||||
return new_zone
|
||||
|
||||
def change_tags_for_resource(self, resource_id, tags):
|
||||
if 'Tag' in tags:
|
||||
for key, tag in tags.items():
|
||||
for t in tag:
|
||||
self.resource_tags[resource_id][t['Key']] = t['Value']
|
||||
|
||||
else:
|
||||
for _, keys in tags.items():
|
||||
if isinstance(keys, list):
|
||||
for key in keys:
|
||||
del(self.resource_tags[resource_id][key])
|
||||
else:
|
||||
del(self.resource_tags[resource_id][keys])
|
||||
|
||||
|
||||
def list_tags_for_resource(self, resource_id):
|
||||
if resource_id in self.resource_tags:
|
||||
return self.resource_tags[resource_id]
|
||||
|
||||
def get_all_hosted_zones(self):
|
||||
return self.zones.values()
|
||||
|
||||
|
@ -15,7 +15,7 @@ def list_or_create_hostzone_response(request, full_url, headers):
|
||||
# in boto3, this field is set directly in the xml
|
||||
private_zone = elements["CreateHostedZoneRequest"]["HostedZoneConfig"]["PrivateZone"]
|
||||
except KeyError:
|
||||
# if a VPC subsection is only included in xmls params when private_zone=True,
|
||||
# if a VPC subsection is only included in xmls params when private_zone=True,
|
||||
# see boto: boto/route53/connection.py
|
||||
private_zone = 'VPC' in elements["CreateHostedZoneRequest"]
|
||||
else:
|
||||
@ -138,6 +138,52 @@ def not_implemented_response(request, full_url, headers):
|
||||
raise NotImplementedError("The action for {0} has not been implemented for route 53".format(action))
|
||||
|
||||
|
||||
def list_or_change_tags_for_resource_request(request, full_url, headers):
|
||||
parsed_url = urlparse(full_url)
|
||||
id_ = parsed_url.path.split("/")[-1]
|
||||
type_ = parsed_url.path.split("/")[-2]
|
||||
|
||||
if request.method == "GET":
|
||||
tags = route53_backend.list_tags_for_resource(id_)
|
||||
template = Template(LIST_TAGS_FOR_RESOURCE_RESPONSE)
|
||||
return 200, headers, template.render(
|
||||
resource_type=type_, resource_id=id_, tags=tags)
|
||||
|
||||
if request.method == "POST":
|
||||
tags = xmltodict.parse(
|
||||
request.body)['ChangeTagsForResourceRequest']
|
||||
|
||||
if 'AddTags' in tags:
|
||||
tags = tags['AddTags']
|
||||
elif 'RemoveTagKeys' in tags:
|
||||
tags = tags['RemoveTagKeys']
|
||||
|
||||
route53_backend.change_tags_for_resource(id_, tags)
|
||||
template = Template(CHANGE_TAGS_FOR_RESOURCE_RESPONSE)
|
||||
|
||||
return 200, headers, template.render()
|
||||
|
||||
LIST_TAGS_FOR_RESOURCE_RESPONSE = """
|
||||
<ListTagsForResourceResponse xmlns="https://route53.amazonaws.com/doc/2015-01-01/">
|
||||
<ResourceTagSet>
|
||||
<ResourceType>{{resource_type}}</ResourceType>
|
||||
<ResourceId>{{resource_id}}</ResourceId>
|
||||
<Tags>
|
||||
{% for key, value in tags.items() %}
|
||||
<Tag>
|
||||
<Key>{{key}}</Key>
|
||||
<Value>{{value}}</Value>
|
||||
</Tag>
|
||||
{% endfor %}
|
||||
</Tags>
|
||||
</ResourceTagSet>
|
||||
</ListTagsForResourceResponse>
|
||||
"""
|
||||
|
||||
CHANGE_TAGS_FOR_RESOURCE_RESPONSE = """<ChangeTagsForResourceResponse xmlns="https://route53.amazonaws.com/doc/2015-01-01/">
|
||||
</ChangeTagsForResourceResponse>
|
||||
"""
|
||||
|
||||
LIST_RRSET_REPONSE = """<ListResourceRecordSetsResponse xmlns="https://route53.amazonaws.com/doc/2012-12-12/">
|
||||
<ResourceRecordSets>
|
||||
{% for record_set in record_sets %}
|
||||
|
@ -10,5 +10,6 @@ url_paths = {
|
||||
'{0}hostedzone/[^/]+$': responses.get_or_delete_hostzone_response,
|
||||
'{0}hostedzone/[^/]+/rrset/?$': responses.rrset_response,
|
||||
'{0}healthcheck': responses.health_check_response,
|
||||
'{0}tags|trafficpolicyinstances/*': responses.not_implemented_response,
|
||||
'{0}tags/(healthcheck|hostedzone)/*': responses.list_or_change_tags_for_resource_request,
|
||||
'{0}trafficpolicyinstances/*': responses.not_implemented_response
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ from boto.route53.record import ResourceRecordSets
|
||||
|
||||
import sure # noqa
|
||||
|
||||
import uuid
|
||||
|
||||
from moto import mock_route53
|
||||
|
||||
|
||||
@ -328,3 +330,66 @@ def test_hosted_zone_private_zone_preserved_boto3():
|
||||
|
||||
# zone = conn.list_hosted_zones_by_name(DNSName="testdns.aws.com.")
|
||||
# zone.config["PrivateZone"].should.equal(True)
|
||||
|
||||
@mock_route53
|
||||
def test_list_or_change_tags_for_resource_request():
|
||||
conn = boto3.client('route53')
|
||||
healthcheck_id = str(uuid.uuid4())
|
||||
|
||||
tag1 = {"Key": "Deploy", "Value": "True"}
|
||||
tag2 = {"Key": "Name", "Value": "UnitTest"}
|
||||
|
||||
# Test adding a tag for a resource id
|
||||
conn.change_tags_for_resource(
|
||||
ResourceType='healthcheck',
|
||||
ResourceId=healthcheck_id,
|
||||
AddTags=[tag1, tag2]
|
||||
)
|
||||
|
||||
# Check to make sure that the response has the 'ResourceTagSet' key
|
||||
response = conn.list_tags_for_resource(ResourceType='healthcheck', ResourceId=healthcheck_id)
|
||||
response.should.contain('ResourceTagSet')
|
||||
|
||||
# Validate that each key was added
|
||||
response['ResourceTagSet']['Tags'].should.contain(tag1)
|
||||
response['ResourceTagSet']['Tags'].should.contain(tag2)
|
||||
|
||||
# Try to remove the tags
|
||||
conn.change_tags_for_resource(
|
||||
ResourceType='healthcheck',
|
||||
ResourceId=healthcheck_id,
|
||||
RemoveTagKeys=[tag1['Key']]
|
||||
)
|
||||
|
||||
# Check to make sure that the response has the 'ResourceTagSet' key
|
||||
response = conn.list_tags_for_resource(ResourceType='healthcheck', ResourceId=healthcheck_id)
|
||||
response.should.contain('ResourceTagSet')
|
||||
response['ResourceTagSet']['Tags'].should_not.contain(tag1)
|
||||
response['ResourceTagSet']['Tags'].should.contain(tag2)
|
||||
|
||||
# Remove the second tag
|
||||
conn.change_tags_for_resource(
|
||||
ResourceType='healthcheck',
|
||||
ResourceId=healthcheck_id,
|
||||
RemoveTagKeys=[tag2['Key']]
|
||||
)
|
||||
|
||||
response = conn.list_tags_for_resource(ResourceType='healthcheck', ResourceId=healthcheck_id)
|
||||
response['ResourceTagSet']['Tags'].should_not.contain(tag2)
|
||||
|
||||
# Re-add the tags
|
||||
conn.change_tags_for_resource(
|
||||
ResourceType='healthcheck',
|
||||
ResourceId=healthcheck_id,
|
||||
AddTags=[tag1, tag2]
|
||||
)
|
||||
|
||||
# Remove both
|
||||
conn.change_tags_for_resource(
|
||||
ResourceType='healthcheck',
|
||||
ResourceId=healthcheck_id,
|
||||
RemoveTagKeys=[tag1['Key'], tag2['Key']]
|
||||
)
|
||||
|
||||
response = conn.list_tags_for_resource(ResourceType='healthcheck', ResourceId=healthcheck_id)
|
||||
response['ResourceTagSet']['Tags'].should.be.empty
|
||||
|
Loading…
Reference in New Issue
Block a user