tailscale-api/src/bin/ts.rs

76 lines
2.0 KiB
Rust

use chrono::prelude::*;
use structopt::StructOpt;
use tailscale_api::*;
#[derive(StructOpt, Debug)]
struct Opt {
/// The domain associated with your tailscale account.
#[structopt(env = "TAILSCALE_DOMAIN", long)]
domain: String,
/// The tailscale API key as fetched from the admin panel.
#[structopt(env = "TAILSCALE_API_KEY", long, hide_env_values = true)]
api_key: String,
#[structopt(subcommand)]
command: Command,
}
#[derive(StructOpt, Debug)]
enum Command {
/// Prints or modifies the list of domains that Magic DNS uses.
Nameservers { servers: Vec<String> },
/// Prints or modifies the list of DNS search paths that Magic DNS uses.
Searchpaths { domains: Vec<String> },
/// Prints the list of devices in your tailscale network.
Devices,
}
fn main() -> Result {
let opt = Opt::from_args();
//println!("{:?}", opt);
let cli = Client::new(opt.domain, opt.api_key, "Xe/ts".to_string());
use Command::*;
match opt.command {
Nameservers { servers } => match servers.len() {
0 => println!("{:?}", cli.get_nameservers()?),
_ => println!("{:?}", cli.set_nameservers(servers)?),
},
Searchpaths { domains } => match domains.len() {
0 => println!("{:?}", cli.get_search_paths()?),
_ => println!("{:?}", cli.set_search_paths(domains)?),
},
Devices => {
let _ = cli
.devices()?
.devices
.into_iter()
.map(device_row)
.for_each(|dev| println!("{}", dev));
}
}
Ok(())
}
fn device_row(d: Device) -> String {
format!(
"{}, {}, {}, {}, {}",
d.display_node_key,
d.hostname,
d.os,
d.client_version,
{
let delta = Utc::now() - d.last_seen;
format!(
"last seen {} days {} hours {} minutes ago",
delta.num_days(),
delta.num_hours() % 24,
delta.num_minutes() % 60
)
}
)
}