add multi name support and help texts
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 2m4s
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 2m4s
This commit is contained in:
parent
824218ad73
commit
948da79c12
4 changed files with 106 additions and 30 deletions
|
@ -8,4 +8,4 @@ chrono = { version = "0.4.40", features = ["serde"] }
|
||||||
reqwest = { version = "0.12.15", features = ["json"] }
|
reqwest = { version = "0.12.15", features = ["json"] }
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
serde_json = "1.0.140"
|
serde_json = "1.0.140"
|
||||||
tokio = { version = "1.44.2", features = ["macros", "time"] }
|
tokio = { version = "1.44.2", features = ["macros"] }
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
naersk-lib = pkgs.callPackage naersk { };
|
naersk-lib = pkgs.callPackage naersk { };
|
||||||
|
package_name = "hetzner_dns";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
defaultPackage = naersk-lib.buildPackage ./.;
|
defaultPackage = naersk-lib.buildPackage ./.;
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use reqwest::{
|
use reqwest::{
|
||||||
Client, Method, Request, Url,
|
Client, Method, Request, Url,
|
||||||
header::{HeaderMap, HeaderValue},
|
header::HeaderValue,
|
||||||
};
|
};
|
||||||
use serde::{Serializer, de::Visitor};
|
use std::borrow::Borrow;
|
||||||
use serde_json::Value;
|
|
||||||
use std::{borrow::Borrow, collections::HashMap};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum RecordType {
|
pub enum RecordType {
|
||||||
|
@ -108,7 +106,6 @@ impl HetznerDNSAPIClient {
|
||||||
method,
|
method,
|
||||||
self.host.join(url).map_err(|e| {
|
self.host.join(url).map_err(|e| {
|
||||||
println!("url formatting error: {}", e);
|
println!("url formatting error: {}", e);
|
||||||
()
|
|
||||||
})?,
|
})?,
|
||||||
);
|
);
|
||||||
req.headers_mut().append(
|
req.headers_mut().append(
|
||||||
|
@ -120,11 +117,9 @@ impl HetznerDNSAPIClient {
|
||||||
serde_json::to_string(&payload)
|
serde_json::to_string(&payload)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
println!("body encoding error: {}", e);
|
println!("body encoding error: {}", e);
|
||||||
()
|
|
||||||
})?
|
})?
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
println!("{:#?}", serde_json::to_string(&payload));
|
|
||||||
}
|
}
|
||||||
let t = self
|
let t = self
|
||||||
.client
|
.client
|
||||||
|
@ -132,23 +127,19 @@ impl HetznerDNSAPIClient {
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
println!("request execution error: {}", e);
|
println!("request execution error: {}", e);
|
||||||
()
|
|
||||||
})?
|
})?
|
||||||
.error_for_status()
|
.error_for_status()
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
println!("request error: {}", e);
|
println!("request error: {}", e);
|
||||||
()
|
|
||||||
})?
|
})?
|
||||||
.text()
|
.text()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
println!("request decoding error: {}", 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);
|
println!("json response parsing error: {}", e);
|
||||||
()
|
})
|
||||||
})?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_zones<'a>(
|
pub async fn get_zones<'a>(
|
||||||
|
|
116
src/main.rs
116
src/main.rs
|
@ -1,9 +1,7 @@
|
||||||
#![allow(dead_code, unused)]
|
|
||||||
use crate::client::*;
|
use crate::client::*;
|
||||||
use crate::models::*;
|
use crate::models::*;
|
||||||
use core::panic;
|
use core::panic;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::ops::Sub;
|
|
||||||
|
|
||||||
mod client;
|
mod client;
|
||||||
mod models;
|
mod models;
|
||||||
|
@ -268,7 +266,7 @@ async fn main() {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut records =
|
let records =
|
||||||
client.get_records(None, None, Some(zone.id)).await.unwrap();
|
client.get_records(None, None, Some(zone.id)).await.unwrap();
|
||||||
println!("{:#?}", records);
|
println!("{:#?}", records);
|
||||||
}
|
}
|
||||||
|
@ -287,9 +285,26 @@ async fn main() {
|
||||||
.unwrap()[0]
|
.unwrap()[0]
|
||||||
.id;
|
.id;
|
||||||
ctx.record_context.records[0].zone_id = zone.to_string();
|
ctx.record_context.records[0].zone_id = zone.to_string();
|
||||||
println!("{:#?}", ctx.record_context.records);
|
if let Ok(record) = client
|
||||||
if let Ok(record) =
|
.create_records(
|
||||||
client.create_records(ctx.record_context.records).await
|
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);
|
println!("{:#?}", record);
|
||||||
}
|
}
|
||||||
|
@ -317,10 +332,13 @@ async fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for old_record in records {
|
for old_record in records {
|
||||||
if let Some(mut new_record) =
|
if let Some(new_record) = records_iter.find(|r| {
|
||||||
records_iter.find(|r| r.name == old_record.name)
|
r.name == old_record.name
|
||||||
{
|
|| r.name
|
||||||
let mut old_record = old_record;
|
.split(",")
|
||||||
|
.find(|s| *s == old_record.name)
|
||||||
|
.is_some()
|
||||||
|
}) {
|
||||||
updated_records.push((
|
updated_records.push((
|
||||||
old_record.id,
|
old_record.id,
|
||||||
RecordPayload {
|
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();
|
let records = client.update_records(updated_records).await.unwrap();
|
||||||
eprintln!("Updated {} records", records.len());
|
eprintln!("Updated {} records", records.len());
|
||||||
} else {
|
} else {
|
||||||
|
@ -354,14 +372,80 @@ async fn main() {
|
||||||
_ => panic!("how in the even"),
|
_ => panic!("how in the even"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("missing token!");
|
panic!("missing token! set HETZNER_DNS_API_TOKEN or pass --token <token>");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match ctx.mode {
|
match ctx.mode {
|
||||||
Mode::Zone => println!("zone help"),
|
Mode::Zone => {
|
||||||
Mode::Record => println!("record help"),
|
print_general_help();
|
||||||
Mode::PrimaryServer => println!("primary server help"),
|
print_zone_help();
|
||||||
_ => println!("full 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!"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue