seamless-glance 1.0.0

Fast, read-only AWS TUI for cloud infrastructure visibility and triage
use crate::app::App;
use crate::aws::apigateway;
use crate::aws::{cloudwatch, ec2, ecs, lambda, rds, secrets, sqs, target_group, vpc};
use crate::models::AccountOverview;
use tokio::join;

pub struct IdentityInfo {
    pub kind: String,
    pub name: String,
}

fn parse_identity_from_arn(arn: &str) -> IdentityInfo {
    if arn.contains(":assumed-role/") {
        let parts: Vec<&str> = arn.split(":assumed-role/").collect();
        let role_part = parts.get(1).unwrap_or(&"unknown/unknown");
        let role_name = role_part.split('/').next().unwrap_or("unknown");

        IdentityInfo {
            kind: "Assumed Role".into(),
            name: role_name.into(),
        }
    } else if arn.contains(":user/") {
        let user_name = arn.split(":user/").last().unwrap_or("unknown");
        IdentityInfo {
            kind: "IAM User".into(),
            name: user_name.into(),
        }
    } else if arn.ends_with(":root") {
        IdentityInfo {
            kind: "Root".into(),
            name: "root".into(),
        }
    } else {
        IdentityInfo {
            kind: "Unknown".into(),
            name: arn.to_string(),
        }
    }
}

pub async fn fetch_account_overview(app: &App) -> AccountOverview {
    let ident = app.aws.sts.get_caller_identity().send().await.unwrap();
    let arn = ident.arn().unwrap_or("");
    let identity = parse_identity_from_arn(arn);

    let (
        ecs_clusters,
        ec2_counts,
        rds_result,
        lambda_result,
        apigw_result,
        sqs_result,
        vpc_result,
        alarms,
        secrets,
        target_groups,
    ) = join!(
        ecs::fetch_ecs_clusters(app),
        ec2::fetch_ec2_counts(app),
        rds::fetch_rds(app),
        lambda::fetch_lambda_summary(app),
        apigateway::fetch_apigateway_summary(app),
        sqs::fetch_sqs_summary(app),
        vpc::fetch_vpc_summary(app),
        cloudwatch::fetch_cloudwatch(app),
        secrets::fetch_secrets(app),
        target_group::fetch_target_groups(app)
    );

    let ecs_clusters_count = ecs_clusters.len() as u32;
    let ecs_services_count: u32 = ecs_clusters.iter().map(|c| c.active_services as u32).sum();

    let unhealthy = target_groups
        .iter()
        .filter(|tg| tg.unhealthy_targets > 0)
        .count();

    AccountOverview {
        account_id: ident.account().unwrap_or("unknown").to_string(),
        identity_kind: identity.kind,
        identity_name: identity.name,
        region: app.current_region_label().to_string(),
        role_name: ident
            .arn()
            .and_then(|arn| arn.split(":assumed-role/").nth(1))
            .and_then(|s| s.split('/').next())
            .map(|s| s.to_string()),

        ec2_running: ec2_counts.running,
        ec2_stopped: ec2_counts.stopped,

        ecs_clusters: ecs_clusters_count,
        ecs_services: ecs_services_count,

        rds_status: rds_result.0,
        lambda_functions: lambda_result.function_count,
        lambda_status: lambda_result.status,

        apigw_rest_apis: apigw_result.rest_count,
        apigw_http_apis: apigw_result.http_count,
        apigw_status: apigw_result.status,

        sqs_queues: sqs_result.queue_count,
        sqs_dlqs: sqs_result.dlq_count,
        sqs_status: sqs_result.status,

        vpc_count: vpc_result.vpc_count,
        subnet_count: vpc_result.subnet_count,
        vpc_status: vpc_result.status,
        alarms: alarms.0,
        secrets: secrets.0,

        target_groups_total: target_groups.len(),
        target_groups_unhealthy: unhealthy,
    }
}