use crate::jump::parser::JumpHost;
use crate::ssh::tokio_client::Client;
#[derive(Debug)]
pub struct JumpConnection {
pub client: Client,
pub jump_info: JumpInfo,
}
#[derive(Debug, Clone)]
pub enum JumpInfo {
Direct { host: String, port: u16 },
Jumped {
jump_hosts: Vec<JumpHost>,
destination: String,
destination_port: u16,
},
}
impl JumpInfo {
pub fn path_description(&self) -> String {
match self {
JumpInfo::Direct { host, port } => {
format!("Direct connection to {host}:{port}")
}
JumpInfo::Jumped {
jump_hosts,
destination,
destination_port,
} => {
let jump_chain: Vec<String> = jump_hosts
.iter()
.map(|j| j.to_connection_string())
.collect();
format!(
"Jump path: {} -> {}:{}",
jump_chain.join(" -> "),
destination,
destination_port
)
}
}
}
pub fn destination(&self) -> (&str, u16) {
match self {
JumpInfo::Direct { host, port } => (host, *port),
JumpInfo::Jumped {
destination,
destination_port,
..
} => (destination, *destination_port),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_jump_info_path_description() {
let direct = JumpInfo::Direct {
host: "example.com".to_string(),
port: 22,
};
assert_eq!(
direct.path_description(),
"Direct connection to example.com:22"
);
let jumped = JumpInfo::Jumped {
jump_hosts: vec![
JumpHost::new("jump1".to_string(), Some("user".to_string()), Some(22)),
JumpHost::new("jump2".to_string(), None, Some(2222)),
],
destination: "target.com".to_string(),
destination_port: 22,
};
assert_eq!(
jumped.path_description(),
"Jump path: user@jump1:22 -> jump2:2222 -> target.com:22"
);
}
#[test]
fn test_jump_info_destination() {
let direct = JumpInfo::Direct {
host: "example.com".to_string(),
port: 2222,
};
let (host, port) = direct.destination();
assert_eq!(host, "example.com");
assert_eq!(port, 2222);
let jumped = JumpInfo::Jumped {
jump_hosts: vec![],
destination: "target.com".to_string(),
destination_port: 22,
};
let (host, port) = jumped.destination();
assert_eq!(host, "target.com");
assert_eq!(port, 22);
}
}