Skip to content
This repository was archived by the owner on Aug 14, 2024. It is now read-only.

Commit 5200867

Browse files
committed
refactor utils for resource tagging
1 parent 1fbf658 commit 5200867

7 files changed

Lines changed: 37 additions & 30 deletions

File tree

localstack/services/cloudformation/cloudformation_api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import xmltodict
55
from flask import Flask, request
66
from requests.models import Response
7-
from localstack.utils.aws import aws_stack
7+
from localstack.utils.aws import aws_stack, aws_responses
88
from localstack.utils.common import (
99
parse_request_data, short_uid, long_uid, clone, clone_safe, select_attributes,
1010
timestamp_millis, recurse_object)
@@ -177,7 +177,7 @@ def template_resources(self):
177177

178178
@property
179179
def tags(self):
180-
return aws_stack.extract_tags(self.metadata)
180+
return aws_responses.extract_tags(self.metadata)
181181

182182
@property
183183
def imports(self):

localstack/services/cloudwatch/cloudwatch_listener.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def forward_request(self, method, path, data, headers):
1919
action = req_data.get('Action')
2020
if action == 'TagResource':
2121
arn = req_data.get('ResourceARN')
22-
tags = aws_stack.extract_tags(req_data)
22+
tags = aws_responses.extract_tags(req_data)
2323
TAGS.tag_resource(arn, tags)
2424
return aws_responses.requests_response_xml(action, {}, xmlns=XMLNS_CLOUDWATCH)
2525
if action == 'UntagResource':
@@ -53,9 +53,8 @@ def return_response(self, method, path, data, headers, response):
5353
cloudwatch_backends[aws_stack.get_region()].alarms[name].treat_missing_data = treat_missing_data
5454
# record tags
5555
arn = aws_stack.cloudwatch_alarm_arn(name)
56-
tags = aws_stack.extract_tags(req_data)
57-
if tags:
58-
TAGS.tag_resource(arn, tags)
56+
tags = aws_responses.extract_tags(req_data)
57+
TAGS.tag_resource(arn, tags)
5958

6059
# Fix Incorrect date format to the correct format
6160
# the dictionary contains the tag as the key and the value is a

localstack/services/sns/sns_listener.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ def forward_request(self, method, path, data, headers):
176176
def _extract_tags(topic_arn, req_data, is_create_topic_request):
177177
tags = []
178178
req_tags = {k: v for k, v in req_data.items() if k.startswith('Tags.member.')}
179+
# TODO: use aws_responses.extract_tags(..) here!
179180
for i in range(int(len(req_tags.keys()) / 2)):
180181
key = req_tags['Tags.member.' + str(i + 1) + '.Key'][0]
181182
value = req_tags['Tags.member.' + str(i + 1) + '.Value'][0]

localstack/utils/aws/aws_responses.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,30 @@ def make_error(*args, **kwargs):
168168
return flask_error_response_xml(*args, **kwargs)
169169

170170

171+
def extract_tags(req_data):
172+
keys = []
173+
values = []
174+
for param_name in ['Tag', 'member']:
175+
keys = extract_url_encoded_param_list(req_data, 'Tags.{}.%s.Key'.format(param_name))
176+
values = extract_url_encoded_param_list(req_data, 'Tags.{}.%s.Value'.format(param_name))
177+
if keys and values:
178+
break
179+
entries = zip(keys, values)
180+
tags = [{'Key': entry[0], 'Value': entry[1]} for entry in entries]
181+
return tags
182+
183+
184+
def extract_url_encoded_param_list(req_data, pattern):
185+
result = []
186+
for i in range(1, 200):
187+
key = pattern % i
188+
value = req_data.get(key)
189+
if value is None:
190+
break
191+
result.append(value)
192+
return result
193+
194+
171195
def calculate_crc32(content):
172196
return crc32(to_bytes(content)) & 0xffffffff
173197

localstack/utils/aws/aws_stack.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -972,17 +972,3 @@ def check_stack():
972972
def await_stack_completion(stack_name, retries=20, sleep=2, statuses=None):
973973
statuses = statuses or ['CREATE_COMPLETE', 'UPDATE_COMPLETE']
974974
return await_stack_status(stack_name, statuses, retries=retries, sleep=sleep)
975-
976-
977-
# TODO: move to aws_responses.py?
978-
def extract_tags(req_data):
979-
tags = []
980-
for i in range(1, 200):
981-
k1 = 'Tags.member.%s.Key' % i
982-
k2 = 'Tags.member.%s.Value' % i
983-
key = req_data.get(k1)
984-
value = req_data.get(k2, '')
985-
if key is None:
986-
break
987-
tags.append({'Key': key, 'Value': value})
988-
return tags

localstack/utils/tagging.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ class TaggingService(object):
33
def __init__(self):
44
self.tags = {}
55

6-
def list_tags_for_resource(self, arn):
6+
def list_tags_for_resource(self, arn, root_name=None):
7+
root_name = root_name or 'Tags'
78
result = []
89
if arn in self.tags:
910
for k, v in self.tags[arn].items():
1011
result.append({'Key': k, 'Value': v})
11-
return {'Tags': result}
12+
return {root_name: result}
1213

1314
def tag_resource(self, arn, tags):
15+
if not tags:
16+
return
1417
if arn not in self.tags:
1518
self.tags[arn] = {}
1619
for t in tags:

tests/integration/test_sqs.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,12 @@
44
import unittest
55
import requests
66
import datetime
7-
87
from botocore.exceptions import ClientError
98
from botocore.awsrequest import AWSRequest
109
from botocore.credentials import Credentials
1110
from botocore.auth import SigV4Auth, SIGV4_TIMESTAMP
12-
from localstack.constants import (
13-
TEST_AWS_ACCOUNT_ID,
14-
TEST_AWS_ACCESS_KEY_ID,
15-
TEST_AWS_SECRET_ACCESS_KEY
16-
)
11+
from localstack.constants import TEST_AWS_ACCOUNT_ID, TEST_AWS_ACCESS_KEY_ID, TEST_AWS_SECRET_ACCESS_KEY
1712
from six.moves.urllib.parse import urlencode
18-
1913
from localstack import config
2014
from localstack.utils import testutil
2115
from localstack.utils.aws import aws_stack
@@ -867,7 +861,7 @@ def test_create_queue_with_slashes(self):
867861
self.client.delete_queue(QueueUrl=queue_url.get('QueueUrl'))
868862

869863
result = self.client.list_queues()
870-
self.assertNotIn(queue_url.get('QueueUrl'), result.get('QueueUrls'))
864+
self.assertNotIn(queue_url.get('QueueUrl'), result.get('QueueUrls', []))
871865

872866
def list_queues_with_auth_in_presigned_url(self, method):
873867
base_url = '{}://{}:{}'.format(get_service_protocol(), config.LOCALSTACK_HOSTNAME, config.PORT_SQS)

0 commit comments

Comments
 (0)