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 {
@ -22,20 +25,21 @@ sub properties {
key => { key => {
type => 'string', type => 'string',
}, },
reversemaskv6 => { reversemaskv6 => {
type => 'integer' type => 'integer'
}, },
}; };
} }
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) { return; # the record already exist so return early
$foundrecord = 1;
next;
} }
push @$final_records, $record; push @$final_records, $record;
} }
return if $foundrecord;
my $record = { content => $ip,
disabled => JSON::false,
name => $fqdn,
type => $type };
my $record = {
content => $ip,
disabled => JSON::false,
name => $fqdn,
type => $type,
};
push @$final_records, $record; push @$final_records, $record;
my $rrset = { name => $fqdn, my $params = {
type => $type, rrsets => [{
ttl => $ttl, name => $fqdn,
changetype => "REPLACE", type => $type,
records => $final_records }; ttl => $ttl,
changetype => "REPLACE",
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 = {
disabled => JSON::false, content => $hostname,
name => $reverseip, disabled => JSON::false,
type => $type }; name => $reverseip,
type => $type,
my $rrset = { name => $reverseip,
type => $type,
ttl => $ttl,
changetype => "REPLACE",
records => [ $record ] };
my $params = { rrsets => [ $rrset ] };
eval {
PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params);
}; };
if ($@) { my $params = {
die "error add $reverseip to zone $zone: $@" if !$noerr; rrsets => [{
} name => $reverseip,
type => $type,
ttl => $ttl,
changetype => "REPLACE",
records => [ $record ],
}],
};
eval { PVE::Network::SDN::api_request("PATCH", "$url/zones/$zone", $headers, $params) };
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) { type => $type,
#if we still have other records, we rewrite them without removed ip };
$rrset = { name => $fqdn,
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,38 +172,30 @@ sub del_ptr_record {
my $type = "PTR"; my $type = "PTR";
my $rrset = { name => $reverseip, my $params = {
type => $type, rrsets => [{
changetype => "DELETE", name => $reverseip,
records => [] }; type => $type,
changetype => "DELETE",
my $params = { rrsets => [ $rrset ] }; records => [],
}],
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 {
my ($class, $plugin_config, $zone, $noerr) = @_; my ($class, $plugin_config, $zone, $noerr) = @_;
#verify that api is working #verify that api is working
my $url = $plugin_config->{url}; my $url = $plugin_config->{url};
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 {
@ -245,12 +219,15 @@ sub get_reversedns_zone {
} elsif ($ipblock1 == 10) { } elsif ($ipblock1 == 10) {
$zone = "10.in-addr.arpa."; $zone = "10.in-addr.arpa.";
} }
} 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.";
@ -274,52 +251,39 @@ sub get_reversedns_zone {
sub on_update_hook { sub on_update_hook {
my ($class, $plugin_config) = @_; my ($class, $plugin_config) = @_;
#verify that api is working # verify that api is working
my $url = $plugin_config->{url}; my $url = $plugin_config->{url};
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: $@";
}
} }
sub get_zone_content { sub get_zone_content {
my ($plugin_config, $zone) = @_; my ($plugin_config, $zone) = @_;
#verify that api is working # verify that api is working
my $url = $plugin_config->{url}; my $url = $plugin_config->{url};
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;