Skip to content

Commit

Permalink
[BUG FIX] route53 list_tags_for_resources no results & hostedzone ids…
Browse files Browse the repository at this point in the history
… not decoding properly (#8131)
  • Loading branch information
zkarpinski authored Sep 21, 2024
1 parent acd682d commit 1c30b5b
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 12 deletions.
8 changes: 5 additions & 3 deletions moto/route53/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,10 +647,12 @@ def list_tags_for_resource(self, resource_id: str) -> Dict[str, str]:
return self.resource_tags[resource_id]
return {}

def list_tags_for_resources(self, resource_ids: List[str]) -> Dict[str, str]:
resources = {}
def list_tags_for_resources(self, resource_ids: List[str]) -> List[Dict[str, Any]]:
resources = []
for id in resource_ids:
resources.update(self.list_tags_for_resource(id))
resource_set = {"ResourceId": id, "Tags": {}}
resource_set["Tags"] = self.list_tags_for_resource(id)
resources.append(resource_set)
return resources

def list_resource_record_sets(
Expand Down
22 changes: 14 additions & 8 deletions moto/route53/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import re
from typing import Any
from urllib.parse import parse_qs
from urllib.parse import parse_qs, unquote

import xmltodict
from jinja2 import Template
Expand Down Expand Up @@ -346,8 +346,10 @@ def list_or_change_tags_for_resource_request( # type: ignore[return]
) -> TYPE_RESPONSE:
self.setup_class(request, full_url, headers)

id_ = self.parsed_url.path.split("/")[-1]
type_ = self.parsed_url.path.split("/")[-2]
id_matcher = re.search(r"/tags/([-a-z]+)/(.+)", self.parsed_url.path)
assert id_matcher
type_ = id_matcher.group(1)
id_ = unquote(id_matcher.group(2))

if request.method == "GET":
tags = self.backend.list_tags_for_resource(id_)
Expand All @@ -371,12 +373,16 @@ def list_or_change_tags_for_resource_request( # type: ignore[return]
return 200, headers, template.render()

def list_tags_for_resources(self) -> str:
if id_matcher := re.search(r"/tags/[-a-z]+/(.+)", self.parsed_url.path):
resource_type = unquote(id_matcher.group(1))
else:
resource_type = ""
resource_ids = xmltodict.parse(self.body)["ListTagsForResourcesRequest"][
"ResourceIds"
]
]["ResourceId"]
tag_sets = self.backend.list_tags_for_resources(resource_ids=resource_ids)
template = Template(LIST_TAGS_FOR_RESOURCES_RESPONSE)
return template.render(tag_sets)
return template.render(tag_sets=tag_sets, resource_type=resource_type)

def get_change(self) -> str:
change_id = self.parsed_url.path.rstrip("/").rsplit("/", 1)[1]
Expand Down Expand Up @@ -494,10 +500,10 @@ def delete_reusable_delegation_set(self) -> str:
<ResourceTagSets>
{% for set in tag_sets %}
<ResourceTagSet>
<ResourceType>{{set.resource_type}}</ResourceType>
<ResourceId>{{set.resource_id}}</ResourceId>
<ResourceType>{{resource_type}}</ResourceType>
<ResourceId>{{set["ResourceId"]}}</ResourceId>
<Tags>
{% for key, value in set.tags.items() %}
{% for key, value in set["Tags"].items() %}
<Tag>
<Key>{{key}}</Key>
<Value>{{value}}</Value>
Expand Down
72 changes: 71 additions & 1 deletion tests/test_route53/test_route53.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ def test_list_or_change_tags_for_resource_request():
@mock_aws
def test_list_tags_for_resources():
conn = boto3.client("route53", region_name="us-east-1")
# Create two hosted zones
zone1 = conn.create_hosted_zone(
Name="testdns1.aws.com", CallerReference=str(hash("foo"))
)
Expand All @@ -562,11 +563,48 @@ def test_list_tags_for_resources():
)
zone2_id = zone2["HostedZone"]["Id"]

# confirm this works for resources with zero tags
# Create two healthchecks
health_check1 = conn.create_health_check(
CallerReference="foo",
HealthCheckConfig={
"IPAddress": "192.0.2.44",
"Port": 123,
"Type": "HTTP",
"ResourcePath": "/",
"RequestInterval": 30,
"FailureThreshold": 123,
"HealthThreshold": 123,
},
)
healthcheck1_id = health_check1["HealthCheck"]["Id"]

health_check2 = conn.create_health_check(
CallerReference="bar",
HealthCheckConfig={
"IPAddress": "192.0.2.44",
"Port": 123,
"Type": "HTTP",
"ResourcePath": "/",
"RequestInterval": 30,
"FailureThreshold": 123,
"HealthThreshold": 123,
},
)
healthcheck2_id = health_check2["HealthCheck"]["Id"]

# confirm this works for resources with zero tags for hostedzone
response = conn.list_tags_for_resources(
ResourceIds=[zone1_id, zone2_id], ResourceType="hostedzone"
)

for set in response["ResourceTagSets"]:
assert set["Tags"] == []

# confirm this works for resources with zero tags for healthchecks
response = conn.list_tags_for_resources(
ResourceIds=[healthcheck1_id, healthcheck2_id], ResourceType="healthcheck"
)

for set in response["ResourceTagSets"]:
assert set["Tags"] == []

Expand All @@ -582,14 +620,46 @@ def test_list_tags_for_resources():
ResourceType="hostedzone", ResourceId=zone2_id, AddTags=[tag3, tag4]
)

conn.change_tags_for_resource(
ResourceType="healthcheck", ResourceId=healthcheck1_id, AddTags=[tag1, tag2]
)
conn.change_tags_for_resource(
ResourceType="healthcheck", ResourceId=healthcheck2_id, AddTags=[tag3, tag4]
)

# Test hostedzone
response = conn.list_tags_for_resources(
ResourceIds=[zone1_id, zone2_id], ResourceType="hostedzone"
)
assert len(response["ResourceTagSets"]) == 2
for set in response["ResourceTagSets"]:
assert set["ResourceId"] in (zone1_id, zone2_id)
if set["ResourceId"] == zone1_id:
assert tag1 in set["Tags"]
assert tag2 in set["Tags"]
assert tag3 not in set["Tags"]
assert tag4 not in set["Tags"]
elif set["ResourceId"] == zone2_id:
assert tag1 not in set["Tags"]
assert tag2 not in set["Tags"]
assert tag3 in set["Tags"]
assert tag4 in set["Tags"]

# Test healthcheck
response = conn.list_tags_for_resources(
ResourceIds=[healthcheck1_id, healthcheck2_id], ResourceType="healthcheck"
)
assert len(response["ResourceTagSets"]) == 2
for set in response["ResourceTagSets"]:
assert set["ResourceId"] in (healthcheck1_id, healthcheck2_id)
if set["ResourceId"] == healthcheck1_id:
assert tag1 in set["Tags"]
assert tag2 in set["Tags"]
assert tag3 not in set["Tags"]
assert tag4 not in set["Tags"]
elif set["ResourceId"] == healthcheck2_id:
assert tag1 not in set["Tags"]
assert tag2 not in set["Tags"]
assert tag3 in set["Tags"]
assert tag4 in set["Tags"]

Expand Down

0 comments on commit 1c30b5b

Please sign in to comment.