add multi name support and help texts
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 2m4s

This commit is contained in:
bread 2025-04-22 03:06:26 +02:00
parent 824218ad73
commit 948da79c12
4 changed files with 106 additions and 30 deletions

View file

@ -8,4 +8,4 @@ chrono = { version = "0.4.40", features = ["serde"] }
reqwest = { version = "0.12.15", features = ["json"] }
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
tokio = { version = "1.44.2", features = ["macros", "time"] }
tokio = { version = "1.44.2", features = ["macros"] }

View file

@ -10,6 +10,7 @@
let
pkgs = import nixpkgs { inherit system; };
naersk-lib = pkgs.callPackage naersk { };
package_name = "hetzner_dns";
in
{
defaultPackage = naersk-lib.buildPackage ./.;

View file

@ -1,11 +1,9 @@
use crate::*;
use reqwest::{
Client, Method, Request, Url,
header::{HeaderMap, HeaderValue},
header::HeaderValue,
};
use serde::{Serializer, de::Visitor};
use serde_json::Value;
use std::{borrow::Borrow, collections::HashMap};
use std::borrow::Borrow;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RecordType {
@ -108,7 +106,6 @@ impl HetznerDNSAPIClient {
method,
self.host.join(url).map_err(|e| {
println!("url formatting error: {}", e);
()
})?,
);
req.headers_mut().append(
@ -120,11 +117,9 @@ impl HetznerDNSAPIClient {
serde_json::to_string(&payload)
.map_err(|e| {
println!("body encoding error: {}", e);
()
})?
.into(),
);
println!("{:#?}", serde_json::to_string(&payload));
}
let t = self
.client
@ -132,23 +127,19 @@ impl HetznerDNSAPIClient {
.await
.map_err(|e| {
println!("request execution error: {}", e);
()
})?
.error_for_status()
.map_err(|e| {
println!("request error: {}", e);
()
})?
.text()
.await
.map_err(|e| {
println!("request decoding error: {}", e);
()
})?;
Ok(serde_json::from_str::<T>(&t).map_err(|e| {
serde_json::from_str::<T>(&t).map_err(|e| {
println!("json response parsing error: {}", e);
()
})?)
})
}
pub async fn get_zones<'a>(

View file

@ -1,9 +1,7 @@
#![allow(dead_code, unused)]
use crate::client::*;
use crate::models::*;
use core::panic;
use serde::{Deserialize, Serialize};
use std::ops::Sub;
mod client;
mod models;
@ -268,7 +266,7 @@ async fn main() {
.into_iter()
.next()
.unwrap();
let mut records =
let records =
client.get_records(None, None, Some(zone.id)).await.unwrap();
println!("{:#?}", records);
}
@ -287,9 +285,26 @@ async fn main() {
.unwrap()[0]
.id;
ctx.record_context.records[0].zone_id = zone.to_string();
println!("{:#?}", ctx.record_context.records);
if let Ok(record) =
client.create_records(ctx.record_context.records).await
if let Ok(record) = client
.create_records(
ctx.record_context
.records
.into_iter()
.flat_map(|r| {
r.name
.split(",")
.map(|s| RecordPayload {
zone_id: r.zone_id.clone(),
r#type: r.r#type.clone(),
name: String::from(s),
value: r.value.clone(),
ttl: r.ttl,
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>(),
)
.await
{
println!("{:#?}", record);
}
@ -317,10 +332,13 @@ async fn main() {
);
}
for old_record in records {
if let Some(mut new_record) =
records_iter.find(|r| r.name == old_record.name)
{
let mut old_record = old_record;
if let Some(new_record) = records_iter.find(|r| {
r.name == old_record.name
|| r.name
.split(",")
.find(|s| *s == old_record.name)
.is_some()
}) {
updated_records.push((
old_record.id,
RecordPayload {
@ -333,7 +351,7 @@ async fn main() {
));
}
}
if updated_records.len() > 0 {
if !updated_records.is_empty() {
let records = client.update_records(updated_records).await.unwrap();
eprintln!("Updated {} records", records.len());
} else {
@ -354,14 +372,80 @@ async fn main() {
_ => panic!("how in the even"),
}
} else {
panic!("missing token!");
panic!("missing token! set HETZNER_DNS_API_TOKEN or pass --token <token>");
}
} else {
match ctx.mode {
Mode::Zone => println!("zone help"),
Mode::Record => println!("record help"),
Mode::PrimaryServer => println!("primary server help"),
_ => println!("full help"),
Mode::Zone => {
print_general_help();
print_zone_help();
}
Mode::Record => {
print_general_help();
print_zone_help();
}
Mode::PrimaryServer => {
print_general_help();
print_primary_help();
}
_ => {
print_general_help();
print_zone_help();
print_record_help();
print_primary_help();
}
}
}
}
fn print_general_help() {
println!(
"
Usage: hetzner_dns <subject> <action> <options>
Not passing an option will yield this help page.
Subjects:
- z|zones: manage zones/domains
- r|records: manage records for a zone
- p|primary: manage primary servers for a zone
Actions (valid for all subjects):
- g|get
- c|create
- u|update
- d|delete"
);
}
fn print_zone_help() {
println!(
"
Zone options per action:
- g|get [--all] [--zone <zone>]
- c|create [--name <name>] [--ttl <ttl>]
- u|update [--zone <zone>] [--name <name>] [--ttl <ttl>]
- d|delete [--zone <zone>]"
);
}
fn print_record_help() {
println!(
"
Record options per action:
- g|get [--all] [--zone <zone>]
- c|create [--zone <zone>] [--name <name>] [--value <value>] [--ttl <ttl>]
- u|update [--zone <zone>] [--name <name>] [--value <value>] [--ttl <ttl>]
- d|delete [--zone <zone>] [--name <name>]
Create will update existing records and update will create them if nescessary.
--name supports comma separated values to create/update multiple records with same values. (wip)
--ttl is always otpional and defaults to 86400."
);
}
fn print_primary_help() {
println!(
"
Missing implemention for primary servers - consider opening an issue at
https://git.thebread.dev/thebreadcompany/hetzner_dns/issues
if this feature is relevant for you!"
);
}