use anyhow::{bail, Result};
use owo_colors::OwoColorize;
use crate::api::client::ApiClient;
use crate::api::models::SettingsPatch;
use crate::render::theme;
pub async fn capacity(client: &ApiClient) -> Result<()> {
let capacity = client.capacity().await?;
println!();
println!(
" {} de {} MB libres {}",
capacity.available_memory_mb.style(theme::strong()),
capacity.total_memory_mb,
format!(
"({} para el sistema, {} comprometidos)",
capacity.reserved_memory_mb, capacity.committed_memory_mb
)
.style(theme::muted()),
);
println!(
" caben {} servicios más a 512 MB",
capacity.remaining_at_default_size.style(theme::strong()),
);
println!(
" {}",
format!(
"puertos {} de {}",
capacity.ports_in_use, capacity.ports_total
)
.style(theme::muted()),
);
if capacity.running_low {
println!();
println!(
" {} Queda poco sitio en esta máquina.",
theme::PENDING.style(theme::warning()),
);
}
println!();
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub async fn set_settings(
client: &ApiClient,
project_reference: &str,
service_reference: &str,
patch: SettingsPatch,
) -> Result<()> {
let project = client.find_project(project_reference).await?;
let service = client.find_service(&project.id, service_reference).await?;
client.update_settings(&service.id, &patch).await?;
println!(
" {} Ajustes de {} guardados",
theme::CHECK.style(theme::success()),
service.name.style(theme::strong()),
);
println!(
" {}",
"El próximo despliegue los recoge; el contenedor actual no.".style(theme::muted()),
);
Ok(())
}
pub async fn encryption(
client: &ApiClient,
project_reference: &str,
service_reference: &str,
enabled: bool,
) -> Result<()> {
let project = client.find_project(project_reference).await?;
let service = client.find_service(&project.id, service_reference).await?;
println!(
" {}",
if enabled {
"Cifrando… se reescribe lo que ya está guardado.".style(theme::muted())
} else {
"Quitando el cifrado por defecto…".style(theme::muted())
}
);
let outcome = client.set_encryption(&service.id, enabled).await?;
if !outcome.enabled {
println!(
" {} Cifrado desactivado para lo nuevo en {} bucket(s)",
theme::CHECK.style(theme::success()),
outcome.buckets.len(),
);
return Ok(());
}
println!(
" {} Cifrado activado en {} bucket(s), {} objeto(s) reescrito(s)",
theme::CHECK.style(theme::success()),
outcome.buckets.len(),
outcome.re_encrypted,
);
println!(
" {}",
"La clave vive en el llavero de la plataforma. Si se pierde, los objetos no se recuperan."
.style(theme::muted()),
);
Ok(())
}
pub async fn expose(
client: &ApiClient,
project_reference: &str,
service_reference: &str,
public: bool,
) -> Result<()> {
let project = client.find_project(project_reference).await?;
let service = client.find_service(&project.id, service_reference).await?;
let outcome = client.set_public_access(&service.id, public).await?;
if !public {
println!(
" {} {} sale de internet",
theme::CHECK.style(theme::success()),
service.name.style(theme::strong()),
);
println!(
" {}",
"Sus dominios quedan apagados y sus registros DNS borrados. Los demás servicios del \
proyecto lo siguen alcanzando por su nombre."
.style(theme::muted()),
);
return Ok(());
}
println!(
" {} {} vuelve a ser público",
theme::CHECK.style(theme::success()),
service.name.style(theme::strong()),
);
let serving: Vec<_> = outcome
.domains
.iter()
.filter(|domain| domain.enabled)
.collect();
if serving.is_empty() {
println!(
" {}",
"Todavía sin dominio. Dale uno con `fundaia domains add`.".style(theme::muted()),
);
} else {
for domain in serving {
println!(" https://{}", domain.host);
}
}
Ok(())
}
pub async fn delete(
client: &ApiClient,
project_reference: &str,
service_reference: &str,
confirmation: Option<&str>,
) -> Result<()> {
let project = client.find_project(project_reference).await?;
let service = client.find_service(&project.id, service_reference).await?;
if confirmation != Some(service.name.as_str()) {
bail!(
"escribe `--confirm {}` para eliminarlo: se van sus despliegues, dominios y variables",
service.name
);
}
client.delete_service(&service.service_id).await?;
println!(
" {} {} eliminado",
theme::CHECK.style(theme::success()),
service.name.style(theme::strong()),
);
Ok(())
}
pub async fn rename_project(
client: &ApiClient,
project_reference: &str,
name: Option<&str>,
description: Option<&str>,
) -> Result<()> {
if name.is_none() && description.is_none() {
bail!("no has pedido ningún cambio: pasa un nombre o `--description`");
}
let project = client.find_project(project_reference).await?;
client
.rename_project(&project.id, name, description)
.await?;
println!(
" {} {} {} {}",
theme::CHECK.style(theme::success()),
project.name.style(theme::muted()),
theme::ARROW,
name.unwrap_or(&project.name).style(theme::strong()),
);
Ok(())
}
pub async fn archive_project(
client: &ApiClient,
project_reference: &str,
confirmation: Option<&str>,
) -> Result<()> {
let project = client.find_project(project_reference).await?;
if confirmation != Some(project.name.as_str()) && confirmation != Some(project.slug.as_str()) {
bail!(
"archivar `{}` borra sus servicios: repite el nombre con --confirm {}",
project.name,
project.slug,
);
}
client.archive_project(&project.id).await?;
println!(
" {} {} archivado",
theme::CHECK.style(theme::success()),
project.name.style(theme::strong()),
);
Ok(())
}
pub async fn move_project(
client: &ApiClient,
project_reference: &str,
workspace_reference: &str,
) -> Result<()> {
let project = client.find_project(project_reference).await?;
let workspace = client.find_workspace(Some(workspace_reference)).await?;
client.move_project(&project.id, &workspace.id).await?;
println!(
" {} {} {} {}",
theme::CHECK.style(theme::success()),
project.name.style(theme::strong()),
theme::ARROW,
workspace.name.style(theme::strong()),
);
println!(
" {}",
"Todo el que comparte ese espacio lo ve.".style(theme::muted()),
);
Ok(())
}
pub async fn disconnect(
client: &ApiClient,
project_reference: &str,
service_reference: &str,
provider_reference: &str,
) -> Result<()> {
let project = client.find_project(project_reference).await?;
let consumer = client.find_service(&project.id, service_reference).await?;
let provider = client.find_service(&project.id, provider_reference).await?;
let removed = client.disconnect(&consumer.id, &provider.id).await?;
println!(
" {} {} ya no lee nada de {}",
theme::CHECK.style(theme::success()),
consumer.name.style(theme::strong()),
provider.name.style(theme::strong()),
);
println!(
" {}",
format!("{removed} variables retiradas").style(theme::muted()),
);
println!(
" {}",
"Despliega el consumidor para que deje de recibirlas.".style(theme::muted()),
);
Ok(())
}
pub async fn detach_volume(client: &ApiClient, volume_id: &str) -> Result<()> {
client.detach_volume(volume_id).await?;
println!(
" {} volumen {} retirado",
theme::CHECK.style(theme::success()),
volume_id.style(theme::strong()),
);
Ok(())
}