Skip to content

Commit

Permalink
add full report to completion
Browse files Browse the repository at this point in the history
  • Loading branch information
badra001 committed Jul 17, 2026
1 parent a1856a7 commit e559dd2
Showing 1 changed file with 63 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import getpass
import smtplib
from datetime import datetime, timezone
from email.message import EmailMessage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from collections import defaultdict
from concurrent.futures import ThreadPoolExecutor

Expand All @@ -21,27 +25,42 @@ from rich.table import Table
from rich.progress import Progress, BarColumn, TextColumn, TimeElapsedColumn, SpinnerColumn

# --- VERSIONING ---
__version__ = "2.7.0"
__version__ = "2.8.0"

console = Console()

def dispatch_progress_email(recipient_email, subject_str, body_str):
"""Dispatches a plain-text status tracking email via localhost SMTP."""
def dispatch_progress_email(recipient_email, subject_str, body_str, attachment_paths=None):
"""Dispatches a plain-text or multipart status tracking email via localhost SMTP."""
try:
sender_user = getpass.getuser()
sender_host = "localhost"
sender_address = f"{sender_user}@{sender_host}"

msg = EmailMessage()
msg.set_content(body_str)
msg["Subject"] = subject_str
msg["From"] = sender_address
msg["To"] = recipient_email
if attachment_paths:
msg = MIMEMultipart()
msg["Subject"] = subject_str
msg["From"] = sender_address
msg["To"] = recipient_email
msg.attach(MIMEText(body_str, "plain"))

for path in attachment_paths:
if os.path.exists(path):
part = MIMEBase("application", "octet-stream")
with open(path, "rb") as f:
part.set_payload(f.read())
encoders.encode_base64(part)
part.add_header("Content-Disposition", f'attachment; filename="{os.path.basename(path)}"')
msg.attach(part)
else:
msg = EmailMessage()
msg.set_content(body_str)
msg["Subject"] = subject_str
msg["From"] = sender_address
msg["To"] = recipient_email

with smtplib.SMTP("localhost", 25) as server:
server.send_message(msg)
except Exception as email_err:
# Fail gracefully to keep terminal execution threads uninterrupted
console.print(f"[bold yellow]Warning: Notification pipeline failed to dispatch email: {email_err}[/bold yellow]")

def build_assumed_role_session(target_account_id, role_name, region_name, profile=None):
Expand Down Expand Up @@ -288,7 +307,6 @@ def main():
active_lane_allocations = {i: None for i in range(args.workers)}
futures_map = {}

# Milestone notification variables setup
completed_counter = 0
next_email_milestone_pct = 10

Expand Down Expand Up @@ -330,7 +348,6 @@ def main():
completed_futures = [f for f in futures_map if f.done()]
for fut in completed_futures:
meta = futures_map.pop(fut)

assigned_lane = next(k for k, v in active_lane_allocations.items() if v == fut)
active_lane_allocations[assigned_lane] = None

Expand All @@ -351,7 +368,6 @@ def main():
overall_progress.update(macro_task_id, advance=1)
lane_progress.update(lane_task_ids[assigned_lane], bucket_name="IDLE", completed=0, current_test="IDLE", total_tests="0")

# --- REFRESH EMAIL NOTIFICATION PIPELINE SNAPSHOT CHECKS ---
if args.notification and completed_counter < total_targets_count:
current_macro_pct = int((completed_counter / total_targets_count) * 100)
if current_macro_pct >= next_email_milestone_pct:
Expand All @@ -376,20 +392,6 @@ def main():
global_end_timestamp = datetime.now(timezone.utc).strftime(time_format)[:-3] + "Z"
global_total_elapsed = round(global_end_epoch - global_start_epoch, 3)

# --- DISPATCH COMPLETION EMAIL SNAPSHOT REPORT ---
if args.notification:
sub_msg = f"purge progress 100% bucket {total_targets_count} of {total_targets_count}"
body_msg = (
f"AWS ORGANIZATIONAL S3 METRICS STORAGE PURGE LIFECYCLE PROGRESS REPORT\n"
f"======================================================================\n"
f"Current Status : CONCLUSION (All Operations Executed Safely)\n"
f"Progress Percentage : 100%\n"
f"Total Buckets Managed : {total_targets_count} of {total_targets_count}\n"
f"Total Elapsed Duration: {global_total_elapsed:.2f} seconds\n"
f"Dry Run Active Status : {dry_run}\n"
)
dispatch_progress_email(args.notification, sub_msg, body_msg)

if args.output != "." and not os.path.exists(args.output):
os.makedirs(args.output, exist_ok=True)

Expand Down Expand Up @@ -431,6 +433,41 @@ def main():
with open(json_out_path, "w", encoding="utf-8") as jf:
json.dump(json_telemetry_payload, jf, indent=2)

# --- GENERATE SUMMARY TEXT TABLE FOR EMAIL BODY ---
table_header = f"| {'Account ID':<12} | {'Account Name':<20} | {'Bucket Name':<35} | {'Region':<12} | {detected_size_unit_label:<12} | {'Objects':<10} | {'Elapsed (s)':<12} | {'Errors':<6} |\n"
table_divider = f"|{'-'*14}|{'-'*22}|{'-'*37}|{'-'*14}|{'-'*14}|{'-'*12}|{'-'*14}|{'-'*8}|\n"
table_body = ""

for r in operation_tracking_results:
acct_id_trunc = r["account_id"]
acct_name_trunc = r["account_name"][:18] + ".." if len(r["account_name"]) > 20 else r["account_name"]
bucket_trunc = r["bucket_name"][:32] + ".." if len(r["bucket_name"]) > 35 else r["bucket_name"]
region_str = r["region"]
size_str = f"{r['source_size']:.4f}"
objects_str = f"{r['object_count']:,}"
elapsed_str = f"{r['elapsed_time_seconds']:.3f}"
errors_str = str(r["error_count"])

table_body += f"| {acct_id_trunc:<12} | {acct_name_trunc:<20} | {bucket_trunc:<35} | {region_str:<12} | {size_str:<12} | {objects_str:<10} | {elapsed_str:<12} | {errors_str:<6} |\n"

ascii_summary_table = table_header + table_divider + table_body

# --- DISPATCH COMPLETION EMAIL SNAPSHOT REPORT WITH LOG ATTACHMENTS ---
if args.notification:
sub_msg = f"purge progress 100% bucket {total_targets_count} of {total_targets_count}"
body_msg = (
f"AWS ORGANIZATIONAL S3 METRICS STORAGE PURGE LIFECYCLE PROGRESS REPORT\n"
f"======================================================================\n"
f"Current Status : CONCLUSION (All Operations Executed Safely)\n"
f"Progress Percentage : 100%\n"
f"Total Buckets Managed : {total_targets_count} of {total_targets_count}\n"
f"Total Elapsed Duration: {global_total_elapsed:.2f} seconds\n"
f"Dry Run Active Status : {dry_run}\n\n"
f"EXECUTION SUMMARY TABLE:\n"
f"{ascii_summary_table}"
)
dispatch_progress_email(args.notification, sub_msg, body_msg, attachment_paths=[csv_out_path, json_out_path])

console.print(f"\n[bold blue]======================================================================[/bold blue]")
console.print(f"[*] PURGE SEQUENCE LIFECYCLE CONCLUDED | Total Run Time: {global_total_elapsed:.2f}s")
console.print(f"[bold blue]======================================================================[/bold blue]")
Expand Down

0 comments on commit e559dd2

Please sign in to comment.