dns: style and code clean-up powerdns plugin

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2024-03-04 16:30:51 +01:00
parent 244fb03d3a
commit e92b11a2e5

View file

@ -2,12 +2,15 @@ package PVE::Network::SDN::Dns::PowerdnsPlugin;
use strict; use strict;
use warnings; use warnings;
use PVE::INotify;
use PVE::Cluster;
use PVE::Tools;
use JSON; use JSON;
use Net::IP; use Net::IP;
use NetAddr::IP qw(:lower); use NetAddr::IP qw(:lower);
use PVE::Cluster;
use PVE::INotify;
use PVE::Tools;
use base('PVE::Network::SDN::Dns::Plugin'); use base('PVE::Network::SDN::Dns::Plugin');
sub type { sub type {
@ -29,13 +32,14 @@ sub properties {
} }
sub options { sub options {
return { return {
url => { optional => 0}, url => { optional => 0},
key => { optional => 0 }, key => { optional => 0 },
ttl => { optional => 1 }, ttl => { optional => 1 },
reversemaskv6 => { optional => 1, description => "force a different netmask for the ipv6 reverse zone name." }, reversemaskv6 => {
optional => 1,
description => "force a different netmask for the ipv6 reverse zone name.",
},
}; };
} }
@ -56,39 +60,33 @@ sub add_a_record {
my $existing_rrset = get_zone_rrset($zonecontent, $fqdn); my $existing_rrset = get_zone_rrset($zonecontent, $fqdn);
my $final_records = []; my $final_records = [];
my $foundrecord = undef; for my $record (@{$existing_rrset->{records}}) {
foreach my $record (@{$existing_rrset->{records}}) {
if ($record->{content} eq $ip) { if ($record->{content} eq $ip) {
$foundrecord = 1; return; # the record already exist so return early
next;
} }
push @$final_records, $record; push @$final_records, $record;
} }
return if $foundrecord;
my $record = { content => $ip, my $record = {
content => $ip,
disabled => JSON::false, disabled => JSON::false,
name => $fqdn, name => $fqdn,
type => $type }; type => $type,
};
push @$final_records, $record; push @$final_records, $record;
my $rrset = { name => $fqdn, my $params = {
rrsets => [{
name => $fqdn,
type => $type, type => $type,
ttl => $ttl, ttl => $ttl,
changetype => "REPLACE", changetype => "REPLACE",
records => $final_records }; records => $final_records,
}],
my $params = { rrsets => [ $rrset ] };
eval {
PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params);
}; };
if ($@) { eval { PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params) };
die "error add $fqdn to zone $zone: $@" if !$noerr; die "error add $fqdn to zone $zone: $@" if $@ && !$noerr;
}
} }
sub add_ptr_record { sub add_ptr_record {
@ -104,27 +102,25 @@ sub add_ptr_record {
my $type = "PTR"; my $type = "PTR";
my $record = { content => $hostname, my $record = {
content => $hostname,
disabled => JSON::false, disabled => JSON::false,
name => $reverseip, name => $reverseip,
type => $type }; type => $type,
};
my $rrset = { name => $reverseip, my $params = {
rrsets => [{
name => $reverseip,
type => $type, type => $type,
ttl => $ttl, ttl => $ttl,
changetype => "REPLACE", changetype => "REPLACE",
records => [ $record ] }; records => [ $record ],
}],
my $params = { rrsets => [ $rrset ] };
eval {
PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params);
}; };
if ($@) { eval { PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params) };
die "error add $reverseip to zone $zone: $@" if !$noerr; die "error add $reverseip to zone $zone: $@" if $@ && !$noerr;
}
} }
sub del_a_record { sub del_a_record {
@ -139,44 +135,30 @@ sub del_a_record {
my $zonecontent = get_zone_content($plugin_config, $zone); my $zonecontent = get_zone_content($plugin_config, $zone);
my $existing_rrset = get_zone_rrset($zonecontent, $fqdn); my $existing_rrset = get_zone_rrset($zonecontent, $fqdn);
my $final_records = []; my $final_records = [ grep { $_->{content} ne $ip } $existing_rrset->{records}->@* ];
my $foundrecord = undef; my $final_records_size = scalar($final_records->@*);
foreach my $record (@{$existing_rrset->{records}}) { # early return if we didn't find our record (i.e., un/filtered record sets have the same size)
if ($record->{content} eq $ip) { return if scalar($existing_rrset->{content}->@*) == $final_records_size;
$foundrecord = 1;
next;
}
push @$final_records, $record;
}
return if !$foundrecord;
my $rrset = {}; my $rrset = {
name => $fqdn,
if (scalar (@{$final_records}) > 0) {
#if we still have other records, we rewrite them without removed ip
$rrset = { name => $fqdn,
type => $type, type => $type,
ttl => $existing_rrset->{ttl}, };
changetype => "REPLACE",
records => $final_records };
if ($final_records_size > 0) {
# if we still have other records, we rewrite them with the $ip removed
$rrset->{ttl} = $existing_rrset->{ttl};
$rrset->{changetype} = "REPLACE";
$rrset->{records} = $final_records;
} else { } else {
$rrset->{changetype} = "DELETE";
$rrset = { name => $fqdn, $rrset->{records} = [];
type => $type,
changetype => "DELETE",
records => [] };
} }
my $params = { rrsets => [ $rrset ] }; my $params = { rrsets => [ $rrset ] };
eval { eval { PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params) };
PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params); die "error delete $fqdn from zone $zone: $@" if $@ && !$noerr;
};
if ($@) {
die "error delete $fqdn from zone $zone: $@" if !$noerr;
}
} }
sub del_ptr_record { sub del_ptr_record {
@ -190,20 +172,17 @@ sub del_ptr_record {
my $type = "PTR"; my $type = "PTR";
my $rrset = { name => $reverseip, my $params = {
rrsets => [{
name => $reverseip,
type => $type, type => $type,
changetype => "DELETE", changetype => "DELETE",
records => [] }; records => [],
}],
my $params = { rrsets => [ $rrset ] };
eval {
PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params);
}; };
if ($@) { eval { PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params) };
die "error delete $reverseip from zone $zone: $@" if !$noerr; die "error delete $reverseip from zone $zone: $@" if $@ && !$noerr;
}
} }
sub verify_zone { sub verify_zone {
@ -215,13 +194,8 @@ sub verify_zone {
my $key = $plugin_config->{key}; my $key = $plugin_config->{key};
my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $key]; my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $key];
eval { eval { PVE::Network::SDN::api_request("GET", "$url/zones/$zone?rrsets=false", $headers) };
PVE::Network::SDN::api_request("GET", "$url/zones/$zone?rrsets=false", $headers); die "can't read zone $zone: $@" if $@ && !$noerr;
};
if ($@) {
die "can't read zone $zone: $@" if !$noerr;
}
} }
sub get_reversedns_zone { sub get_reversedns_zone {
@ -248,9 +222,12 @@ sub get_reversedns_zone {
} else { } else {
# public ipv4 : RIPE,ARIN,AFRNIC # public ipv4 : RIPE,ARIN,AFRNIC
#. Delegations can be managed in IPv4 on bit boundaries (/8, /16 or /24s), and IPv6 networks can be managed on nibble boundaries (every 4 bits of the IPv6 address) # Delegations can be managed in IPv4 on bit boundaries (/8, /16 or /24s), and IPv6
#One or more /24 type zones need to be created if your address space has a prefix length between /17 and /24. # networks can be managed on nibble boundaries (every 4 bits of the IPv6 address)
# If your prefix length is between /16 and /9 you will have to request one or more delegations for /16 type zones. # One or more /24 type zones need to be created if your address space has a prefix
# length between /17 and /24.
# If your prefix length is between /16 and /9 you will have to request one or more
# delegations for /16 type zones.
if ($mask <= 24) { if ($mask <= 24) {
$zone = "$ipblock3.$ipblock2.$ipblock1.in-addr.arpa."; $zone = "$ipblock3.$ipblock2.$ipblock1.in-addr.arpa.";
@ -280,13 +257,8 @@ sub on_update_hook {
my $key = $plugin_config->{key}; my $key = $plugin_config->{key};
my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $key]; my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $key];
eval { eval { PVE::Network::SDN::api_request("GET", "$url", $headers) };
PVE::Network::SDN::api_request("GET", "$url", $headers); die "dns api error: $@" if $@;
};
if ($@) {
die "dns api error: $@";
}
} }
@ -299,27 +271,19 @@ sub get_zone_content {
my $key = $plugin_config->{key}; my $key = $plugin_config->{key};
my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $key]; my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $key];
my $result = undef; my $result = eval { PVE::Network::SDN::api_request("GET", "$url/zones/$zone", $headers) };
eval { die "can't read zone $zone: $@" if $@;
$result = PVE::Network::SDN::api_request("GET", "$url/zones/$zone", $headers);
};
if ($@) {
die "can't read zone $zone: $@";
}
return $result; return $result;
} }
sub get_zone_rrset { sub get_zone_rrset {
my ($zonecontent, $name) = @_; my ($zonecontent, $name) = @_;
my $rrsetresult = undef; for my $rrset (@{$zonecontent->{rrsets}}) {
foreach my $rrset (@{$zonecontent->{rrsets}}) { return $rrset if $rrset->{name} eq $name;
next if $rrset->{name} ne $name;
$rrsetresult = $rrset;
last;
} }
return $rrsetresult; return; # not found
} }
1; 1;