@@ -107,10 +107,11 @@ Resources:
107107 # Mohideen - Added Budgets tag collection module
108108 import os
109109 import json
110+ import re
110111 import logging
111112 import datetime
112113 from json import JSONEncoder
113-
114+
114115 import boto3
115116
116117 BUCKET = os.environ["BUCKET_NAME"]
@@ -128,6 +129,27 @@ Resources:
128129 return o.isoformat()
129130 return None
130131
132+ def clean_value(value):
133+ """Clean string values by replacing special characters with underscores"""
134+ if isinstance(value, str):
135+ return re.sub(r'\W+', '_', value)
136+ elif isinstance(value, list):
137+ return [clean_value(v) for v in value]
138+ return value
139+
140+ def process_cost_filters(budget):
141+ """Process and clean cost filters in budget"""
142+ cost_filters = budget.get('CostFilters', {})
143+ if not cost_filters:
144+ budget['CostFilters'] = {'Filter': ['None']}
145+ return
146+
147+ cleaned_filters = {
148+ re.sub(r'\W+', '_', key): clean_value(value)
149+ for key, value in cost_filters.items()
150+ }
151+ budget['CostFilters'] = cleaned_filters
152+
131153 def assume_role(account_id, service, region):
132154 partition = boto3.session.Session().get_partition_for_region(region_name=region)
133155 cred = boto3.client('sts', region_name=region).assume_role(
@@ -173,9 +195,13 @@ Resources:
173195 'Tags': budget_tags.get('ResourceTags') or []
174196 })
175197 # Fetch CostFilters if available
176- if not budget.get('CostFilters'):
177- budget.update({'CostFilters': {'Filter': ['None']}})
178-
198+ process_cost_filters(budget)
199+ # Add column plannedbudgetslimit as type array
200+ budget_limits = budget.pop('PlannedBudgetLimits', {})
201+ budget['PlannedBudgetLimits_Flat'] = [
202+ {'date': key, 'Amount': value.get('Amount'), 'Unit': value.get('Unit')}
203+ for key, value in budget_limits.items()
204+ ]
179205 f.write(json.dumps(budget, cls=DateTimeEncoder) + "\n")
180206 count += 1
181207 logger.info(f"Budgets collected: {count}")
0 commit comments