Skip to content

Commit df9d6e7

Browse files
authored
Merge pull request #240 from awslabs/more-robust-data-collection
marke cases and budgets collection more robust
2 parents ae8a663 + 97b0561 commit df9d6e7

File tree

4 files changed

+46
-31
lines changed

4 files changed

+46
-31
lines changed

data-collection/deploy/account-collector.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ Resources:
146146
raise Exception(f"Lambda event must have 'Type' parameter with value = ({list(functions.keys())})") #pylint: disable=broad-exception-raised
147147
148148
account_iterator = functions[account_type]
149-
with open(TMP_FILE, "w") as f:
149+
with open(TMP_FILE, "w", encoding='utf-8') as f:
150150
count = 0
151151
f.write("[\n")
152152
for account in account_iterator():
@@ -194,10 +194,9 @@ Resources:
194194
account = account_data.split(',')
195195
yield format_account(account[0], account[1], account[2])
196196
else:
197-
logger.info(f'Using payer organization for the account list')
197+
logger.info('Using payer organization for the account list')
198198
excluded_accounts = get_from_bucket(BUCKET, EXCLUDED_ACCOUNT_LIST_KEY)
199199
if excluded_accounts:
200-
pass
201200
logger.info(f'Found list of accounts to exclude in s3://{BUCKET}/{EXCLUDED_ACCOUNT_LIST_KEY}. Will only collect accounts that are not in the list')
202201
excluded_accounts = [a.strip() for a in excluded_accounts[0].split(',') if a]
203202
for org_account_data in iterate_admins_accounts('organizations'):
@@ -228,7 +227,7 @@ Resources:
228227
try:
229228
data = s3.get_object(Bucket=bucket, Key=key)
230229
return data['Body'].read().decode('utf-8').strip('\n').split('\n')
231-
except Exception as exc: #pylint: disable=broad-exception-caught
230+
except Exception: #pylint: disable=broad-exception-caught
232231
return None
233232
234233
def format_account(account_id, account_name, payer_id):

data-collection/deploy/module-budgets.yaml

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ Resources:
110110
import logging
111111
import datetime
112112
from json import JSONEncoder
113-
import sys
114113
115114
import boto3
116115
@@ -157,31 +156,36 @@ Resources:
157156
payer_id = account["payer_id"]
158157
159158
logger.info(f"Collecting data for account: {account_id}")
160-
budgets_client = assume_role(account_id, "budgets", "us-east-1") # must be us-east-1
161-
count = 0
162-
with open(TMP_FILE, "w", encoding='utf-8') as f:
163-
for budget in budgets_client.get_paginator("describe_budgets").paginate(AccountId=account_id).search('Budgets'):
164-
if not budget: continue
165-
budget['collection_time'] = collection_time
166-
167-
# Fetch tags for the budget using List tag for resource API
168-
budget_name = budget['BudgetName']
169-
budget_tags = budgets_client.list_tags_for_resource(ResourceARN=f"arn:{aws_partition}:budgets::{account_id}:budget/{budget_name}")
170-
budget.update({
171-
'Account_ID': account_id,
172-
'Account_Name': account_name,
173-
'Tags': budget_tags.get('ResourceTags') or []
174-
})
175-
176-
# Fetch CostFilters if available
177-
if not budget.get('CostFilters'):
178-
budget.update({'CostFilters': {'Filter': ['None']}})
179-
180-
f.write(json.dumps(budget, cls=DateTimeEncoder) + "\n")
181-
count += 1
182-
logger.info(f"Budgets collected: {count}")
183-
s3_upload(account_id, payer_id)
159+
try:
160+
budgets_client = assume_role(account_id, "budgets", "us-east-1") # must be us-east-1
161+
count = 0
162+
with open(TMP_FILE, "w", encoding='utf-8') as f:
163+
for budget in budgets_client.get_paginator("describe_budgets").paginate(AccountId=account_id).search('Budgets'):
164+
if not budget:
165+
continue
166+
budget['collection_time'] = collection_time
167+
# Fetch tags for the budget using List tag for resource API
168+
budget_name = budget['BudgetName']
169+
budget_tags = budgets_client.list_tags_for_resource(ResourceARN=f"arn:{aws_partition}:budgets::{account_id}:budget/{budget_name}")
170+
budget.update({
171+
'Account_ID': account_id,
172+
'Account_Name': account_name,
173+
'Tags': budget_tags.get('ResourceTags') or []
174+
})
175+
# Fetch CostFilters if available
176+
if not budget.get('CostFilters'):
177+
budget.update({'CostFilters': {'Filter': ['None']}})
184178
179+
f.write(json.dumps(budget, cls=DateTimeEncoder) + "\n")
180+
count += 1
181+
logger.info(f"Budgets collected: {count}")
182+
s3_upload(account_id, payer_id)
183+
except Exception as exc: #pylint: disable=broad-exception-caught
184+
if "AccessDenied" in str(exc):
185+
print(f'Failed to assume role {ROLE_NAME} in account {account_id}. Please make sure the role exists. {exc}')
186+
else:
187+
print(f'{exc}. Gracefully exiting from Lambda so we do not break all StepFunction Execution')
188+
return
185189
186190
def s3_upload(account_id, payer_id):
187191
if os.path.getsize(TMP_FILE) == 0:

data-collection/deploy/module-support-cases.yaml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,17 @@ Resources:
143143
raise RuntimeError(f"(MissingParameterError) Lambda event missing '{key}' parameter")
144144
145145
account = json.loads(event[key])
146-
main(account, ROLE_NAME, MODULE_NAME, BUCKET)
146+
147+
try:
148+
main(account, ROLE_NAME, MODULE_NAME, BUCKET)
149+
except Exception as exc: #pylint: disable=broad-exception-caught
150+
if "AccessDenied" in str(exc):
151+
print(f'Failed to assume role {ROLE_NAME} in account {account}. Please make sure the role exists. {exc}')
152+
else:
153+
print(f'{exc}. Gracefully exiting from Lambda so we do not break all StepFunction Execution')
154+
return {
155+
'statusCode': 200
156+
}
147157
return {
148158
'statusCode': 200
149159
}
@@ -172,7 +182,7 @@ Resources:
172182
x.isoformat() if isinstance(x, (date, datetime)) else None
173183
)
174184
175-
def main(account, role_name, module_name, bucket):
185+
def main(account, role_name, module_name, bucket): #pylint: disable=too-many-locals
176186
account_id = account["account_id"]
177187
payer_id = account["payer_id"]
178188
account_name = account.get("account_name", None)

data-collection/test/test_from_scratch.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
logger = logging.getLogger(__name__)
4242

4343

44+
def test_deployment_works(athena):
45+
pass
4446

4547
def test_budgets_data(athena):
4648
data = athena_query(athena=athena, sql_query='SELECT * FROM "optimization_data"."budgets_data" LIMIT 10;')

0 commit comments

Comments
 (0)