use rustnetconf::transport::ssh::HostKeyVerification;
use rustnetconf::{Client, Datastore};
use std::env;
use std::path::PathBuf;
use std::process;
#[tokio::main]
async fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 4 {
eprintln!(
"Usage: {} <host[:port]> <username> <known_hosts_path> [--password <pass>] [--key <path>]",
args[0]
);
process::exit(1);
}
let host = &args[1];
let username = &args[2];
let known_hosts_path = PathBuf::from(&args[3]);
let mut password: Option<String> = None;
let mut key_file: Option<String> = None;
let mut idx = 4;
while idx < args.len() {
match args[idx].as_str() {
"--password" => {
idx += 1;
password = Some(args.get(idx).expect("--password requires a value").clone());
}
"--key" => {
idx += 1;
key_file = Some(args.get(idx).expect("--key requires a value").clone());
}
other => {
eprintln!("Unknown option: {other}");
process::exit(1);
}
}
idx += 1;
}
let mut builder = Client::connect(host)
.username(username)
.host_key_verification(HostKeyVerification::KnownHosts(known_hosts_path.clone()));
if let Some(ref key) = key_file {
builder = builder.key_file(key);
} else if let Some(ref pass) = password {
builder = builder.password(pass);
} else {
eprintln!("Error: specify --password or --key for authentication");
process::exit(1);
}
eprintln!(
"Connecting to {host} (host key verified against {})",
known_hosts_path.display()
);
let mut client = match builder.connect().await {
Ok(c) => c,
Err(e) => {
eprintln!("Connection failed: {e}");
process::exit(1);
}
};
eprintln!("Host key verified.");
match client.get_config(Datastore::Running).await {
Ok(data) => {
let preview: String = data.chars().take(500).collect();
println!("{preview}");
if data.len() > 500 {
println!("... ({} more chars)", data.len() - 500);
}
}
Err(e) => {
eprintln!("get-config failed: {e}");
client.close_session().await.ok();
process::exit(1);
}
}
client.close_session().await.ok();
}