-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
84 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| #!/bin/env python | ||
|
|
||
| import csv | ||
| import argparse | ||
| import sys | ||
|
|
||
| __version__ = "1.0.2" | ||
|
|
||
| def load_csv_to_dict(filename): | ||
| data = {} | ||
| try: | ||
| with open(filename, mode='r') as f: | ||
| reader = csv.DictReader(f) | ||
| for row in reader: | ||
| service = row['Service'] | ||
| if service == 'GRAND TOTAL': | ||
| continue | ||
| # Extract usage and amortized cost | ||
| data[service] = { | ||
| 'usage': float(row['Usage Quantity']), | ||
| 'cost': float(row['Total (Amortized)']) | ||
| } | ||
| return data | ||
| except Exception as e: | ||
| print(f"❌ Error reading {filename}: {e}") | ||
| sys.exit(1) | ||
|
|
||
| def compare_costs(file1, file2): | ||
| old_data = load_csv_to_dict(file1) | ||
| new_data = load_csv_to_dict(file2) | ||
|
|
||
| all_services = set(old_data.keys()).union(set(new_data.keys())) | ||
| comparison_rows = [] | ||
| total_cost_change = 0.0 | ||
|
|
||
| for svc in all_services: | ||
| old = old_data.get(svc, {'usage': 0.0, 'cost': 0.0}) | ||
| new = new_data.get(svc, {'usage': 0.0, 'cost': 0.0}) | ||
|
|
||
| usage_diff = new['usage'] - old['usage'] | ||
| cost_diff = new['cost'] - old['cost'] | ||
|
|
||
| # Exclude Private Offers from the total calculation logic | ||
| if "Private Offer" not in svc: | ||
| total_cost_change += cost_diff | ||
|
|
||
| comparison_rows.append({ | ||
| 'Service': svc, | ||
| 'Usage Change': usage_diff, | ||
| 'Cost Change': cost_diff | ||
| }) | ||
|
|
||
| # Sort: Largest savings (most negative) at the top, highest increases at the bottom | ||
| comparison_rows.sort(key=lambda x: x['Cost Change'], reverse=False) | ||
|
|
||
| output_file = "cost_comparison.csv" | ||
| print(f"--- AWS Cost Comparison v{__version__} ---") | ||
| print(f"Savings (negative) appear first; increases appear last.") | ||
| print(f"Note: 'Private Offer' services excluded from grand total calculation.\n") | ||
|
|
||
| with open(output_file, 'w', newline='') as f: | ||
| writer = csv.writer(f) | ||
| writer.writerow(['Service', 'Usage Change', 'Cost Change']) | ||
|
|
||
| for row in comparison_rows: | ||
| writer.writerow([ | ||
| row['Service'], | ||
| f"{row['Usage Change']:.2f}", | ||
| f"{row['Cost Change']:.2f}" | ||
| ]) | ||
|
|
||
| # Grand Total line | ||
| writer.writerow(['TOTAL', 'NA', f"{total_cost_change:.2f}"]) | ||
|
|
||
| print(f"✅ Comparison saved to {output_file}") | ||
| print(f"Filtered Net Change: ${total_cost_change:.2f}") | ||
|
|
||
| if __name__ == "__main__": | ||
| parser = argparse.ArgumentParser(description="Compare two AWS Cost CSVs (v1.0.2)") | ||
| parser.add_argument('old_file', help="Baseline CSV") | ||
| parser.add_argument('new_file', help="Comparison CSV") | ||
| parser.add_argument('--version', action='version', version=f'%(prog)s {__version__}') | ||
| args = parser.parse_args() | ||
| compare_costs(args.old_file, args.new_file) |