@@ -171,17 +171,25 @@ impl DreamhostClient {
171171 }
172172
173173 fn list_records ( & self ) -> Result < Vec < Record > > {
174- // Check cache first
175174 let mut cache = self . record_cache . lock ( ) . unwrap ( ) ;
176175 if let Some ( records) = cache. as_ref ( ) {
177176 debug ! ( "Using cached DNS records" ) ;
178177 return Ok ( records. clone ( ) ) ;
179178 }
180179
181180 let resp = self . call ( & [ ( "cmd" , "dns-list_records" ) ] ) ?;
182- let records: Vec < Record > = serde_json:: from_value ( resp[ "data" ] . clone ( ) ) ?;
181+
182+ // Ensure we have a JSON array for data; else, treat as error
183+ let records: Vec < Record > = match & resp[ "data" ] {
184+ serde_json:: Value :: Array ( arr) => serde_json:: from_value ( serde_json:: Value :: Array ( arr. clone ( ) ) ) ?,
185+ _ => {
186+ // "data" might be a string like "slow_down_bucko"
187+ let reason = resp[ "reason" ] . as_str ( ) . unwrap_or ( "Unknown DreamHost API error" ) ;
188+ return Err ( anyhow ! ( "DreamHost API error: {}" , reason) ) ;
189+ }
190+ } ;
183191
184- * cache = Some ( records. clone ( ) ) ; // store in cache
192+ * cache = Some ( records. clone ( ) ) ; // cache it
185193 Ok ( records)
186194 }
187195
@@ -266,68 +274,48 @@ fn check_and_update(
266274) -> Result < ( ) > {
267275
268276 match dh. get_dns_ip ( record, record_type) {
269-
270277 Ok ( current_ip) => {
271-
278+ // Existing record exists, update if necessary
272279 if let Ok ( existing_ip) = current_ip. parse :: < IpAddr > ( ) {
273-
274280 if detected_ip == existing_ip {
275-
276281 info ! ( "{} record already up-to-date" , record_type) ;
277282 return Ok ( ( ) ) ;
278-
279283 }
280-
281284 }
282285
283286 warn ! ( "{} record mismatch detected" , record_type) ;
284287
285288 if dry_run {
286-
287- info ! (
288- "DRY RUN: Would update {} record {} -> {}" ,
289- record_type,
290- current_ip,
291- detected_ip
292- ) ;
293-
289+ info ! ( "DRY RUN: Would update {} record {} -> {}" , record_type, current_ip, detected_ip) ;
294290 return Ok ( ( ) ) ;
295291 }
296292
297- dh. update_dns (
298- record,
299- & current_ip,
300- & detected_ip. to_string ( ) ,
301- record_type,
302- ) ?;
303-
293+ dh. update_dns ( record, & current_ip, & detected_ip. to_string ( ) , record_type) ?;
304294 info ! ( "{} record updated successfully" , record_type) ;
305-
306295 }
307296
308- Err ( _ ) => {
309-
310- warn ! ( "{} record does not exist, creating new one" , record_type ) ;
311-
312- if dry_run {
297+ Err ( e ) => {
298+ // Only create record if the error indicates "not found"
299+ let msg = e . to_string ( ) ;
300+ if msg . contains ( "not found" ) {
301+ warn ! ( "{} record does not exist, creating new one" , record_type ) ;
313302
314- info ! (
315- "DRY RUN: Would create {} record -> {}" ,
316- record_type,
317- detected_ip
318- ) ;
303+ if dry_run {
304+ info ! ( "DRY RUN: Would create {} record -> {}" , record_type, detected_ip) ;
305+ return Ok ( ( ) ) ;
306+ }
319307
320- return Ok ( ( ) ) ;
308+ dh. call ( & [
309+ ( "cmd" , "dns-add_record" ) ,
310+ ( "record" , record) ,
311+ ( "type" , record_type) ,
312+ ( "value" , & detected_ip. to_string ( ) ) ,
313+ ] ) ?;
314+ info ! ( "{} record created successfully" , record_type) ;
315+ } else {
316+ // Propagate all other errors (API errors, rate limits, network errors)
317+ return Err ( e) ;
321318 }
322-
323- dh. call ( & [
324- ( "cmd" , "dns-add_record" ) ,
325- ( "record" , record) ,
326- ( "type" , record_type) ,
327- ( "value" , & detected_ip. to_string ( ) ) ,
328- ] ) ?;
329-
330- info ! ( "{} record created successfully" , record_type) ;
331319 }
332320 }
333321
@@ -375,36 +363,45 @@ fn main() -> Result<()> {
375363
376364 impl DetectionJob {
377365 fn run ( self , dh : & Arc < DreamhostClient > ) -> Result < ( ) > {
366+
367+ // helper to safely remove a DNS record if it exists
368+ let remove_stale_record = |record_type : & str , record_name : & str | -> Result < ( ) > {
369+ match dh. get_dns_ip ( record_name, record_type) {
370+ Ok ( existing_ip) => {
371+ warn ! ( "{} record exists but no WAN IP detected: {}" , record_type, existing_ip) ;
372+ if self . dry_run {
373+ info ! ( "DRY RUN: Would remove stale {} record {}" , record_type, existing_ip) ;
374+ } else {
375+ dh. call ( & [
376+ ( "cmd" , "dns-remove_record" ) ,
377+ ( "record" , record_name) ,
378+ ( "type" , record_type) ,
379+ ( "value" , & existing_ip) ,
380+ ] ) ?;
381+ warn ! ( "Removed stale {} record {}" , record_type, existing_ip) ;
382+ }
383+ }
384+ Err ( _) => debug ! ( "No {} record exists; nothing to remove" , record_type) ,
385+ }
386+ Ok ( ( ) )
387+ } ;
388+
378389 match detect_ip ( & self . client , self . services , self . require_ipv4 ) {
379390 Ok ( ip) => {
380- info ! ( "Detected {} WAN: {}" , self . record_type, ip) ;
391+ let ipv = if self . record_type =="A" { "IPV4" } else { "IPV6" } ;
392+ info ! ( "Detected {} WAN: {}" , ipv, ip) ;
381393 check_and_update ( dh, & self . record_name , ip, self . record_type , self . dry_run ) ?;
382394 }
383395 Err ( _) => {
384396 if self . record_type == "AAAA" {
385397 info ! ( "No IPv6 WAN detected" ) ;
386- match dh. get_dns_ip ( & self . record_name , "AAAA" ) {
387- Ok ( existing_ip) => {
388- warn ! ( "IPv6 not detected but AAAA record exists: {}" , existing_ip) ;
389- if self . dry_run {
390- info ! ( "DRY RUN: Would remove stale AAAA record {}" , existing_ip) ;
391- } else {
392- dh. call ( & [
393- ( "cmd" , "dns-remove_record" ) ,
394- ( "record" , & self . record_name ) ,
395- ( "type" , "AAAA" ) ,
396- ( "value" , & existing_ip) ,
397- ] ) ?;
398- warn ! ( "Removed stale AAAA record {}" , existing_ip) ;
399- }
400- }
401- Err ( _) => debug ! ( "No AAAA record exists; nothing to remove" ) ,
402- }
398+ remove_stale_record ( "AAAA" , & self . record_name ) ?;
403399 } else {
404400 warn ! ( "No IPv4 WAN detected" ) ;
405401 }
406402 }
407403 }
404+
408405 Ok ( ( ) )
409406 }
410407 }
0 commit comments