blob: 487c87843ba73c7518e96ff86559d33b6e9ebae0 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
crate::constants::{SSH_PORT, SSH_PRIV},
crate::target::TargetAddr,
anyhow::{anyhow, Result},
ffx_config::{file, get},
std::process::Command,
};
static DEFAULT_SSH_OPTIONS: &'static [&str] = &[
"-o CheckHostIP=no",
"-o StrictHostKeyChecking=no",
"-o UserKnownHostsFile=/dev/null",
"-o ServerAliveInterval=1",
"-o ServerAliveCountMax=10",
"-o LogLevel=ERROR",
];
pub async fn build_ssh_command(addrs: Vec<TargetAddr>, command: Vec<&str>) -> Result<Command> {
if command.is_empty() {
return Err(anyhow!("missing SSH command"));
}
let port: Option<String> = get(SSH_PORT).await?;
let key: String = file(SSH_PRIV).await?;
let mut c = Command::new("ssh");
if let Some(p) = port {
c.arg("-p").arg(p);
}
c.arg("-i").arg(key);
let addr = addrs.iter().next().ok_or(anyhow!("no IP's for chosen target"))?;
c.args(DEFAULT_SSH_OPTIONS).arg(format!("{}", addr)).args(&command);
return Ok(c);
}
#[cfg(test)]
mod test {
use {
super::build_ssh_command,
crate::target::TargetAddr,
anyhow::Result,
std::net::{IpAddr, Ipv4Addr},
};
#[fuchsia_async::run_singlethreaded(test)]
async fn test_empty_command_vec_produces_error() {
let result = build_ssh_command(Vec::new(), vec![]).await;
assert!(result.is_err(), "empty command vec should produce an error");
}
#[fuchsia_async::run_singlethreaded(test)]
async fn test_no_ips_produces_error() {
let result = build_ssh_command(Vec::new(), vec!["ls"]).await;
assert!(result.is_err(), "target with no IP's should produce an error");
}
#[fuchsia_async::run_singlethreaded(test)]
async fn test_valid_inputs() -> Result<()> {
let key_path = std::env::current_exe().unwrap();
let key_path = key_path.to_str().take().unwrap();
std::env::set_var("FUCHSIA_SSH_PORT", "1234");
std::env::set_var("FUCHSIA_SSH_KEY", key_path);
let ip = IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1));
let mut addrs = Vec::new();
addrs.push(TargetAddr::from((ip, 0)));
let result = build_ssh_command(addrs, vec!["ls"]).await.unwrap();
let dbgstr = format!("{:?}", result);
assert!(dbgstr.contains(&format!("\"-p\" \"1234\" \"-i\" \"{}\"", key_path)), "{}", dbgstr);
assert!(dbgstr.contains(&ip.to_string()), "{}", dbgstr);
Ok(())
}
}