seamless-glance 1.0.0

Fast, read-only AWS TUI for cloud infrastructure visibility and triage
use async_trait::async_trait;

use crate::{
    aws::clients::AwsClients,
    models::{
        describable::{shell_quote, DescribableResource},
        service_status::ServiceStatus,
    },
};

#[derive(Debug, Clone)]
pub struct RdsSummary {
    pub status: ServiceStatus,
    pub total: usize,
    pub available: usize,
}

#[derive(Debug, Clone)]
pub struct RdsInstanceInfo {
    pub identifier: String,
    pub region: String,
    pub engine: String,
    pub instance_class: String,
    pub status: String,
    pub az: String,
    pub multi_az: bool,
}

impl RdsInstanceInfo {
    pub const PRODUCTION_NAME_HINTS: [&str; 7] = [
        "prod",
        "production",
        "live",
        "critical",
        "primary",
        "main",
        "customer",
    ];

    pub fn is_available(&self) -> bool {
        self.status == "available"
    }

    pub fn has_production_like_identifier(&self) -> bool {
        let normalized = self.identifier.to_ascii_lowercase();
        Self::PRODUCTION_NAME_HINTS
            .iter()
            .any(|hint| normalized.contains(hint))
    }

    pub fn needs_single_az_review(&self) -> bool {
        self.is_available() && !self.multi_az && self.has_production_like_identifier()
    }

    pub fn review_signals(&self) -> Vec<&'static str> {
        let mut signals = Vec::new();

        if !self.multi_az {
            signals.push("single-az");
        }

        if self.has_production_like_identifier() {
            signals.push("prod-name");
        }

        signals
    }
}

#[async_trait]
impl DescribableResource for RdsInstanceInfo {
    fn resource_name(&self) -> String {
        self.identifier.clone()
    }

    fn action_region(&self) -> Option<&str> {
        Some(&self.region)
    }

    async fn describe(&self, clients: &AwsClients) -> anyhow::Result<String> {
        let resp = clients
            .rds
            .describe_db_instances()
            .db_instance_identifier(&self.identifier)
            .send()
            .await?;

        Ok(format!("{:#?}", resp))
    }

    fn console_url(&self, region: &str) -> Option<String> {
        Some(format!(
            "https://{}.console.aws.amazon.com/rds/home?region={}#database:id={}",
            region, region, self.identifier
        ))
    }

    fn cli_command(&self, region: &str) -> Option<String> {
        Some(format!(
            "aws rds describe-db-instances --db-instance-identifier {} --region {}",
            shell_quote(&self.identifier),
            shell_quote(region)
        ))
    }
}