Files
api/lnvps_api/src/ssh_client.rs
Kieran 9296e571ec
All checks were successful
continuous-integration/drone/push Build is passing
refactor: convert to workspace
2025-04-02 13:18:18 +01:00

53 lines
1.4 KiB
Rust

use anyhow::{anyhow, Result};
use log::info;
use ssh2::Channel;
use std::io::Read;
use std::path::{Path, PathBuf};
use tokio::net::{TcpStream, ToSocketAddrs};
pub struct SshClient {
session: ssh2::Session,
}
impl SshClient {
pub fn new() -> Result<SshClient> {
let session = ssh2::Session::new()?;
Ok(SshClient { session })
}
pub async fn connect(
&mut self,
host: impl ToSocketAddrs,
username: &str,
key: &PathBuf,
) -> Result<()> {
let tcp = TcpStream::connect(host).await?;
self.session.set_tcp_stream(tcp);
self.session.handshake()?;
self.session
.userauth_pubkey_file(username, None, key, None)?;
Ok(())
}
pub async fn open_channel(&mut self) -> Result<Channel> {
let channel = self.session.channel_session()?;
Ok(channel)
}
pub fn tunnel_unix_socket(&mut self, remote_path: &Path) -> Result<Channel> {
self.session
.channel_direct_streamlocal(remote_path.to_str().unwrap(), None)
.map_err(|e| anyhow!(e))
}
pub async fn execute(&mut self, command: &str) -> Result<(i32, String)> {
info!("Executing command: {}", command);
let mut channel = self.session.channel_session()?;
channel.exec(command)?;
let mut s = String::new();
channel.read_to_string(&mut s)?;
channel.wait_close()?;
Ok((channel.exit_status()?, s))
}
}