use crate::config::CliConfig;
pub async fn set_status(name: &str, status: &str, env: Option<&str>) -> eyre::Result<()> {
let config = CliConfig::load_with_env(env)?;
if let Some(ref env_name) = config.env_name {
println!("Environment: {}", env_name);
}
let client = config.http_client();
let resp = config
.auth_request(
&client,
reqwest::Method::GET,
&format!("{}/api/services", config.api_url),
)
.send()
.await?;
if !resp.status().is_success() {
eyre::bail!("Failed to list services: {}", resp.status());
}
let body: serde_json::Value = resp.json().await?;
let service = body["services"]
.as_array()
.and_then(|arr| arr.iter().find(|s| s["name"].as_str() == Some(name)))
.ok_or_else(|| eyre::eyre!("Service '{}' not found", name))?;
let service_id = service["id"]
.as_str()
.ok_or_else(|| eyre::eyre!("Service has no ID"))?;
let resp = config
.auth_request(
&client,
reqwest::Method::PATCH,
&format!("{}/api/services/{}/status", config.api_url, service_id),
)
.json(&serde_json::json!({ "status": status }))
.send()
.await?;
if resp.status().is_success() {
let action = if status == "active" {
"enabled"
} else {
"disabled"
};
println!("Service '{}' {}.", name, action);
} else {
let status_code = resp.status();
let body = resp.text().await.unwrap_or_default();
eyre::bail!(
"Failed to update service status ({}): {}",
status_code,
body
);
}
Ok(())
}
pub async fn delete(name: &str, yes: bool, env: Option<&str>) -> eyre::Result<()> {
let config = CliConfig::load_with_env(env)?;
if let Some(ref env_name) = config.env_name {
println!("Environment: {}", env_name);
}
let client = config.http_client();
let resp = config
.auth_request(
&client,
reqwest::Method::GET,
&format!("{}/api/services", config.api_url),
)
.send()
.await?;
if !resp.status().is_success() {
eyre::bail!("Failed to list services: {}", resp.status());
}
let body: serde_json::Value = resp.json().await?;
let service = body["services"]
.as_array()
.and_then(|arr| arr.iter().find(|s| s["name"].as_str() == Some(name)))
.ok_or_else(|| eyre::eyre!("Service '{}' not found", name))?;
let service_id = service["id"]
.as_str()
.ok_or_else(|| eyre::eyre!("Service has no ID"))?;
if !yes {
println!(
"This will permanently delete service '{}' and all its configs, deployments, and data.",
name
);
print!("Are you sure? [y/N] ");
use std::io::Write;
std::io::stdout().flush()?;
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
if !input.trim().eq_ignore_ascii_case("y") {
println!("Aborted.");
return Ok(());
}
}
let resp = config
.auth_request(
&client,
reqwest::Method::DELETE,
&format!("{}/api/services/{}", config.api_url, service_id),
)
.send()
.await?;
if resp.status().is_success() {
println!("Service '{}' deleted.", name);
} else {
let status = resp.status();
let body = resp.text().await.unwrap_or_default();
eyre::bail!("Failed to delete service ({}): {}", status, body);
}
Ok(())
}
pub async fn run(env: Option<&str>) -> eyre::Result<()> {
let config = CliConfig::load_with_env(env)?;
if let Some(ref name) = config.env_name {
println!("Environment: {}", name);
}
let client = config.http_client();
let resp = config
.auth_request(
&client,
reqwest::Method::GET,
&format!("{}/api/services", config.api_url),
)
.send()
.await?;
if !resp.status().is_success() {
eyre::bail!("Failed to list services: {}", resp.status());
}
let body: serde_json::Value = resp.json().await?;
let services = body["services"].as_array();
match services {
Some(services) if !services.is_empty() => {
println!(
"{:<30} {:<10} {:<8} {:<10} {:<15} {:<9}",
"NAME", "VERSION", "MODE", "STATUS", "TENANT", "COMMIT"
);
println!("{}", "-".repeat(82));
for svc in services {
let commit = svc["commit_hash"]
.as_str()
.map(|h| if h.len() > 7 { &h[..7] } else { h })
.unwrap_or("-");
println!(
"{:<30} v{:<9} {:<8} {:<10} {:<15} {:<9}",
svc["name"].as_str().unwrap_or("?"),
svc["current_version"],
svc["mode"].as_str().unwrap_or("?"),
svc["status"].as_str().unwrap_or("?"),
svc["tenant_slug"].as_str().unwrap_or("?"),
commit,
);
}
println!("\n{} service(s)", services.len());
}
_ => {
println!("No services deployed yet.");
println!("Use `cufflink deploy` to deploy your first service.");
}
}
Ok(())
}