mod client;
pub use client::*;
use crate::error::{Error, Result};
use crate::project::{self, Project};
use crate::server::{self, Server};
#[derive(Default)]
pub struct SshResolveArgs {
pub id: Option<String>,
pub project: Option<String>,
pub server: Option<String>,
}
#[derive(Debug)]
pub struct SshResolveResult {
pub resolved_type: String,
pub project_id: Option<String>,
pub server_id: String,
pub server: Server,
pub base_path: Option<String>,
}
pub fn resolve_context(args: &SshResolveArgs) -> Result<SshResolveResult> {
if args.id.is_none() && args.project.is_none() && args.server.is_none() {
return Err(Error::validation_missing_argument(vec![
"<id>".to_string(),
"--project".to_string(),
"--server".to_string(),
]));
}
let (resolved_type, project_id, server_id, server, base_path) = resolve_internal(args)?;
if !server.is_valid() {
let mut missing = Vec::new();
if server.host.is_empty() {
missing.push("host".to_string());
}
if server.user.is_empty() {
missing.push("user".to_string());
}
return Err(Error::ssh_server_invalid(server_id, missing));
}
Ok(SshResolveResult {
resolved_type,
project_id,
server_id,
server,
base_path,
})
}
fn resolve_internal(
args: &SshResolveArgs,
) -> Result<(String, Option<String>, String, Server, Option<String>)> {
if let Some(project_id) = &args.project {
let project = project::load(project_id)?;
let base_path = project.base_path.clone();
let (server_id, server) = resolve_from_project(&project)?;
return Ok((
"project".to_string(),
Some(project.id),
server_id,
server,
base_path,
));
}
if let Some(server_id) = &args.server {
let server = server::load(server_id)?;
return Ok(("server".to_string(), None, server_id.clone(), server, None));
}
let id = args.id.as_ref().unwrap();
if let Ok(project) = project::load(id) {
let base_path = project.base_path.clone();
let (server_id, server) = resolve_from_project(&project)?;
return Ok((
"project".to_string(),
Some(project.id),
server_id,
server,
base_path,
));
}
if let Ok(server) = server::load(id) {
return Ok(("server".to_string(), None, id.clone(), server, None));
}
Err(Error::validation_invalid_argument(
"id",
"No matching project or server",
Some(id.clone()),
Some(vec!["project".to_string(), "server".to_string()]),
))
}
fn resolve_from_project(project: &Project) -> Result<(String, Server)> {
let server_id = project.server_id.clone().ok_or_else(|| {
Error::validation_invalid_argument(
"project.server_id",
"Server not configured for project",
None,
None,
)
})?;
let server = server::load(&server_id)?;
Ok((server_id, server))
}