From 216c9c6010d26f1016199f0e0f8d5acc3c82fa03 Mon Sep 17 00:00:00 2001 From: Richard Hansen Date: Fri, 12 Jul 2024 19:33:49 -0400 Subject: [PATCH] hetzner: Remove unnecessary host groupings Each host is already updated individually so there's no point in grouping the hosts. --- ddclient.in | 177 +++++++++++++++++++++++++--------------------------- 1 file changed, 85 insertions(+), 92 deletions(-) diff --git a/ddclient.in b/ddclient.in index c16b452..6211064 100755 --- a/ddclient.in +++ b/ddclient.in @@ -6253,114 +6253,107 @@ EoEXAMPLE ###################################################################### sub nic_hetzner_update { debug("\nnic_hetzner_update -------------------"); - my %groups = group_hosts_by(\@_, [qw(ssh login password server wildcard mx backupmx zone wantipv4 wantipv6)]); - for my $sig (keys %groups) { - my @hosts = @{$groups{$sig}}; - my $hosts = join(',', @hosts); - my $key = $hosts[0]; - - my $headers = "Auth-API-Token: $config{$key}{'password'}\n"; + for my $domain (@_) { + my $headers = "Auth-API-Token: $config{$domain}{'password'}\n"; $headers .= "Content-Type: application/json"; - for my $domain (@hosts) { - (my $hostname = $domain) =~ s/\.$config{$key}{zone}$//; - my $ipv4 = delete $config{$domain}{'wantipv4'}; - my $ipv6 = delete $config{$domain}{'wantipv6'}; + (my $hostname = $domain) =~ s/\.$config{$domain}{zone}$//; + my $ipv4 = delete $config{$domain}{'wantipv4'}; + my $ipv6 = delete $config{$domain}{'wantipv6'}; - info("getting Hetzner Zone ID for %s", $domain); + info("getting Hetzner Zone ID for %s", $domain); - # Get zone ID - my $url = "https://$config{$key}{'server'}/zones?name=" . $config{$key}{'zone'}; + # Get zone ID + my $url = "https://$config{$domain}{'server'}/zones?name=" . $config{$domain}{'zone'}; - my $reply = geturl(proxy => opt('proxy'), - url => $url, - headers => $headers - ); + my $reply = geturl(proxy => opt('proxy'), + url => $url, + headers => $headers + ); + unless ($reply && header_ok($domain, $reply)) { + failed("updating %s: Could not connect to %s.", $domain, $config{$domain}{'server'}); + next; + } + + # Strip header + $reply =~ qr/{(?:[^{}]*|(?R))*}/mp; + my $response = eval {decode_json(${^MATCH})}; + unless ($response && $response->{zones}) { + failed("updating %s: invalid json or result.", $domain); + next; + } + + # Pull the ID out of the json, messy + my ($zone_id) = map {$_->{name} eq $config{$domain}{'zone'} ? $_->{id} : ()} @{$response->{zones}}; + unless ($zone_id) { + failed("updating %s: No zone ID found.", $config{$domain}{'zone'}); + next; + } + info("Zone ID is %s", $zone_id); + + # IPv4 and IPv6 handling are similar enough to do in a loop... + for my $ip ($ipv4, $ipv6) { + next if (!$ip); + my $ipv = ($ip eq ($ipv6 // '')) ? '6' : '4'; + my $type = ($ip eq ($ipv6 // '')) ? 'AAAA' : 'A'; + + info("updating %s: setting IPv$ipv address to %s", $domain, $ip); + $config{$domain}{"status-ipv$ipv"} = 'failed'; + + # Get DNS 'A' or 'AAAA' record ID + $url = "https://$config{$domain}{'server'}/records?zone_id=$zone_id"; + $reply = geturl(proxy => opt('proxy'), + url => $url, + headers => $headers + ); unless ($reply && header_ok($domain, $reply)) { - failed("updating %s: Could not connect to %s.", $domain, $config{$key}{'server'}); + failed("updating %s: Could not connect to %s.", $domain, $config{$domain}{'server'}); next; } - # Strip header $reply =~ qr/{(?:[^{}]*|(?R))*}/mp; - my $response = eval {decode_json(${^MATCH})}; - unless ($response && $response->{zones}) { + $response = eval {decode_json(${^MATCH})}; + unless ($response && $response->{records}) { failed("updating %s: invalid json or result.", $domain); next; } - # Pull the ID out of the json, messy - my ($zone_id) = map {$_->{name} eq $config{$key}{'zone'} ? $_->{id} : ()} @{$response->{zones}}; - unless ($zone_id) { - failed("updating %s: No zone ID found.", $config{$key}{'zone'}); + my ($dns_rec_id) = map { ($_->{name} eq $hostname && $_->{type} eq $type) ? $_->{id} : ()} @{$response->{records}}; + + # Set domain + my $http_method=""; + if ($dns_rec_id) + { + debug("updating %s: DNS '$type' record ID: $dns_rec_id", $domain); + $url = "https://$config{$domain}{'server'}/records/$dns_rec_id"; + $http_method = "PUT"; + } else { + debug("creating %s: DNS '$type'", $domain); + $url = "https://$config{$domain}{'server'}/records"; + $http_method = "POST"; + } + my $data = "{\"zone_id\":\"$zone_id\", \"name\": \"$hostname\", \"value\": \"$ip\", \"type\": \"$type\", \"ttl\": $config{$domain}{'ttl'}}"; + + $reply = geturl(proxy => opt('proxy'), + url => $url, + headers => $headers, + method => $http_method, + data => $data + ); + unless ($reply && header_ok($domain, $reply)) { + failed("updating %s: Could not connect to %s.", $domain, $config{$domain}{'server'}); next; } - info("Zone ID is %s", $zone_id); - - # IPv4 and IPv6 handling are similar enough to do in a loop... - for my $ip ($ipv4, $ipv6) { - next if (!$ip); - my $ipv = ($ip eq ($ipv6 // '')) ? '6' : '4'; - my $type = ($ip eq ($ipv6 // '')) ? 'AAAA' : 'A'; - - info("updating %s: setting IPv$ipv address to %s", $domain, $ip); - $config{$domain}{"status-ipv$ipv"} = 'failed'; - - # Get DNS 'A' or 'AAAA' record ID - $url = "https://$config{$key}{'server'}/records?zone_id=$zone_id"; - $reply = geturl(proxy => opt('proxy'), - url => $url, - headers => $headers - ); - unless ($reply && header_ok($domain, $reply)) { - failed("updating %s: Could not connect to %s.", $domain, $config{$key}{'server'}); - next; - } - # Strip header - $reply =~ qr/{(?:[^{}]*|(?R))*}/mp; - $response = eval {decode_json(${^MATCH})}; - unless ($response && $response->{records}) { - failed("updating %s: invalid json or result.", $domain); - next; - } - # Pull the ID out of the json, messy - my ($dns_rec_id) = map { ($_->{name} eq $hostname && $_->{type} eq $type) ? $_->{id} : ()} @{$response->{records}}; - - # Set domain - my $http_method=""; - if ($dns_rec_id) - { - debug("updating %s: DNS '$type' record ID: $dns_rec_id", $domain); - $url = "https://$config{$key}{'server'}/records/$dns_rec_id"; - $http_method = "PUT"; - } else { - debug("creating %s: DNS '$type'", $domain); - $url = "https://$config{$key}{'server'}/records"; - $http_method = "POST"; - } - my $data = "{\"zone_id\":\"$zone_id\", \"name\": \"$hostname\", \"value\": \"$ip\", \"type\": \"$type\", \"ttl\": $config{$domain}{'ttl'}}"; - - $reply = geturl(proxy => opt('proxy'), - url => $url, - headers => $headers, - method => $http_method, - data => $data - ); - unless ($reply && header_ok($domain, $reply)) { - failed("updating %s: Could not connect to %s.", $domain, $config{$domain}{'server'}); - next; - } - # Strip header - $reply =~ qr/{(?:[^{}]*|(?R))*}/mp; - $response = eval {decode_json(${^MATCH})}; - if ($response && $response->{record}) { - success("updating %s: IPv$ipv address set to %s", $domain, $ip); - $config{$domain}{"ipv$ipv"} = $ip; - $config{$domain}{'mtime'} = $now; - $config{$domain}{"status-ipv$ipv"} = 'good'; - } else { - failed("updating %s: invalid json or result.", $domain); - } + # Strip header + $reply =~ qr/{(?:[^{}]*|(?R))*}/mp; + $response = eval {decode_json(${^MATCH})}; + if ($response && $response->{record}) { + success("updating %s: IPv$ipv address set to %s", $domain, $ip); + $config{$domain}{"ipv$ipv"} = $ip; + $config{$domain}{'mtime'} = $now; + $config{$domain}{"status-ipv$ipv"} = 'good'; + } else { + failed("updating %s: invalid json or result.", $domain); } } }