diff --git a/report.py b/report.py index 0a442278..050da766 100644 --- a/report.py +++ b/report.py @@ -40,6 +40,7 @@ class Report: + UNTAGGED = '(untagged)' def __init__(self, *, platform: str, date: datetime.date, config_path: str): self.platform = platform @@ -126,6 +127,10 @@ def render_email(self, class AWSReport(Report): + # TODO: Should move this into a config file. Holding off for now as there is a config refactor in the near future + RESOURCE_SHORTHAND = {"Amazon Elastic Compute Cloud": "AWS EC2", + "Amazon Simple Storage Service": "AWS S3 Bucket", + "Amazon Elastic Block Store": "AWS EBS"} def __init__(self, config_path: str, date: datetime.date): super().__init__(platform='aws', config_path=config_path, date=date) @@ -161,20 +166,28 @@ def generate_report(self) -> str: ec2_owner_by_account_today = nested_dict() ec2_by_name = collections.defaultdict(Decimal) ec2_by_name_today = collections.defaultdict(Decimal) + untagged_resource_by_account = collections.defaultdict(dict) today = self.date.strftime('%Y-%m-%d') for row in report_csv: - account = self.accounts.get(row['lineItem/UsageAccountId'], '(unknown)') - service = row['product/ProductName'] - amount = Decimal(row['lineItem/BlendedCost']) + account = self.accounts.get(row['lineItem/UsageAccountId'], '(unknown)') # account for resource + resource_id = row['lineItem/ResourceId'] # id of the resource + service = row['product/ProductName'] # which type of product this is + amount = Decimal(row['lineItem/BlendedCost']) # the cost associated with this when = row['lineItem/UsageStartDate'][0:10] # ISO8601 + owner = row['resourceTags/user:Owner'] or self.UNTAGGED # owner of the resource, untagged if none specified + name = row['resourceTags/user:Name'] or self.UNTAGGED # name of the resource, untagged if none specified + + # if the resource is untagged, we want to explicitly list it under it's respective account + if (owner == self.UNTAGGED) \ + and service == "Amazon Simple Storage Service" \ + and len(resource_id) != 0: + untagged_resource_by_account[account][resource_id] = self.RESOURCE_SHORTHAND[service] if when == today: service_by_account_today[account][service] += amount service_by_account[account][service] += amount if service == 'Amazon Elastic Compute Cloud': - owner = row['resourceTags/user:Owner'] or '(untagged)' - name = row['resourceTags/user:Name'] or '(untagged)' ec2_by_name_today[name] += amount ec2_by_name[name] += amount ec2_owner_by_account_today[account][owner] += amount @@ -182,8 +195,6 @@ def generate_report(self) -> str: elif when < today: service_by_account[account][service] += amount if service == 'Amazon Elastic Compute Cloud': - owner = row['resourceTags/user:Owner'] or '(untagged)' - name = row['resourceTags/user:Name'] or '(untagged)' ec2_by_name[name] += amount ec2_owner_by_account[account][owner] += amount @@ -194,7 +205,8 @@ def generate_report(self) -> str: ec2_owner_by_account=ec2_owner_by_account, ec2_owner_by_account_today=ec2_owner_by_account_today, ec2_by_name=ec2_by_name, - ec2_by_name_today=ec2_by_name_today + ec2_by_name_today=ec2_by_name_today, + untagged_resource_by_account=untagged_resource_by_account ) diff --git a/templates/aws_report.html b/templates/aws_report.html index ef4b0f2b..d4027fc7 100644 --- a/templates/aws_report.html +++ b/templates/aws_report.html @@ -33,6 +33,25 @@

Totals by account

{% for account_id, services in service_by_account.items()|sort %}

Report for account {{ account_id }}

+ + + + + + + + + + + {% for resource_id, product_type in untagged_resource_by_account[account_id].items()|sort(attribute='1') %} + + + + + {% endfor %} + +
Non-compliant Resource Breakdown
Resource IDProduct Type
{{ resource_id }}{{ product_type }}
+ {% if service_by_account[account_id].get('Amazon Elastic Compute Cloud') %} @@ -63,6 +82,7 @@

Report for account {{ account_id }}


{% endif %}
EC2 Breakdown by Owner
+
Service Summary
Service