use std::net::SocketAddr;
use clap::{Parser, Subcommand};
use miette::Result;
use serde_json::Value;
use super::names::{ask, joined, list, tell, text};
use crate::actions::Context;
#[derive(Debug, Clone, Parser)]
#[clap(verbatim_doc_comment)]
pub struct DnsArgs {
#[command(subcommand)]
command: Option<Command>,
#[arg(long, global = true)]
server_addr: Vec<SocketAddr>,
#[arg(long, global = true)]
json: bool,
}
#[derive(Debug, Clone, Subcommand)]
enum Command {
Show,
Register {
name: String,
#[arg(required = true)]
addresses: Vec<std::net::IpAddr>,
},
Withdraw {
name: String,
},
}
pub async fn run(args: DnsArgs, _ctx: Context) -> Result<()> {
let (endpoint, query) = match args.command.clone().unwrap_or(Command::Show) {
Command::Show => ("status", Vec::new()),
Command::Withdraw { name } => ("dns-withdraw", vec![("name", name)]),
Command::Register { name, addresses } => (
"dns-register",
vec![
("name", name),
(
"addresses",
addresses
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(","),
),
],
),
};
let answer = if endpoint == "status" {
ask(&args.server_addr, endpoint, &query).await?
} else {
tell(&args.server_addr, endpoint, &query).await?
};
if args.json {
println!(
"{}",
serde_json::to_string_pretty(&answer).unwrap_or_default()
);
return Ok(());
}
match endpoint {
"status" => show(&answer),
_ => registered(&answer),
}
Ok(())
}
fn show(answer: &Value) {
println!(
"DNS grant: {}",
if answer["dnsEntitled"].as_bool().unwrap_or(false) {
"held"
} else {
"not held"
}
);
println!("Domains: {}", joined(answer, "domains"));
let names: Vec<String> = answer["registeredNames"]
.as_array()
.map(|rows| rows.iter().filter_map(Value::as_str).map(str::to_owned).collect())
.unwrap_or_default();
list("Names registered", &names);
}
fn registered(answer: &Value) {
println!("{}", text(answer, "name"));
println!(" will publish: {}", joined(answer, "addresses"));
println!(" published: {}", joined(answer, "publishedAddresses"));
println!(
" zone caught up: {}",
if answer["published"].as_bool().unwrap_or(false) {
"yes"
} else {
"not yet"
}
);
if let Some(err) = answer["lastError"].as_str() {
println!(" last publish failed: {err}");
}
}