#![allow(dead_code)]
use crate::cli::{DbCommands, OutputFormat};
use crate::connection::ConnectionManager;
use crate::error::RedisCtlError;
use redisctl_core::DeploymentType;
use std::process::Command;
use tracing::debug;
pub async fn handle_db_command(
db_cmd: &DbCommands,
conn_mgr: &ConnectionManager,
_output: OutputFormat,
) -> Result<(), RedisCtlError> {
match db_cmd {
DbCommands::Open {
profile,
dry_run,
redis_cli,
args,
} => handle_open(conn_mgr, profile, *dry_run, redis_cli, args).await,
}
}
async fn handle_open(
conn_mgr: &ConnectionManager,
profile_name: &str,
dry_run: bool,
redis_cli_path: &str,
extra_args: &[String],
) -> Result<(), RedisCtlError> {
let profile = conn_mgr.config.profiles.get(profile_name).ok_or_else(|| {
RedisCtlError::Configuration(format!("Profile '{}' not found", profile_name))
})?;
if profile.deployment_type != DeploymentType::Database {
return Err(RedisCtlError::Configuration(format!(
"Profile '{}' is not a database profile (type: {})",
profile_name, profile.deployment_type
)));
}
let (host, port, password, tls, username, _database) = profile
.resolve_database_credentials()
.map_err(|e| RedisCtlError::Configuration(format!("Failed to resolve credentials: {}", e)))?
.ok_or_else(|| {
RedisCtlError::Configuration(format!(
"Profile '{}' has no database credentials",
profile_name
))
})?;
let mut cli_args = vec![
"-h".to_string(),
host.clone(),
"-p".to_string(),
port.to_string(),
];
if username != "default" {
cli_args.push("--user".to_string());
cli_args.push(username.clone());
}
if let Some(ref pwd) = password {
cli_args.push("-a".to_string());
cli_args.push(pwd.clone());
}
if tls {
cli_args.push("--tls".to_string());
}
cli_args.extend(extra_args.iter().cloned());
debug!(
"redis-cli args (password redacted): {:?}",
cli_args
.iter()
.enumerate()
.map(|(i, arg)| {
if i > 0 && cli_args[i - 1] == "-a" {
"***".to_string()
} else {
arg.clone()
}
})
.collect::<Vec<_>>()
);
if dry_run {
let display_args: Vec<String> = cli_args
.iter()
.enumerate()
.map(|(i, arg)| {
if i > 0 && cli_args[i - 1] == "-a" {
"***".to_string()
} else {
if arg.contains(' ') {
format!("\"{}\"", arg)
} else {
arg.clone()
}
}
})
.collect();
println!("{} {}", redis_cli_path, display_args.join(" "));
return Ok(());
}
if which::which(redis_cli_path).is_err() {
return Err(RedisCtlError::Configuration(format!(
"redis-cli not found at '{}'. Install Redis or specify --redis-cli path",
redis_cli_path
)));
}
#[cfg(unix)]
{
use std::os::unix::process::CommandExt;
let mut cmd = Command::new(redis_cli_path);
cmd.args(&cli_args);
let err = cmd.exec();
Err(RedisCtlError::Configuration(format!(
"Failed to exec redis-cli: {}",
err
)))
}
#[cfg(not(unix))]
{
let status = Command::new(redis_cli_path)
.args(&cli_args)
.status()
.map_err(|e| {
RedisCtlError::Configuration(format!("Failed to spawn redis-cli: {}", e))
})?;
if !status.success() {
return Err(RedisCtlError::Configuration(format!(
"redis-cli exited with status: {}",
status
)));
}
Ok(())
}
}