Skip to content

Commit 0ea6b90

Browse files
authored
[IT-4483] Refactor get_synapse_owner_id (#63)
Refactor get_synapse_owner_id method to get the owner ID from both synapse::ownerId and aws:servicecatalog:provisioningPrincipalArn tags with the former as the preferred option and the latter as the fallback option. This implements the following proposal in IT-4483: ``` For a SC product Updates action the lambda currently also gets the synapse id from the aws:servicecatalog:provisioningPrincipalArn tag. We would need to refactor the lambda to get the synapse id from thesynapse:owerId tag instead. Then the lambda will generate and apply all of the synapse prefixed tags with the new owner info. ```
1 parent 61bb409 commit 0ea6b90

File tree

2 files changed

+88
-65
lines changed

2 files changed

+88
-65
lines changed

set_tags/utils.py

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -107,47 +107,50 @@ def get_env_var_value(env_var):
107107
return value
108108

109109
def get_synapse_owner_id(tags):
110-
'''Find the value of the principal ARN among the resource tags. The principal
111-
ARN tag is applied by AWS and it's value should be in the following format
112-
'arn:aws:sts::111111111:assumed-role/ServiceCatalogEndusers/1234567'
113-
'''
114-
principal_arn_tag = 'aws:servicecatalog:provisioningPrincipalArn'
115-
for tag in tags:
116-
if tag.get('Key') == principal_arn_tag:
117-
principal_arn_value = tag.get('Value')
118-
synapse_owner_id = principal_arn_value.split('/')[-1]
119-
return synapse_owner_id
120-
else:
121-
raise ValueError(f'Expected to find {principal_arn_tag} in {tags}')
122-
123-
def get_synapse_owner_id(tags):
124-
'''Find the value of the principal ARN among the resource tags. The principal
125-
ARN tag is applied by AWS and it's value should be in the following format
126-
'arn:aws:sts::111111111:assumed-role/ServiceCatalogEndusers/378505'
110+
'''Find the synapse owner ID from a group of tags. Look for the id from
111+
'synapse:ownerId' tag first, if not found then look for the
112+
'aws:servicecatalog:provisioningPrincipalArn' tag (IT-4483).
113+
The principal ARN tag is applied by AWS on an initial service catalog
114+
product deployment, it's value is in the following format
115+
'arn:aws:sts::111111111:assumed-role/ServiceCatalogEndusers/378505'
127116
:param tags: resource tags can take two forms
128117
* A list of dictionary of key/value pairs
129-
i.e. tags:[{'Key':'string', 'Value':'string'}]
130-
* A dictionary of key pairs
131-
i.e. tags:{'string':'string'}
118+
i.e. tags = [{'Key':'key1', 'Value':'value1'}, {'Key':'key2', 'Value':'value2'}]
119+
* A dictionary of key value pairs
120+
i.e. tags = {'key1':'value1', 'key2':'value2'}
132121
returns: the synapse user id (i.e. 378505)
133122
'''
123+
synapse_owner_id_tag = 'synapse:ownerId'
134124
principal_arn_tag = 'aws:servicecatalog:provisioningPrincipalArn'
135-
synapse_owner_id = None
136125

137-
if isinstance(tags, list): # tags:[{'Key':'string', 'Value':'string'}]
138-
for tag in tags:
139-
if tag.get('Key') == principal_arn_tag:
140-
principal_arn_value = tag.get('Value')
126+
# Case 1: list of dicts with "Key"/"Value"
127+
# tags = [{'Key':'key1', 'Value':'value1'}, {'Key':'key2', 'Value':'value2'}]
128+
if isinstance(tags, list):
129+
for item in tags: # Look for synapse:ownerId first
130+
if item.get("Key") == synapse_owner_id_tag:
131+
synapse_owner_id = item.get('Value')
132+
return synapse_owner_id
133+
for item in tags: # Fallback to aws:servicecatalog:provisioningPrincipalArn
134+
if item.get("Key") == principal_arn_tag:
135+
principal_arn_value = item.get('Value')
141136
synapse_owner_id = principal_arn_value.split('/')[-1]
142-
if isinstance(tags, dict): # tags:{'string':'string'}
143-
if principal_arn_tag in tags:
144-
principal_arn_value = tags.get(principal_arn_tag)
145-
synapse_owner_id = principal_arn_value.split('/')[-1]
146-
147-
if synapse_owner_id is None:
148-
raise ValueError(f'{principal_arn_tag} not found in tags: {tags}')
137+
return synapse_owner_id
138+
return None
139+
140+
# Case 2: dictionary of key-value pairs
141+
# tags = {'key1':'value1', 'key2':'value2'}
142+
elif isinstance(tags, dict):
143+
if synapse_owner_id_tag in tags: # Look for synapse:ownerId first
144+
synapse_owner_id = tags[synapse_owner_id_tag]
145+
return synapse_owner_id
146+
elif principal_arn_tag in tags: # Fallback to aws:servicecatalog:provisioningPrincipalArn
147+
principal_arn_value = tags[principal_arn_tag]
148+
synapse_owner_id = principal_arn_value.split('/')[-1]
149+
return synapse_owner_id
150+
return None
149151

150-
return synapse_owner_id
152+
else:
153+
raise TypeError("Input must be either a dict or a list of {'Key':..., 'Value':...} dicts.")
151154

152155
def get_synapse_user_profile(synapse_id):
153156
'''Get synapse user profile data'''

tests/unit/utils/test_get_synapse_owner_id.py

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,56 @@
55

66
class TestGetSynapseOwnerId(unittest.TestCase):
77

8-
def test_list_tag_present(self):
9-
tags = [
10-
{'Key': 'heresatag', 'Value': 'heresatagvalue'},
11-
{'Key': 'theresatag', 'Value': 'theresatagvalue'},
12-
{'Key': 'aws:servicecatalog:provisioningPrincipalArn', 'Value': 'foo/bar'}
13-
]
14-
result = utils.get_synapse_owner_id(tags)
15-
self.assertEqual(result, 'bar')
16-
17-
def test_list_tag_missing(self):
18-
with self.assertRaises(ValueError):
19-
tags = [
20-
{'Key': 'heresatag', 'Value': 'heresatagvalue'},
21-
{'Key': 'theresatag', 'Value': 'theresatagvalue'}
22-
]
23-
utils.get_synapse_owner_id(tags)
24-
25-
def test_dict_tag_present(self):
26-
tags = {
27-
'heresatag': 'heresatagvalue',
28-
'theresatag':'theresatagvalue',
29-
'aws:servicecatalog:provisioningPrincipalArn':'foo/bar'
30-
}
31-
result = utils.get_synapse_owner_id(tags)
32-
self.assertEqual(result, 'bar')
33-
34-
def test_dict_tag_missing(self):
35-
with self.assertRaises(ValueError):
36-
tags = {
37-
'heresatag': 'heresatagvalue',
38-
'theresatag': 'theresatagvalue',
8+
def test_dict_with_both_keys(self):
9+
data = {
10+
"synapse:ownerId": "1234567",
11+
"aws:servicecatalog:provisioningPrincipalArn": "arn:aws:sts::111111111:assumed-role/ServiceCatalogEndusers/378505"
3912
}
40-
utils.get_synapse_owner_id(tags)
13+
self.assertEqual(utils.get_synapse_owner_id(data), "1234567")
14+
15+
def test_dict_with_only_owner(self):
16+
data = {"synapse:ownerId": "1234567"}
17+
self.assertEqual(utils.get_synapse_owner_id(data), "1234567")
18+
19+
def test_dict_with_only_principal(self):
20+
data = {"aws:servicecatalog:provisioningPrincipalArn": "arn:aws:sts::111111111:assumed-role/ServiceCatalogEndusers/378505"}
21+
self.assertEqual(
22+
utils.get_synapse_owner_id(data),
23+
"378505"
24+
)
25+
26+
def test_dict_with_no_keys(self):
27+
data = {"foo": "bar"}
28+
self.assertIsNone(utils.get_synapse_owner_id(data))
29+
30+
def test_list_with_both_keys(self):
31+
data = [
32+
{"Key": "aws:servicecatalog:provisioningPrincipalArn", "Value": "arn:aws:sts::111111111:assumed-role/ServiceCatalogEndusers/378505"},
33+
{"Key": "synapse:ownerId", "Value": "1234567"},
34+
]
35+
self.assertEqual(utils.get_synapse_owner_id(data), "1234567")
36+
37+
def test_list_with_only_owner(self):
38+
data = [{"Key": "synapse:ownerId", "Value": "1234567"}]
39+
self.assertEqual(utils.get_synapse_owner_id(data), "1234567")
40+
41+
def test_list_with_only_principal(self):
42+
data = [{"Key": "aws:servicecatalog:provisioningPrincipalArn", "Value": "arn:aws:sts::111111111:assumed-role/ServiceCatalogEndusers/378505"}]
43+
self.assertEqual(
44+
utils.get_synapse_owner_id(data),
45+
"378505"
46+
)
47+
48+
def test_list_with_no_keys(self):
49+
data = [{"Key": "foo", "Value": "bar"}]
50+
self.assertIsNone(utils.get_synapse_owner_id(data))
51+
52+
def test_empty_dict(self):
53+
self.assertIsNone(utils.get_synapse_owner_id({}))
54+
55+
def test_empty_list(self):
56+
self.assertIsNone(utils.get_synapse_owner_id([]))
57+
58+
def test_invalid_type(self):
59+
with self.assertRaises(TypeError):
60+
utils.get_synapse_owner_id("not a dict or list")

0 commit comments

Comments
 (0)