fundaia 0.55.0

Command line for the Fundaia deployment platform: projects, services, variables, deployments, logs and metrics
use anyhow::Result;

use crate::api::client::ApiClient;
use crate::api::models::{ReplicaContainer, ReplicaSet};
use crate::output::Format;
use crate::render::sanitise;
use crate::render::table::{Cell, Table};
use crate::render::theme;

pub async fn list(
    client: &ApiClient,
    project_reference: &str,
    service_reference: &str,
    format: Format,
) -> Result<()> {
    let (project, service) = client.locate(project_reference, service_reference).await?;
    let answer = client.replicas(&service.id).await?;

    if format.answered_in_json(&answer.raw) {
        return Ok(());
    }

    println!("{}", summary(&answer.body));
    let mut table = Table::new(&["#", "servidor", "puerto", "estado", "contenedor"]);
    for replica in &answer.body.replicas {
        table.push(vec![
            Cell::styled(format!("{}", replica.ordinal + 1), theme::muted()),
            Cell::styled(sanitise::plain(&replica.server.name), theme::strong()),
            Cell::plain(format!("{}:{}", replica.host, replica.port)),
            Cell::styled(state_word(replica), theme::muted()),
            Cell::styled(sanitise::plain(&replica.container), theme::muted()),
        ]);
    }

    table.print_or(format_args!(
        "`{}` no está desplegado. fundaia deploy {} {}",
        service.name, project.slug, service.slug
    ));
    Ok(())
}

fn summary(set: &ReplicaSet) -> String {
    let spread = if set.spread {
        ", repartidas entre servidores"
    } else {
        ""
    };
    format!(
        "{} de {} en marcha{}",
        set.running,
        set.requested.max(1),
        spread
    )
}

fn state_word(replica: &ReplicaContainer) -> &'static str {
    match replica.state.as_str() {
        "running" => "en marcha",
        "stopped" => "parado",
        "missing" => "no existe",
        _ => "sin respuesta del servidor",
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::api::models::ReplicaServer;

    fn replica(state: &str) -> ReplicaContainer {
        ReplicaContainer {
            ordinal: 1,
            container: "infra-tienda-web-7-r1".to_string(),
            server: ReplicaServer {
                id: "local".to_string(),
                name: "principal".to_string(),
            },
            host: "127.0.0.1".to_string(),
            port: 34002,
            state: state.to_string(),
        }
    }

    #[test]
    fn says_how_many_run_of_how_many_were_asked() {
        let set = ReplicaSet {
            requested: 3,
            spread: false,
            running: 2,
            replicas: vec![],
        };
        assert_eq!(summary(&set), "2 de 3 en marcha");
    }

    #[test]
    fn says_when_the_replicas_spread_over_servers() {
        let set = ReplicaSet {
            requested: 2,
            spread: true,
            running: 2,
            replicas: vec![],
        };
        assert_eq!(
            summary(&set),
            "2 de 2 en marcha, repartidas entre servidores"
        );
    }

    #[test]
    fn names_a_replica_on_a_server_that_does_not_answer() {
        assert_eq!(
            state_word(&replica("unknown")),
            "sin respuesta del servidor"
        );
    }
}