Write update status to %recap
, not %config
Status is not configuration so it doesn't belong in `%config`. `wantip`, `wantipv4`, and `wantipv6` are still passed along in `%config` because `group_hosts_by` needs access to them like other settings.
This commit is contained in:
parent
0348ded46b
commit
268369a05e
6 changed files with 254 additions and 451 deletions
|
@ -100,6 +100,8 @@ repository history](https://github.com/ddclient/ddclient/commits/master).
|
|||
|
||||
### Bug fixes
|
||||
|
||||
* Fixed numerous bugs in cache file (recap) handling.
|
||||
[#740](https://github.com/ddclient/ddclient/pull/740)
|
||||
* Fixed numerous bugs in command-line option and configuration file
|
||||
processing. [#733](https://github.com/ddclient/ddclient/pull/733)
|
||||
* `noip`: Fixed failure to honor IP discovery settings in some circumstances.
|
||||
|
|
466
ddclient.in
466
ddclient.in
|
@ -145,15 +145,10 @@ our %config;
|
|||
# host's "recap variables" -- the host's protocol's variables with a truthy `recap` property -- are
|
||||
# included.
|
||||
#
|
||||
# `%config` is the source of truth for recap variable values. The recap variable values in
|
||||
# `%config` are initialized with values from the cache file (via `%recap`). After initialization,
|
||||
# any change to a recap variable's value is made to `%config` and later copied to `%recap` before
|
||||
# being written to the cache file. Changes made directly to `%recap` are erroneous because they
|
||||
# will be overwritten by the value in `%config`.
|
||||
#
|
||||
# There are two classes of recap variables:
|
||||
# `%recap` is independent of `%config`, although they both share the same set of variable
|
||||
# declarations. There are two classes of recap variables:
|
||||
# * "Status" variables: These track update success/failure, the IP address of the last successful
|
||||
# update, etc. These do not hold configuration data. These should always be kept in sync with
|
||||
# update, etc. These do not hold configuration data; they are unrelated to any entries in
|
||||
# `%config`.
|
||||
# * "Configuration change detection" variables: These are used to force an update if the value in
|
||||
# the same-named entry in `%config` has changed since the previous update attempt. The value
|
||||
|
@ -654,20 +649,13 @@ our %variables = (
|
|||
'min-error-interval' => setv(T_DELAY, 0, 0, interval('5m'), 0),
|
||||
|
||||
# The desired IP address (IPv4 or IPv6, but almost always IPv4) that should be saved at the
|
||||
# DDNS service.
|
||||
# TODO: Legacy protocol implementations write the IP address most recently saved at the
|
||||
# DDNS service to this variable so that it can be saved in the recap (as `ipv4` or `ipv6`).
|
||||
# Update the legacy implementations to use `ipv4` or `ipv6` instead, though see the TODO
|
||||
# for those variables.
|
||||
# DDNS service (when `use=ip`).
|
||||
'ip' => setv(T_IP, 0, 0, undef, undef),
|
||||
# As a recap value, this is the IPv4 address most recently saved at the DDNS service. As a
|
||||
# setting, this is the desired IPv4 address that should be saved at the DDNS service.
|
||||
# TODO: The use of `ipv4` as a recap status variable is supposed to be independent of the
|
||||
# use of `ipv4` as a configuration setting. Unfortunately, because the `%config` value is
|
||||
# synced to `%recap`, the two uses conflict which causes the bug "skipped: IP address was
|
||||
# already set to a.b.c.d" when the IP was never set to a.b.c.d. Rename the `%recap` status
|
||||
# variable to something like `saved-ipv4` to avoid the collision (and confusion) with the
|
||||
# `%config` setting variable.
|
||||
# TODO: The use of `ipv4` as a recap status variable is independent of the use of `ipv4` as
|
||||
# a configuration setting. Rename the `%recap` status variable to something like
|
||||
# `saved-ipv4` to avoid confusion with the `%config` setting variable.
|
||||
'ipv4' => setv(T_IPV4, 0, 1, undef, undef),
|
||||
# As `ipv4`, but for an IPv6 address.
|
||||
'ipv6' => setv(T_IPV6, 0, 1, undef, undef),
|
||||
|
@ -711,7 +699,7 @@ our %variables = (
|
|||
);
|
||||
|
||||
# Converts a legacy protocol update method to behave like a modern implementation by moving
|
||||
# `$config{$h}{status}` and `$config{$h}{ip}` to the version-specific modern equivalents.
|
||||
# `$recap{$h}{status}` and `$recap{$h}{ip}` to the version-specific modern equivalents.
|
||||
sub adapt_legacy_update {
|
||||
my ($update) = @_;
|
||||
return sub {
|
||||
|
@ -720,7 +708,7 @@ sub adapt_legacy_update {
|
|||
for my $h (@hosts) {
|
||||
$ipv{$h} = defined($config{$h}{'wantipv4'}) ? '4' : '6';
|
||||
$config{$h}{'wantip'} = delete($config{$h}{"wantipv$ipv{$h}"});
|
||||
delete($config{$h}{$_}) for qw(ip status);
|
||||
delete($recap{$h}{$_}) for qw(ip status);
|
||||
}
|
||||
$update->(@hosts);
|
||||
for my $h (@hosts) {
|
||||
|
@ -728,29 +716,8 @@ sub adapt_legacy_update {
|
|||
delete($config{$h}{'wantip'});
|
||||
debug(
|
||||
"legacy protocol; moving 'status' to 'status-ipv$ipv{$h}', 'ip' to 'ipv$ipv{$h}'");
|
||||
$config{$h}{"status-ipv$ipv{$h}"} = delete($config{$h}{'status'});
|
||||
# TODO: Currently $config{$h}{'ip'} is used for two distinct purposes: it holds the
|
||||
# value of the --ip option, and it is updated by legacy protocols to hold the new IP
|
||||
# address after an update. Fortunately, the --ip option is not used very often, and if
|
||||
# it is, the values for the two use cases are usually (but not always) the same. This
|
||||
# boolean is an imperfect attempt to identify whether 'ip' is being used for the --ip
|
||||
# option, to avoid breaking some user's configuration. Protocols should be updated to
|
||||
# not set $config{$h}{'ip'} because %config is for configuration, not update status
|
||||
# (same goes for 'status', 'mtime', etc.).
|
||||
my $ip_option = opt('use', $h) eq 'ip' || opt('usev6', $h) eq 'ip';
|
||||
my $ip = $config{$h}{'ip'};
|
||||
delete($config{$h}{'ip'}) if !$ip_option;
|
||||
# TODO: See above comment for $ip_option. This is the same situation, but for 'ipv4'
|
||||
# and 'ipv6'.
|
||||
my $vip_option = opt("usev$ipv{$h}", $h) eq "ipv$ipv{$h}";
|
||||
if ($vip_option && defined(my $vip = $config{$h}{"ipv$ipv{$h}"})) {
|
||||
if (!defined($ip) || $ip ne $vip) {
|
||||
my $fip = defined($ip) ? "'$ip'" : '<undefined>';
|
||||
debug("unable to set 'ipv$ipv{$h}' to $fip; already set to '$vip'");
|
||||
}
|
||||
next;
|
||||
}
|
||||
$config{$h}{"ipv$ipv{$h}"} = $ip;
|
||||
$recap{$h}{"status-ipv$ipv{$h}"} = delete($recap{$h}{'status'});
|
||||
$recap{$h}{"ipv$ipv{$h}"} = delete($recap{$h}{'ip'});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1502,29 +1469,39 @@ sub update_nics {
|
|||
$0 = sprintf("%s - updating %s", $program, join(',', @hosts));
|
||||
local $_l = pushlogctx($p);
|
||||
for my $h (@hosts) {
|
||||
$config{$h}{'atime'} = $now;
|
||||
delete($config{$h}{$_}) for qw(status-ipv4 status-ipv6 wtime
|
||||
warned-min-interval warned-min-error-interval);
|
||||
$recap{$h}{'atime'} = $now;
|
||||
delete($recap{$h}{$_}) for qw(status-ipv4 status-ipv6 wtime
|
||||
warned-min-interval warned-min-error-interval);
|
||||
# Update configuration change detection variables in `%recap` with the latest
|
||||
# values in `%config`. Notes about why this is done here:
|
||||
# * The vars must not be updated if the host is not being updated because change
|
||||
# detection is defined relative to the previous update attempt. In particular,
|
||||
# these can't be updated when the protocol's `force_update` method is called
|
||||
# because that method is not always called before an update is attempted.
|
||||
# * The vars must be updated after the `force_update` method would be called so
|
||||
# that `force_update` can check whether any settings have changed since the
|
||||
# last time an update was attempted.
|
||||
# * The vars are updated before the protocol's `update` method is called so that
|
||||
# `update` sees consistent values between `%recap` and `%config`. This reduces
|
||||
# the impact of Hyrum's Law; if a protocol needs a variable to be updated after
|
||||
# the `update` method is called then that behavior should be made explicit.
|
||||
my $vars = $protocols{opt('protocol', $h)}{variables};
|
||||
for my $v (qw(static wildcard mx backupmx)) {
|
||||
next if !$vars->{$v} || !$vars->{$v}{recap};
|
||||
if (defined(my $val = opt($v, $h))) {
|
||||
$recap{$h}{$v} = $val;
|
||||
} else {
|
||||
# Entries in `%recap` with `undef` values are deleted to avoid needing to
|
||||
# figure out how to represent `undef` in the cache file and to simplify
|
||||
# testing.
|
||||
delete($recap{$h}{$v});
|
||||
}
|
||||
}
|
||||
}
|
||||
&$update(@hosts);
|
||||
for my $h (@hosts) {
|
||||
delete($config{$h}{$_}) for qw(wantipv4 wantipv6);
|
||||
}
|
||||
for my $h (@hosts) {
|
||||
# Update `%recap` with the latest values in `%config`. This is done after the
|
||||
# protocol's update method returns in case that method mutates any of the `%config`
|
||||
# values or needs access to the previous iteration's `%recap` values. Entries in
|
||||
# `%recap` with `undef` values are deleted to avoid needing to figure out how to
|
||||
# represent `undef` in the cache file and to simplify testing. Also, entries for
|
||||
# non-recap variables (which can happen after changing a host's protocol or after
|
||||
# switching to a different version of ddclient) are deleted.
|
||||
my $vars = $protocols{$p}{variables};
|
||||
$recap{$h} = {};
|
||||
for my $v (keys(%$vars)) {
|
||||
next if !$vars->{$v}{recap} || !defined(opt($v, $h));
|
||||
$recap{$h}{$v} = opt($v, $h);
|
||||
}
|
||||
}
|
||||
runpostscript(join ' ', keys %ipsv4, keys %ipsv6);
|
||||
}
|
||||
}
|
||||
|
@ -1614,7 +1591,6 @@ sub read_recap {
|
|||
%opt = ();
|
||||
$saved_recap = _read_config(\%recap, $globals, "##\\s*$program-$version\\s*", $file);
|
||||
%opt = %saved;
|
||||
$recap{$_} //= {} for keys(%config);
|
||||
for my $h (keys(%recap)) {
|
||||
if (!exists($config{$h})) {
|
||||
delete($recap{$h});
|
||||
|
@ -1624,26 +1600,6 @@ sub read_recap {
|
|||
for my $v (keys(%{$recap{$h}})) {
|
||||
delete($recap{$h}{$v}) if !$vars->{$v} || !$vars->{$v}{recap};
|
||||
}
|
||||
# Only status variables are copied from `%recap` into `%config` because the recap should
|
||||
# not change the configuration. See the documenting comments for `%recap`.
|
||||
# TODO: Hard-coding this list impairs readability and maintainability. In particular,
|
||||
# different pieces of code need to know the list of status variables, and keeping them all
|
||||
# in sync is error-prone (DRY). Also, different protocols might need different status
|
||||
# variables.
|
||||
# TODO: None of the recap variables should be copied into `%config` because `%config` is
|
||||
# not the semantically appropriate place to record update status. Code that currently
|
||||
# reads/sets `$config{$h}{'status-ipv4'}` (and friends) should instead access
|
||||
# `$recap{$h}{'status-ipv4'}` directly.
|
||||
for my $v (qw(atime mtime wtime ipv4 ipv6 status-ipv4 status-ipv6
|
||||
warned-min-interval warned-min-error-interval)) {
|
||||
next if !$vars->{$v} || !$vars->{$v}{recap};
|
||||
if (defined($recap{$h}{$v})) {
|
||||
$config{$h}{$v} = $recap{$h}{$v};
|
||||
} else {
|
||||
delete($config{$h}{$v});
|
||||
}
|
||||
}
|
||||
delete($recap{$h}) if !%{$recap{$h}};
|
||||
}
|
||||
}
|
||||
######################################################################
|
||||
|
@ -3519,15 +3475,14 @@ sub nic_updateable {
|
|||
if (($recap{$host}{'status-ipv4'} // '') eq 'good' &&
|
||||
!interval_expired($host, 'mtime', 'min-interval')) {
|
||||
warning("skipped update from $previpv4 to $ipv4 because it has been less than $prettyi{'min-interval'} since the previous update (on $prettyt{'mtime'})")
|
||||
if opt('verbose') || !($config{$host}{'warned-min-interval'} // 0);
|
||||
if opt('verbose') || !($recap{$host}{'warned-min-interval'} // 0);
|
||||
|
||||
$config{$host}{'warned-min-interval'} = $now;
|
||||
$recap{$host}{'warned-min-interval'} = $now;
|
||||
|
||||
} elsif (($recap{$host}{'status-ipv4'} // '') ne 'good' &&
|
||||
!interval_expired($host, 'atime', 'min-error-interval')) {
|
||||
|
||||
if (opt('verbose') || (!$config{$host}{'warned-min-error-interval'} &&
|
||||
if (opt('verbose') || (!$recap{$host}{'warned-min-error-interval'} &&
|
||||
($warned_ipv4{$host} // 0) < $inv_ip_warn_count)) {
|
||||
warning("skipped update from $previpv4 to $ipv4 because it has been less than $prettyi{'min-error-interval'} since the previous update attempt (on $prettyt{'atime'}), which failed");
|
||||
if (!$ipv4 && !opt('verbose')) {
|
||||
|
@ -3537,7 +3492,6 @@ sub nic_updateable {
|
|||
}
|
||||
}
|
||||
|
||||
$config{$host}{'warned-min-error-interval'} = $now;
|
||||
$recap{$host}{'warned-min-error-interval'} = $now;
|
||||
|
||||
} else {
|
||||
|
@ -3548,15 +3502,14 @@ sub nic_updateable {
|
|||
if (($recap{$host}{'status-ipv6'} // '') eq 'good' &&
|
||||
!interval_expired($host, 'mtime', 'min-interval')) {
|
||||
warning("skipped update from $previpv6 to $ipv6 because it has been less than $prettyi{'min-interval'} since the previous update (on $prettyt{'mtime'})")
|
||||
if opt('verbose') || !($config{$host}{'warned-min-interval'} // 0);
|
||||
if opt('verbose') || !($recap{$host}{'warned-min-interval'} // 0);
|
||||
|
||||
$config{$host}{'warned-min-interval'} = $now;
|
||||
$recap{$host}{'warned-min-interval'} = $now;
|
||||
|
||||
} elsif (($recap{$host}{'status-ipv6'} // '') ne 'good' &&
|
||||
!interval_expired($host, 'atime', 'min-error-interval')) {
|
||||
|
||||
if (opt('verbose') || (!$config{$host}{'warned-min-error-interval'} &&
|
||||
if (opt('verbose') || (!$recap{$host}{'warned-min-error-interval'} &&
|
||||
($warned_ipv6{$host} // 0) < $inv_ip_warn_count)) {
|
||||
warning("skipped update from $previpv6 to $ipv6 because it has been less than $prettyi{'min-error-interval'} since the previous update attempt (on $prettyt{'atime'}, which failed");
|
||||
if (!$ipv6 && !opt('verbose')) {
|
||||
|
@ -3566,7 +3519,6 @@ sub nic_updateable {
|
|||
}
|
||||
}
|
||||
|
||||
$config{$host}{'warned-min-error-interval'} = $now;
|
||||
$recap{$host}{'warned-min-error-interval'} = $now;
|
||||
|
||||
} else {
|
||||
|
@ -3712,16 +3664,16 @@ sub nic_dyndns1_update {
|
|||
}
|
||||
|
||||
if ($return_code ne 'NOERROR' || $error_code ne 'NOERROR' || !$title) {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
$title = 'incomplete response from ' . opt('server', $h) unless $title;
|
||||
warning("SENT: %s", $url) unless opt('verbose');
|
||||
warning("REPLIED: %s", $reply);
|
||||
failed($title);
|
||||
next;
|
||||
}
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
success("$return_code: IP address set to $ip ($title)");
|
||||
}
|
||||
}
|
||||
|
@ -3868,8 +3820,8 @@ sub nic_dyndns2_update {
|
|||
warning("$status: $errors{$status}");
|
||||
$status = 'good';
|
||||
}
|
||||
$config{$h}{'status-ipv4'} = $status if $ipv4;
|
||||
$config{$h}{'status-ipv6'} = $status if $ipv6;
|
||||
$recap{$h}{'status-ipv4'} = $status if $ipv4;
|
||||
$recap{$h}{'status-ipv6'} = $status if $ipv6;
|
||||
if ($status ne 'good') {
|
||||
if (exists($errors{$status})) {
|
||||
failed("$status: $errors{$status}");
|
||||
|
@ -3887,9 +3839,9 @@ sub nic_dyndns2_update {
|
|||
# some services do not return the IP; and (2) comparison is brittle (e.g.,
|
||||
# 192.000.002.001 vs. 192.0.2.1) and false errors could cause high load on the service
|
||||
# (an update attempt every min-error-interval instead of every max-interval).
|
||||
$config{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$config{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$recap{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
success("IPv4 address set to $ipv4") if $ipv4;
|
||||
success("IPv6 address set to $ipv6") if $ipv6;
|
||||
}
|
||||
|
@ -3970,7 +3922,7 @@ sub dnsexit2_update_host {
|
|||
my $ip = delete($config{$h}{"wantipv$ipv"}) or next;
|
||||
$ips{$ipv} = $ip;
|
||||
info("updating IPv$ipv address to $ip");
|
||||
$config{$h}{"status-ipv$ipv"} = 'failed';
|
||||
$recap{$h}{"status-ipv$ipv"} = 'failed';
|
||||
push(@updates, {
|
||||
name => $name,
|
||||
type => ($ipv eq '6') ? 'AAAA' : 'A',
|
||||
|
@ -4036,11 +3988,11 @@ sub dnsexit2_update_host {
|
|||
return;
|
||||
}
|
||||
success($message);
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
keys(%ips); # Reset internal iterator.
|
||||
while (my ($ipv, $ip) = each(%ips)) {
|
||||
$config{$h}{"ipv$ipv"} = $ip;
|
||||
$config{$h}{"status-ipv$ipv"} = 'good';
|
||||
$recap{$h}{"ipv$ipv"} = $ip;
|
||||
$recap{$h}{"status-ipv$ipv"} = 'good';
|
||||
success("updated IPv$ipv address to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -4100,27 +4052,27 @@ sub nic_noip_update {
|
|||
for my $ip (split_by_comma($returnedips)) {
|
||||
next if (!$ip);
|
||||
my $ipv = ($ip eq ($ipv6 // '')) ? '6' : '4';
|
||||
$config{$h}{"status-ipv$ipv"} = $status;
|
||||
$recap{$h}{"status-ipv$ipv"} = $status;
|
||||
}
|
||||
|
||||
if ($status eq 'good') {
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
for my $ip (split_by_comma($returnedips)) {
|
||||
next if (!$ip);
|
||||
my $ipv = ($ip eq ($ipv6 // '')) ? '6' : '4';
|
||||
$config{$h}{"ipv$ipv"} = $ip;
|
||||
$recap{$h}{"ipv$ipv"} = $ip;
|
||||
success("$status: IPv$ipv address set to $ip");
|
||||
}
|
||||
|
||||
} elsif (exists $errors{$status}) {
|
||||
if ($status eq 'nochg') {
|
||||
warning("$status: $errors{$status}");
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
for my $ip (split_by_comma($returnedips)) {
|
||||
next if (!$ip);
|
||||
my $ipv = ($ip eq ($ipv6 // '')) ? '6' : '4';
|
||||
$config{$h}{"ipv$ipv"} = $ip;
|
||||
$config{$h}{"status-ipv$ipv"} = 'good';
|
||||
$recap{$h}{"ipv$ipv"} = $ip;
|
||||
$recap{$h}{"status-ipv$ipv"} = 'good';
|
||||
}
|
||||
} else {
|
||||
failed("$status: $errors{$status}");
|
||||
|
@ -4135,7 +4087,7 @@ sub nic_noip_update {
|
|||
($scale, $units) = (60*60, 'hours') if $units eq 'h';
|
||||
|
||||
$sec = $wait * $scale;
|
||||
$config{$h}{'wtime'} = $now + $sec;
|
||||
$recap{$h}{'wtime'} = $now + $sec;
|
||||
warning("$status: wait $wait $units before further updates");
|
||||
|
||||
} else {
|
||||
|
@ -4236,13 +4188,13 @@ sub nic_dslreports1_update {
|
|||
}
|
||||
|
||||
if ($return_code !~ /NOERROR/) {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
failed($reply);
|
||||
next;
|
||||
}
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
success("$return_code: IP address set to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -4291,9 +4243,9 @@ sub nic_domeneshop_update {
|
|||
password => opt('password', $h),
|
||||
);
|
||||
next if !header_ok($reply);
|
||||
$config{$h}{"ipv$ipv"} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{"status-ipv$ipv"} = 'good';
|
||||
$recap{$h}{"ipv$ipv"} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{"status-ipv$ipv"} = 'good';
|
||||
success("IPv$ipv address set to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -4381,14 +4333,14 @@ sub nic_zoneedit1_update {
|
|||
$status_ip = $var{'IP'} if exists $var{'IP'};
|
||||
|
||||
if ($status eq 'SUCCESS' || ($status eq 'ERROR' && $var{'CODE'} eq '707')) {
|
||||
$config{$h}{'ip'} = $status_ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $status_ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
|
||||
success("IP address set to $ip ($status_code: $status_text)");
|
||||
|
||||
} else {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
failed("$status_code: $status_text");
|
||||
}
|
||||
shift @hosts;
|
||||
|
@ -4491,7 +4443,7 @@ sub nic_easydns_update {
|
|||
# values are considered to be failures and will result in frequent retries (every
|
||||
# min-error-interval, which defaults to 5m).
|
||||
$status = 'good' if ($status // '') =~ qr/^NOERROR|OK$/;
|
||||
$config{$h}{"status-ipv$ipv"} = $status;
|
||||
$recap{$h}{"status-ipv$ipv"} = $status;
|
||||
if ($status ne 'good') {
|
||||
if (exists $errors{$status}) {
|
||||
failed("$status: $errors{$status}");
|
||||
|
@ -4500,8 +4452,8 @@ sub nic_easydns_update {
|
|||
}
|
||||
next;
|
||||
}
|
||||
$config{$h}{"ipv$ipv"} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$recap{$h}{"ipv$ipv"} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
success("IPv$ipv address set to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -4568,12 +4520,12 @@ sub nic_namecheap_update {
|
|||
|
||||
my @reply = split /\n/, $reply;
|
||||
if (grep /<ErrCount>0/i, @reply) {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
success("IP address set to $ip");
|
||||
} else {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
failed("invalid reply: $reply");
|
||||
}
|
||||
}
|
||||
|
@ -4739,7 +4691,7 @@ sub nic_nfsn_update {
|
|||
if ($h eq $zone) {
|
||||
$name = '';
|
||||
} elsif ($h !~ /$zone$/) {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
failed("$h is outside zone $zone");
|
||||
next;
|
||||
} else {
|
||||
|
@ -4754,7 +4706,7 @@ sub nic_nfsn_update {
|
|||
my $list_body = encode_www_form_urlencoded({name => $name, type => 'A'});
|
||||
my $list_resp = nic_nfsn_make_request($h, $list_path, 'POST', $list_body);
|
||||
if (!header_ok($list_resp)) {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
nic_nfsn_handle_error($list_resp, $h);
|
||||
next;
|
||||
}
|
||||
|
@ -4762,7 +4714,7 @@ sub nic_nfsn_update {
|
|||
$list_resp =~ s/^.*?\n\n//s; # Strip header
|
||||
my $list = eval { decode_json($list_resp) };
|
||||
if ($@) {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
failed("JSON decoding failure");
|
||||
next;
|
||||
}
|
||||
|
@ -4779,7 +4731,7 @@ sub nic_nfsn_update {
|
|||
my $rm_resp = nic_nfsn_make_request($h, $rm_path,
|
||||
'POST', $rm_body);
|
||||
if (!header_ok($rm_resp)) {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
nic_nfsn_handle_error($rm_resp, $h);
|
||||
next;
|
||||
}
|
||||
|
@ -4794,12 +4746,12 @@ sub nic_nfsn_update {
|
|||
my $add_resp = nic_nfsn_make_request($h, $add_path, 'POST',
|
||||
$add_body);
|
||||
if (header_ok($add_resp)) {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
success("IP address set to $ip");
|
||||
} else {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
nic_nfsn_handle_error($add_resp, $h);
|
||||
}
|
||||
}
|
||||
|
@ -4903,11 +4855,11 @@ sub nic_njalla_update {
|
|||
}
|
||||
}
|
||||
if ($status eq 'good') {
|
||||
$config{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$config{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$recap{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$recap{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
}
|
||||
$config{$h}{'status-ipv4'} = $status if $ipv4;
|
||||
$config{$h}{'status-ipv6'} = $status if $ipv6;
|
||||
$recap{$h}{'status-ipv4'} = $status if $ipv4;
|
||||
$recap{$h}{'status-ipv6'} = $status if $ipv6;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4968,12 +4920,12 @@ sub nic_sitelutions_update {
|
|||
|
||||
my @reply = split /\n/, $reply;
|
||||
if (grep /success/i, @reply) {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
success("IP address set to $ip");
|
||||
} else {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
warning("SENT: %s", $url) unless opt('verbose');
|
||||
warning("REPLIED: %s", $reply);
|
||||
failed("invalid reply");
|
||||
|
@ -5075,8 +5027,8 @@ sub nic_freedns_update {
|
|||
my $ipv6 = delete $config{$h}{'wantipv6'};
|
||||
|
||||
if ($record_list_error ne '') {
|
||||
$config{$h}{'status-ipv4'} = 'failed' if ($ipv4);
|
||||
$config{$h}{'status-ipv6'} = 'failed' if ($ipv6);
|
||||
$recap{$h}{'status-ipv4'} = 'failed' if ($ipv4);
|
||||
$recap{$h}{'status-ipv6'} = 'failed' if ($ipv6);
|
||||
failed($record_list_error);
|
||||
next;
|
||||
}
|
||||
|
@ -5094,12 +5046,12 @@ sub nic_freedns_update {
|
|||
}
|
||||
|
||||
info("setting IP address to $ip");
|
||||
$config{$h}{"status-ipv$ipv"} = 'failed';
|
||||
$recap{$h}{"status-ipv$ipv"} = 'failed';
|
||||
|
||||
if ($ip eq $rec->[1]) {
|
||||
$config{$h}{"ipv$ipv"} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{"status-ipv$ipv"} = 'good';
|
||||
$recap{$h}{"ipv$ipv"} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{"status-ipv$ipv"} = 'good';
|
||||
success("update not necessary, '$type' record already set to $ip")
|
||||
if (!$daemon || opt('verbose'));
|
||||
} else {
|
||||
|
@ -5113,9 +5065,9 @@ sub nic_freedns_update {
|
|||
if (header_ok($reply)) {
|
||||
$reply =~ s/^.*?\n\n//s; # Strip the headers.
|
||||
if ($reply =~ /Updated.*$h.*to.*$ip/) {
|
||||
$config{$h}{"ipv$ipv"} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{"status-ipv$ipv"} = 'good';
|
||||
$recap{$h}{"ipv$ipv"} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{"status-ipv$ipv"} = 'good';
|
||||
success("IPv$ipv address set to $ip");
|
||||
} else {
|
||||
warning("SENT: %s", $url_tmpl) unless opt('verbose');
|
||||
|
@ -5191,8 +5143,8 @@ sub nic_1984_update {
|
|||
next;
|
||||
}
|
||||
|
||||
$config{$host}{'status'} = 'good';
|
||||
$config{$host}{'ip'} = $ip;
|
||||
$recap{$host}{'status'} = 'good';
|
||||
$recap{$host}{'ip'} = $ip;
|
||||
if ($response->{msg} =~ /unaltered/) {
|
||||
success("skipped: IP was already set to $response->{ip}");
|
||||
} else {
|
||||
|
@ -5259,12 +5211,12 @@ sub nic_changeip_update {
|
|||
|
||||
my @reply = split /\n/, $reply;
|
||||
if (grep /success/i, @reply) {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
success("IP address set to $ip");
|
||||
} else {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
warning("SENT: %s", $url) unless opt('verbose');
|
||||
warning("REPLIED: %s", $reply);
|
||||
failed("invalid reply");
|
||||
|
@ -5380,9 +5332,9 @@ sub nic_godaddy_update {
|
|||
failed($msg);
|
||||
next;
|
||||
}
|
||||
$config{$h}{"ipv$ipv"} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{"status-ipv$ipv"} = 'good';
|
||||
$recap{$h}{"ipv$ipv"} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{"status-ipv$ipv"} = 'good';
|
||||
success("updated successfully to $ip (status: $code)");
|
||||
}
|
||||
}
|
||||
|
@ -5444,7 +5396,7 @@ sub nic_henet_update {
|
|||
my ($line) = split(/\n/, $body, 2);
|
||||
my ($status, $returnedip) = split(/ /, lc($line));
|
||||
$status = 'good' if $status eq 'nochg';
|
||||
$config{$h}{"status-ipv$ipv"} = $status;
|
||||
$recap{$h}{"status-ipv$ipv"} = $status;
|
||||
if ($status ne 'good') {
|
||||
if (exists($errors{$status})) {
|
||||
failed("$status: $errors{$status}");
|
||||
|
@ -5454,8 +5406,8 @@ sub nic_henet_update {
|
|||
next;
|
||||
}
|
||||
success("$status: IPv$ipv address set to $returnedip");
|
||||
$config{$h}{"ipv$ipv"} = $returnedip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$recap{$h}{"ipv$ipv"} = $returnedip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5524,8 +5476,8 @@ sub nic_mythicdyn_update {
|
|||
);
|
||||
my $ok = header_ok($reply);
|
||||
if ($ok) {
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{"status-ipv$mythver"} = "good";
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{"status-ipv$mythver"} = "good";
|
||||
|
||||
success("IPv$mythver updated successfully");
|
||||
}
|
||||
|
@ -5634,12 +5586,12 @@ EoINSTR4
|
|||
my $status = pipecmd($command, $instructions);
|
||||
if ($status eq 1) {
|
||||
for (@hosts) {
|
||||
$config{$_}{'mtime'} = $now;
|
||||
$recap{$_}{'mtime'} = $now;
|
||||
for my $ip ($ipv4, $ipv6) {
|
||||
next if (!$ip);
|
||||
my $ipv = ($ip eq ($ipv6 // '')) ? '6' : '4';
|
||||
$config{$_}{"ipv$ipv"} = $ip;
|
||||
$config{$_}{"status-ipv$ipv"} = 'good';
|
||||
$recap{$_}{"ipv$ipv"} = $ip;
|
||||
$recap{$_}{"status-ipv$ipv"} = 'good';
|
||||
}
|
||||
}
|
||||
success("IPv4 address set to $ipv4") if $ipv4;
|
||||
|
@ -5751,7 +5703,7 @@ sub nic_cloudflare_update {
|
|||
my $type = ($ip eq ($ipv6 // '')) ? 'AAAA' : 'A';
|
||||
|
||||
info("setting IPv$ipv address to $ip");
|
||||
$config{$domain}{"status-ipv$ipv"} = 'failed';
|
||||
$recap{$domain}{"status-ipv$ipv"} = 'failed';
|
||||
|
||||
# Get DNS 'A' or 'AAAA' record ID
|
||||
$url = "https://" . opt('server', $domain) . "/zones/$zone_id/dns_records?";
|
||||
|
@ -5790,9 +5742,9 @@ sub nic_cloudflare_update {
|
|||
$response = eval {decode_json(${^MATCH})};
|
||||
if ($response && $response->{result}) {
|
||||
success("IPv$ipv address set to $ip");
|
||||
$config{$domain}{"ipv$ipv"} = $ip;
|
||||
$config{$domain}{'mtime'} = $now;
|
||||
$config{$domain}{"status-ipv$ipv"} = 'good';
|
||||
$recap{$domain}{"ipv$ipv"} = $ip;
|
||||
$recap{$domain}{'mtime'} = $now;
|
||||
$recap{$domain}{"status-ipv$ipv"} = 'good';
|
||||
} else {
|
||||
failed("invalid json or result");
|
||||
}
|
||||
|
@ -5874,7 +5826,7 @@ sub nic_hetzner_update {
|
|||
my $type = ($ip eq ($ipv6 // '')) ? 'AAAA' : 'A';
|
||||
|
||||
info("setting IPv$ipv address to $ip");
|
||||
$config{$domain}{"status-ipv$ipv"} = 'failed';
|
||||
$recap{$domain}{"status-ipv$ipv"} = 'failed';
|
||||
|
||||
# Get DNS 'A' or 'AAAA' record ID
|
||||
$url = "https://" . opt('server', $domain) . "/records?zone_id=$zone_id";
|
||||
|
@ -5919,9 +5871,9 @@ sub nic_hetzner_update {
|
|||
$response = eval {decode_json(${^MATCH})};
|
||||
if ($response && $response->{record}) {
|
||||
success("IPv$ipv address set to $ip");
|
||||
$config{$domain}{"ipv$ipv"} = $ip;
|
||||
$config{$domain}{'mtime'} = $now;
|
||||
$config{$domain}{"status-ipv$ipv"} = 'good';
|
||||
$recap{$domain}{"ipv$ipv"} = $ip;
|
||||
$recap{$domain}{'mtime'} = $now;
|
||||
$recap{$domain}{"status-ipv$ipv"} = 'good';
|
||||
} else {
|
||||
failed("invalid json or result");
|
||||
}
|
||||
|
@ -6067,8 +6019,8 @@ sub nic_inwx_update {
|
|||
$status = 'good';
|
||||
}
|
||||
for my $h (@hosts) {
|
||||
$config{$h}{'status-ipv4'} = $status if $ipv4;
|
||||
$config{$h}{'status-ipv6'} = $status if $ipv6;
|
||||
$recap{$h}{'status-ipv4'} = $status if $ipv4;
|
||||
$recap{$h}{'status-ipv6'} = $status if $ipv6;
|
||||
}
|
||||
if ($status ne 'good') {
|
||||
if (exists($errors{$status})) {
|
||||
|
@ -6079,9 +6031,9 @@ sub nic_inwx_update {
|
|||
next;
|
||||
}
|
||||
for my $h (@hosts) {
|
||||
$config{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$config{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$recap{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
}
|
||||
success("IPv4 address set to $ipv4") if $ipv4;
|
||||
success("IPv6 address set to $ipv6") if $ipv6;
|
||||
|
@ -6181,9 +6133,9 @@ sub nic_yandex_update {
|
|||
failed("%s", $response->{error});
|
||||
next;
|
||||
}
|
||||
$config{$host}{'ip'} = $ip;
|
||||
$config{$host}{'mtime'} = $now;
|
||||
$config{$host}{'status'} = 'good';
|
||||
$recap{$host}{'ip'} = $ip;
|
||||
$recap{$host}{'mtime'} = $now;
|
||||
$recap{$host}{'status'} = 'good';
|
||||
success("updated successfully to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -6247,11 +6199,11 @@ sub nic_duckdns_update {
|
|||
next;
|
||||
}
|
||||
for my $h (@hosts) {
|
||||
$config{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$config{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status-ipv4'} = 'good' if $ipv4;
|
||||
$config{$h}{'status-ipv6'} = 'good' if $ipv6;
|
||||
$recap{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$recap{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status-ipv4'} = 'good' if $ipv4;
|
||||
$recap{$h}{'status-ipv6'} = 'good' if $ipv6;
|
||||
}
|
||||
success("IPv4 address set to $ipv4") if $ipv4;
|
||||
success("IPv6 address set to $ipv6") if $ipv6;
|
||||
|
@ -6302,9 +6254,9 @@ sub nic_freemyip_update {
|
|||
failed("server said: $body");
|
||||
next;
|
||||
}
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
success("IP address set to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -6352,9 +6304,9 @@ sub nic_ddnsfm_update {
|
|||
url => opt('server', $h) . "/update?key=" . opt('password', $h) . "&domain=$h&myip=$ip",
|
||||
);
|
||||
next if !header_ok($reply);
|
||||
$config{$h}{"ipv$ipv"} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{"status-ipv$ipv"} = 'good';
|
||||
$recap{$h}{"ipv$ipv"} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{"status-ipv$ipv"} = 'good';
|
||||
success("IPv$ipv address set to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -6401,9 +6353,9 @@ sub nic_dondominio_update {
|
|||
failed("server said: $returned");
|
||||
next;
|
||||
}
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
success("IP address set to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -6465,9 +6417,9 @@ sub nic_dnsmadeeasy_update {
|
|||
failed("server said: $err");
|
||||
next;
|
||||
}
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
success("IP address set to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -6533,16 +6485,16 @@ sub nic_ovh_update {
|
|||
my @reply = split /\n/, $reply;
|
||||
my $returned = List::Util::first { $_ =~ /good/ || $_ =~ /nochg/ } @reply;
|
||||
if ($returned) {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
if ($returned =~ /good/) {
|
||||
success("IP address set to $ip");
|
||||
} else {
|
||||
success("skipped: IP address was already set to $ip");
|
||||
}
|
||||
} else {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
failed("server said: $reply");
|
||||
}
|
||||
}
|
||||
|
@ -6678,7 +6630,7 @@ sub nic_porkbun_update {
|
|||
warning("There are multiple applicable records. Only first record is used. Overwrite all with the same content.")
|
||||
if @$records > 1;
|
||||
if ($records->[0]{'content'} eq $ip) {
|
||||
$config{$h}{"status-ipv$ipv"} = "good";
|
||||
$recap{$h}{"status-ipv$ipv"} = "good";
|
||||
success("skipped: IPv$ipv address was already set to $ip");
|
||||
next;
|
||||
}
|
||||
|
@ -6700,7 +6652,7 @@ sub nic_porkbun_update {
|
|||
}),
|
||||
);
|
||||
next if !header_ok($reply);
|
||||
$config{$h}{"status-ipv$ipv"} = "good";
|
||||
$recap{$h}{"status-ipv$ipv"} = "good";
|
||||
success("IPv$ipv address set to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -6755,14 +6707,14 @@ sub nic_cloudns_update {
|
|||
$reply =~ s/^.*?\n\n//s; # Strip the headers.
|
||||
chomp($reply);
|
||||
if ($reply eq "The record's key is wrong!" || $reply eq "Invalid request.") {
|
||||
$config{$_}{'status'} = 'failed' for @hosts;
|
||||
$recap{$_}{'status'} = 'failed' for @hosts;
|
||||
failed($reply);
|
||||
next;
|
||||
}
|
||||
# There's no documentation explaining possible return values, so we assume success.
|
||||
$config{$_}{'ip'} = $ip for @hosts;
|
||||
$config{$_}{'mtime'} = $now for @hosts;
|
||||
$config{$_}{'status'} = 'good' for @hosts;
|
||||
$recap{$_}{'ip'} = $ip for @hosts;
|
||||
$recap{$_}{'mtime'} = $now for @hosts;
|
||||
$recap{$_}{'status'} = 'good' for @hosts;
|
||||
success("IP address set to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -6811,7 +6763,7 @@ sub nic_dinahosting_update {
|
|||
password => opt('password', $h),
|
||||
url => $url,
|
||||
);
|
||||
$config{$h}{'status'} = 'failed'; # assume failure until otherwise determined
|
||||
$recap{$h}{'status'} = 'failed'; # assume failure until otherwise determined
|
||||
next if !header_ok($reply);
|
||||
$reply =~ s/^.*?\n\n//s; # Strip the headers.
|
||||
if ($reply !~ /Success/i) {
|
||||
|
@ -6822,9 +6774,9 @@ sub nic_dinahosting_update {
|
|||
failed("error $code: $message");
|
||||
next;
|
||||
}
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
success("IP address set to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -6876,20 +6828,20 @@ sub nic_directnic_update {
|
|||
(my $body = $reply) =~ s/^.*?\n\n//s;
|
||||
my $response = eval {decode_json($body)};
|
||||
if (ref($response) ne 'HASH') {
|
||||
$config{$h}{"status-ipv$ipv"} = 'bad';
|
||||
$recap{$h}{"status-ipv$ipv"} = 'bad';
|
||||
failed("response is not a JSON object:\n$body");
|
||||
next;
|
||||
}
|
||||
|
||||
if ($response->{'result'} ne 'success') {
|
||||
$config{$h}{"status-ipv$ipv"} = 'failed';
|
||||
$recap{$h}{"status-ipv$ipv"} = 'failed';
|
||||
failed("server said:\n$body");
|
||||
next;
|
||||
}
|
||||
|
||||
$config{$h}{"ipv$ipv"} = $ip;
|
||||
$config{$h}{"status-ipv$ipv"} = 'good';
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$recap{$h}{"ipv$ipv"} = $ip;
|
||||
$recap{$h}{"status-ipv$ipv"} = 'good';
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
success("IPv$ipv address set to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -6972,15 +6924,15 @@ sub nic_gandi_update {
|
|||
$reply =~ s/^.*?\n\n//s;
|
||||
my $response = eval { decode_json($reply) };
|
||||
if (ref($response) ne 'HASH') {
|
||||
$config{$h}{"status-$ipv"} = "bad";
|
||||
$recap{$h}{"status-$ipv"} = "bad";
|
||||
failed("response is not a JSON object: $reply");
|
||||
next;
|
||||
}
|
||||
if ($response->{'rrset_values'}->[0] eq $ip && (!defined(opt('ttl', $h)) ||
|
||||
$response->{'rrset_ttl'} eq opt('ttl', $h))) {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{"status-$ipv"} = "good";
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{"status-$ipv"} = "good";
|
||||
success("skipped: address was already set to $ip");
|
||||
next;
|
||||
}
|
||||
|
@ -6995,7 +6947,7 @@ sub nic_gandi_update {
|
|||
}),
|
||||
);
|
||||
if (!header_ok($reply)) {
|
||||
$config{$h}{"status-$ipv"} = "bad";
|
||||
$recap{$h}{"status-$ipv"} = "bad";
|
||||
$reply =~ s/^.*?\n\n//s;
|
||||
my $response = eval { decode_json($reply) };
|
||||
if (ref($response) eq 'HASH' && ($response->{message} // '') ne '') {
|
||||
|
@ -7005,9 +6957,9 @@ sub nic_gandi_update {
|
|||
}
|
||||
next;
|
||||
}
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{"status-$ipv"} = "good";
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{"status-$ipv"} = "good";
|
||||
success("updated successfully to $ip");
|
||||
}
|
||||
}
|
||||
|
@ -7055,12 +7007,12 @@ sub nic_keysystems_update {
|
|||
last if !header_ok($reply);
|
||||
|
||||
if ($reply =~ /code = 200/) {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
success("IP address set to $ip");
|
||||
} else {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
failed("server said: $reply");
|
||||
}
|
||||
}
|
||||
|
@ -7109,11 +7061,11 @@ sub nic_regfishde_update {
|
|||
failed("server said: $reply");
|
||||
next;
|
||||
}
|
||||
$config{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$config{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$config{$h}{'status-ipv4'} = 'good' if $ipv4;
|
||||
$config{$h}{'status-ipv6'} = 'good' if $ipv6;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$recap{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$recap{$h}{'status-ipv4'} = 'good' if $ipv4;
|
||||
$recap{$h}{'status-ipv6'} = 'good' if $ipv6;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
success("IPv4 address set to $ipv4") if $ipv4;
|
||||
success("IPv6 address set to $ipv6") if $ipv6;
|
||||
}
|
||||
|
@ -7183,12 +7135,12 @@ sub nic_enom_update {
|
|||
my @reply = split /\n/, $reply;
|
||||
|
||||
if (grep /Done=true/i, @reply) {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$recap{$h}{'ip'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status'} = 'good';
|
||||
success("IP address set to $ip");
|
||||
} else {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
warning("SENT: %s", $url) unless opt('verbose');
|
||||
warning("REPLIED: %s", $reply);
|
||||
failed("invalid reply");
|
||||
|
@ -7252,7 +7204,7 @@ sub nic_digitalocean_update_one {
|
|||
|
||||
my $list = eval { decode_json($list_resp) };
|
||||
if ($@) {
|
||||
$config{$h}{"status-$ipv"} = 'failed';
|
||||
$recap{$h}{"status-$ipv"} = 'failed';
|
||||
failed("listing $ipv: JSON decoding failure");
|
||||
return;
|
||||
}
|
||||
|
@ -7261,7 +7213,7 @@ sub nic_digitalocean_update_one {
|
|||
unless ((ref($elem) eq 'HASH') &&
|
||||
(ref ($elem = $elem->{'domain_records'}) eq 'ARRAY') &&
|
||||
(@$elem == 1 && ref ($elem = $elem->[0]) eq 'HASH')) {
|
||||
$config{$h}{"status-$ipv"} = 'failed';
|
||||
$recap{$h}{"status-$ipv"} = 'failed';
|
||||
failed("listing $ipv: no record, multiple records, or malformed JSON");
|
||||
return;
|
||||
}
|
||||
|
@ -7283,9 +7235,9 @@ sub nic_digitalocean_update_one {
|
|||
return if !header_ok($update_resp);
|
||||
}
|
||||
|
||||
$config{$h}{"status-$ipv"} = 'good';
|
||||
$config{$h}{"ip-$ipv"} = $ip;
|
||||
$config{$h}{"mtime"} = $now;
|
||||
$recap{$h}{"status-$ipv"} = 'good';
|
||||
$recap{$h}{"ip-$ipv"} = $ip;
|
||||
$recap{$h}{"mtime"} = $now;
|
||||
}
|
||||
|
||||
sub nic_digitalocean_update {
|
||||
|
@ -7393,9 +7345,9 @@ sub nic_infomaniak_update {
|
|||
next;
|
||||
}
|
||||
success($msg);
|
||||
$config{$h}{"ipv$v"} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{"status-ipv$v"} = 'good';
|
||||
$recap{$h}{"ipv$v"} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{"status-ipv$v"} = 'good';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7417,11 +7369,11 @@ sub nic_emailonly_update {
|
|||
logmsg(email => 1, raw => 1, join("\n", 'Host IP addresses:', map({
|
||||
my $ipv4 = delete($config{$_}{'wantipv4'});
|
||||
my $ipv6 = delete($config{$_}{'wantipv6'});
|
||||
$config{$_}{'status-ipv4'} = 'good' if $ipv4;
|
||||
$config{$_}{'status-ipv6'} = 'good' if $ipv6;
|
||||
$config{$_}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$config{$_}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$config{$_}{'mtime'} = $now;
|
||||
$recap{$_}{'status-ipv4'} = 'good' if $ipv4;
|
||||
$recap{$_}{'status-ipv6'} = 'good' if $ipv6;
|
||||
$recap{$_}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$recap{$_}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$recap{$_}{'mtime'} = $now;
|
||||
sprintf('%30s %s', $_, join(' ', grep(defined($_), $ipv4, $ipv6)));
|
||||
} @_)));
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ my @test_cases = (
|
|||
{
|
||||
desc => 'IPv4, good',
|
||||
cfg => {h1 => {urlv4 => "$hostname/dns/gateway/abc/", wantipv4 => '192.0.2.1'}},
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
},
|
||||
wantlogs => [
|
||||
|
@ -62,7 +62,7 @@ my @test_cases = (
|
|||
{
|
||||
desc => 'IPv4, failed',
|
||||
cfg => {h1 => {urlv4 => "$hostname/dns/gateway/bad_token/", wantipv4 => '192.0.2.1'}},
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'failed'},
|
||||
},
|
||||
wantlogs => [
|
||||
|
@ -72,7 +72,7 @@ my @test_cases = (
|
|||
{
|
||||
desc => 'IPv4, bad',
|
||||
cfg => {h1 => {urlv4 => "$hostname/bad/path/", wantipv4 => '192.0.2.1'}},
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'bad'},
|
||||
},
|
||||
wantlogs => [
|
||||
|
@ -82,7 +82,7 @@ my @test_cases = (
|
|||
{
|
||||
desc => 'IPv4, unexpected response',
|
||||
cfg => {h1 => {urlv4 => "$hostname/unexpected/path/", wantipv4 => '192.0.2.1'}},
|
||||
wantstatus => {h1 => {}},
|
||||
wantrecap => {},
|
||||
wantlogs => [
|
||||
{label => 'FAILED', ctx => ['h1'], msg => qr/400 Bad Request/},
|
||||
],
|
||||
|
@ -90,7 +90,7 @@ my @test_cases = (
|
|||
{
|
||||
desc => 'IPv4, no urlv4',
|
||||
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
||||
wantstatus => {h1 => {}},
|
||||
wantrecap => {},
|
||||
wantlogs => [
|
||||
{label => 'FAILED', ctx => ['h1'], msg => qr/missing urlv4 option/},
|
||||
],
|
||||
|
@ -98,7 +98,7 @@ my @test_cases = (
|
|||
{
|
||||
desc => 'IPv6, good',
|
||||
cfg => {h1 => {urlv6 => "$hostname/dns/gateway/abc/", wantipv6 => '2001:db8::1'}},
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv6' => 'good', 'ipv6' => '2001:db8::1', 'mtime' => $ddclient::now},
|
||||
},
|
||||
wantlogs => [
|
||||
|
@ -113,7 +113,7 @@ my @test_cases = (
|
|||
wantipv4 => '192.0.2.1',
|
||||
wantipv6 => '2001:db8::1',
|
||||
}},
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1',
|
||||
'status-ipv6' => 'good', 'ipv6' => '2001:db8::1',
|
||||
'mtime' => $ddclient::now},
|
||||
|
@ -132,7 +132,7 @@ my @test_cases = (
|
|||
wantipv6 => '2001:db8::1',
|
||||
}},
|
||||
wantips => {h1 => {wantipv4 => '192.0.2.1', wantipv6 => '2001:db8::1'}},
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'failed',
|
||||
'status-ipv6' => 'good', 'ipv6' => '2001:db8::1',
|
||||
'mtime' => $ddclient::now},
|
||||
|
@ -152,20 +152,14 @@ for my $tc (@test_cases) {
|
|||
local $ddclient::globals{verbose} = 1;
|
||||
my $l = Logger->new($ddclient::_l);
|
||||
local %ddclient::config = %{$tc->{cfg}};
|
||||
local %ddclient::recap;
|
||||
{
|
||||
local $ddclient::_l = $l;
|
||||
ddclient::nic_directnic_update(sort(keys(%{$tc->{cfg}})));
|
||||
}
|
||||
# These are the properties in %ddclient::config to check against $tc->{wantstatus}.
|
||||
my %statuskeys = map(($_ => undef), qw(atime ip ipv4 ipv6 mtime status status-ipv4 status-ipv6
|
||||
wantip wantipv4 wantipv6 wtime));
|
||||
my %gotstatus;
|
||||
for my $h (keys(%ddclient::config)) {
|
||||
$gotstatus{$h} = {map(($_ => $ddclient::config{$h}{$_}),
|
||||
grep(exists($statuskeys{$_}), keys(%{$ddclient::config{$h}})))};
|
||||
}
|
||||
is_deeply(\%gotstatus, $tc->{wantstatus}, "$tc->{desc}: status")
|
||||
or diag(ddclient::repr(\%ddclient::config, Names => ['*ddclient::config']));
|
||||
is_deeply(\%ddclient::recap, $tc->{wantrecap}, "$tc->{desc}: recap")
|
||||
or diag(ddclient::repr(Values => [\%ddclient::recap, $tc->{wantrecap}],
|
||||
Names => ['*got', '*want']));
|
||||
$tc->{wantlogs} //= [];
|
||||
subtest("$tc->{desc}: logs" => sub {
|
||||
my @got = @{$l->{logs}};
|
||||
|
|
|
@ -45,7 +45,7 @@ my @test_cases = (
|
|||
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
||||
resp => ['good'],
|
||||
wantquery => 'hostname=h1&myip=192.0.2.1',
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
},
|
||||
wantlogs => [
|
||||
|
@ -57,7 +57,7 @@ my @test_cases = (
|
|||
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
||||
resp => ['nochg'],
|
||||
wantquery => 'hostname=h1&myip=192.0.2.1',
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
},
|
||||
wantlogs => [
|
||||
|
@ -70,7 +70,7 @@ my @test_cases = (
|
|||
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
||||
resp => ['nohost'],
|
||||
wantquery => 'hostname=h1&myip=192.0.2.1',
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'nohost'},
|
||||
},
|
||||
wantlogs => [
|
||||
|
@ -82,7 +82,7 @@ my @test_cases = (
|
|||
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
||||
resp => ['WAT'],
|
||||
wantquery => 'hostname=h1&myip=192.0.2.1',
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'WAT'},
|
||||
},
|
||||
wantlogs => [
|
||||
|
@ -100,7 +100,7 @@ my @test_cases = (
|
|||
'good',
|
||||
],
|
||||
wantquery => 'hostname=h1,h2&myip=192.0.2.1',
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
},
|
||||
|
@ -122,7 +122,7 @@ my @test_cases = (
|
|||
'dnserr',
|
||||
],
|
||||
wantquery => 'hostname=h1,h2,h3&myip=192.0.2.1',
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
h3 => {'status-ipv4' => 'dnserr'},
|
||||
|
@ -139,7 +139,7 @@ my @test_cases = (
|
|||
cfg => {h1 => {wantipv6 => '2001:db8::1'}},
|
||||
resp => ['good'],
|
||||
wantquery => 'hostname=h1&myip=2001:db8::1',
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv6' => 'good', 'ipv6' => '2001:db8::1', 'mtime' => $ddclient::now},
|
||||
},
|
||||
wantlogs => [
|
||||
|
@ -151,7 +151,7 @@ my @test_cases = (
|
|||
cfg => {h1 => {wantipv4 => '192.0.2.1', wantipv6 => '2001:db8::1'}},
|
||||
resp => ['good'],
|
||||
wantquery => 'hostname=h1&myip=192.0.2.1,2001:db8::1',
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1',
|
||||
'status-ipv6' => 'good', 'ipv6' => '2001:db8::1',
|
||||
'mtime' => $ddclient::now},
|
||||
|
@ -173,7 +173,7 @@ my @test_cases = (
|
|||
'WAT',
|
||||
],
|
||||
wantquery => 'hostname=h1,h2&myip=192.0.2.1',
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
},
|
||||
|
@ -191,7 +191,7 @@ my @test_cases = (
|
|||
},
|
||||
resp => ['abuse'],
|
||||
wantquery => 'hostname=h1,h2&myip=192.0.2.1',
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'abuse'},
|
||||
h2 => {'status-ipv4' => 'abuse'},
|
||||
},
|
||||
|
@ -208,7 +208,7 @@ my @test_cases = (
|
|||
},
|
||||
resp => ['good'],
|
||||
wantquery => 'hostname=h1,h2&myip=192.0.2.1',
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
},
|
||||
|
@ -230,7 +230,7 @@ my @test_cases = (
|
|||
'nochg',
|
||||
],
|
||||
wantquery => 'hostname=h1,h2,h3&myip=192.0.2.1',
|
||||
wantstatus => {
|
||||
wantrecap => {
|
||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||
h3 => {'status-ipv4' => 'unknown'},
|
||||
|
@ -252,6 +252,7 @@ for my $tc (@test_cases) {
|
|||
local $ddclient::globals{verbose} = 1;
|
||||
my $l = Logger->new($ddclient::_l);
|
||||
local %ddclient::config;
|
||||
local %ddclient::recap;
|
||||
$ddclient::config{$_} = {
|
||||
login => 'username',
|
||||
password => 'password',
|
||||
|
@ -267,18 +268,9 @@ for my $tc (@test_cases) {
|
|||
local $ddclient::_l = $l;
|
||||
ddclient::nic_dyndns2_update(sort(keys(%{$tc->{cfg}})));
|
||||
}
|
||||
# These are the properties in %ddclient::config to check against $tc->{wantstatus}. Keys are
|
||||
# explicitly listed here rather than read from $tc->{wantstatus} to ensure that entries that
|
||||
# should not exist (e.g., wantipv4 and friends) are deleted (or never set).
|
||||
my %statuskeys = map(($_ => undef), qw(atime ip ipv4 ipv6 mtime status status-ipv4 status-ipv6
|
||||
wantip wantipv4 wantipv6 wtime));
|
||||
my %gotstatus;
|
||||
for my $h (keys(%ddclient::config)) {
|
||||
$gotstatus{$h} = {map(($_ => $ddclient::config{$h}{$_}),
|
||||
grep(exists($statuskeys{$_}), keys(%{$ddclient::config{$h}})))};
|
||||
}
|
||||
is_deeply(\%gotstatus, $tc->{wantstatus}, "$tc->{desc}: status")
|
||||
or diag(ddclient::repr(\%ddclient::config, Names => ['*ddclient::config']));
|
||||
is_deeply(\%ddclient::recap, $tc->{wantrecap}, "$tc->{desc}: recap")
|
||||
or diag(ddclient::repr(Values => [\%ddclient::recap, $tc->{wantrecap}],
|
||||
Names => ['*got', '*want']));
|
||||
$tc->{wantlogs} //= [];
|
||||
subtest("$tc->{desc}: logs" => sub {
|
||||
my @got = @{$l->{logs}};
|
||||
|
|
119
t/read_recap.pl
119
t/read_recap.pl
|
@ -1,6 +1,5 @@
|
|||
use Test::More;
|
||||
use File::Temp;
|
||||
use Scalar::Util qw(refaddr);
|
||||
SKIP: { eval { require Test::Warnings; } or skip($@, 1); }
|
||||
eval { require 'ddclient'; } or BAIL_OUT($@);
|
||||
|
||||
|
@ -9,42 +8,26 @@ local $ddclient::globals{verbose} = 1;
|
|||
local %ddclient::protocols = (
|
||||
protocol_a => {
|
||||
variables => {
|
||||
'host' => {type => ddclient::T_STRING(), recap => 1},
|
||||
'mtime' => {type => ddclient::T_NUMBER(), recap => 1},
|
||||
'atime' => {type => ddclient::T_NUMBER(), recap => 1},
|
||||
'wtime' => {type => ddclient::T_NUMBER(), recap => 1},
|
||||
'ip' => {type => ddclient::T_IP(), recap => 1},
|
||||
'ipv4' => {type => ddclient::T_IPV4(), recap => 1},
|
||||
'ipv6' => {type => ddclient::T_IPV6(), recap => 1},
|
||||
'status' => {type => ddclient::T_ANY(), recap => 1},
|
||||
'status-ipv4' => {type => ddclient::T_ANY(), recap => 1},
|
||||
'status-ipv6' => {type => ddclient::T_ANY(), recap => 1},
|
||||
'warned-min-error-interval' => {type => ddclient::T_ANY(), recap => 1},
|
||||
'warned-min-interval' => {type => ddclient::T_ANY(), recap => 1},
|
||||
|
||||
'var_a' => {type => ddclient::T_BOOL(), recap => 1},
|
||||
host => {type => ddclient::T_STRING(), recap => 1},
|
||||
var_a => {type => ddclient::T_BOOL(), recap => 1},
|
||||
},
|
||||
},
|
||||
protocol_b => {
|
||||
variables => {
|
||||
'host' => {type => ddclient::T_STRING(), recap => 1},
|
||||
'mtime' => {type => ddclient::T_NUMBER()}, # Intentionally not a recap var.
|
||||
'var_b' => {type => ddclient::T_NUMBER(), recap => 1},
|
||||
host => {type => ddclient::T_STRING(), recap => 1},
|
||||
var_b => {type => ddclient::T_NUMBER(), recap => 1},
|
||||
var_b_non_recap => {type => ddclient::T_ANY()},
|
||||
},
|
||||
},
|
||||
);
|
||||
local %ddclient::variables =
|
||||
(merged => {map({ %{$ddclient::protocols{$_}{variables}}; } sort(keys(%ddclient::protocols)))});
|
||||
|
||||
# Sentinel value that means "this hash entry should be deleted."
|
||||
my $DOES_NOT_EXIST = [];
|
||||
|
||||
my @test_cases = (
|
||||
{
|
||||
desc => "ok value",
|
||||
cachefile_lines => ["var_a=yes host_a"],
|
||||
want => {host_a => {host => 'host_a', var_a => 1}},
|
||||
# No config changes are expected because `var_a` is not a "status" recap var.
|
||||
},
|
||||
{
|
||||
desc => "unknown host",
|
||||
|
@ -71,80 +54,16 @@ my @test_cases = (
|
|||
host_a => {host => 'host_a', var_a => 1},
|
||||
host_b => {host => 'host_b', var_b => 123},
|
||||
},
|
||||
# No config changes are expected because `var_a` and `var_b` are not "status" recap vars.
|
||||
},
|
||||
{
|
||||
desc => "used to be status vars",
|
||||
cachefile_lines => ["ip=192.0.2.1,status=good host_a"],
|
||||
want => {host_a => {host => 'host_a', ip => '192.0.2.1', status => 'good'}},
|
||||
# No config changes are expected because `ip` and `status` are no longer "status" recap
|
||||
# vars.
|
||||
},
|
||||
{
|
||||
desc => "status vars",
|
||||
cachefile_lines => ["mtime=1234567890,atime=1234567891,wtime=1234567892,ipv4=192.0.2.1,ipv6=2001:db8::1,status-ipv4=good,status-ipv6=bad,warned-min-interval=1234567893,warned-min-error-interval=1234567894 host_a"],
|
||||
want => {host_a => {
|
||||
'host' => 'host_a',
|
||||
'mtime' => 1234567890,
|
||||
'atime' => 1234567891,
|
||||
'wtime' => 1234567892,
|
||||
'ipv4' => '192.0.2.1',
|
||||
'ipv6' => '2001:db8::1',
|
||||
'status-ipv4' => 'good',
|
||||
'status-ipv6' => 'bad',
|
||||
'warned-min-interval' => 1234567893,
|
||||
'warned-min-error-interval' => 1234567894,
|
||||
}},
|
||||
want_config_changes => {host_a => {
|
||||
'mtime' => 1234567890,
|
||||
'atime' => 1234567891,
|
||||
'wtime' => 1234567892,
|
||||
'ipv4' => '192.0.2.1',
|
||||
'ipv6' => '2001:db8::1',
|
||||
'status-ipv4' => 'good',
|
||||
'status-ipv6' => 'bad',
|
||||
'warned-min-interval' => 1234567893,
|
||||
'warned-min-error-interval' => 1234567894,
|
||||
}},
|
||||
},
|
||||
{
|
||||
desc => "unset status var clears config",
|
||||
cachefile_lines => ["host_a"],
|
||||
config => {host_a => {
|
||||
'mtime' => 1234567890,
|
||||
'atime' => 1234567891,
|
||||
'wtime' => 1234567892,
|
||||
'ipv4' => '192.0.2.1',
|
||||
'ipv6' => '2001:db8::1',
|
||||
'status-ipv4' => 'good',
|
||||
'status-ipv6' => 'bad',
|
||||
'warned-min-interval' => 1234567893,
|
||||
'warned-min-error-interval' => 1234567894,
|
||||
'var_a' => 1,
|
||||
}},
|
||||
want => {host_a => {host => 'host_a'}},
|
||||
want_config_changes => {host_a => {
|
||||
'mtime' => $DOES_NOT_EXIST,
|
||||
'atime' => $DOES_NOT_EXIST,
|
||||
'wtime' => $DOES_NOT_EXIST,
|
||||
'ipv4' => $DOES_NOT_EXIST,
|
||||
'ipv6' => $DOES_NOT_EXIST,
|
||||
'status-ipv4' => $DOES_NOT_EXIST,
|
||||
'status-ipv6' => $DOES_NOT_EXIST,
|
||||
'warned-min-interval' => $DOES_NOT_EXIST,
|
||||
'warned-min-error-interval' => $DOES_NOT_EXIST,
|
||||
# `var_a` should remain untouched.
|
||||
}},
|
||||
},
|
||||
{
|
||||
desc => "non-recap vars are not loaded to %recap or copied to %config",
|
||||
cachefile_lines => ["mtime=1234567890 host_b"],
|
||||
desc => "non-recap vars are not loaded to %recap",
|
||||
cachefile_lines => ["var_b_non_recap=foo host_b"],
|
||||
want => {host_b => {host => 'host_b'}},
|
||||
},
|
||||
{
|
||||
desc => "non-recap vars are scrubbed from %recap",
|
||||
cachefile_lines => ["mtime=1234567890 host_b"],
|
||||
recap => {host_b => {host => 'host_b', mtime => 1234567891}},
|
||||
cachefile_lines => ["var_b_non_recap=foo host_b"],
|
||||
recap => {host_b => {host => 'host_b', var_b_non_recap => 'foo'}},
|
||||
want => {host_b => {host => 'host_b'}},
|
||||
},
|
||||
{
|
||||
|
@ -166,8 +85,6 @@ for my $tc (@test_cases) {
|
|||
host_a => {protocol => 'protocol_a'},
|
||||
host_b => {protocol => 'protocol_b'},
|
||||
);
|
||||
$tc->{config} //= {};
|
||||
$want_config{$_} = {%{$want_config{$_} // {}}, %{$tc->{config}{$_}}} for keys(%{$tc->{config}});
|
||||
# Deep clone %want_config so we can check for changes.
|
||||
local %ddclient::config;
|
||||
$ddclient::config{$_} = {%{$want_config{$_}}} for keys(%want_config);
|
||||
|
@ -180,21 +97,9 @@ for my $tc (@test_cases) {
|
|||
or diag(ddclient::repr(Values => [\%ddclient::recap, $tc->{want}],
|
||||
Names => ['*got', '*want']));
|
||||
}
|
||||
TODO: {
|
||||
local $TODO = $tc->{want_config_changes_TODO};
|
||||
$tc->{want_config_changes} //= {};
|
||||
$want_config{$_} = {%{$want_config{$_} // {}}, %{$tc->{want_config_changes}{$_}}}
|
||||
for keys(%{$tc->{want_config_changes}});
|
||||
for my $h (keys(%want_config)) {
|
||||
for my $k (keys(%{$want_config{$h}})) {
|
||||
my $a = refaddr($want_config{$h}{$k});
|
||||
delete($want_config{$h}{$k}) if defined($a) && $a == refaddr($DOES_NOT_EXIST);
|
||||
}
|
||||
}
|
||||
is_deeply(\%ddclient::config, \%want_config, "$tc->{desc}: %config")
|
||||
or diag(ddclient::repr(Values => [\%ddclient::config, \%want_config],
|
||||
Names => ['*got', '*want']));
|
||||
}
|
||||
is_deeply(\%ddclient::config, \%want_config, "$tc->{desc}: %config")
|
||||
or diag(ddclient::repr(Values => [\%ddclient::config, \%want_config],
|
||||
Names => ['*got', '*want']));
|
||||
}
|
||||
|
||||
done_testing();
|
||||
|
|
|
@ -54,9 +54,9 @@ local %ddclient::protocols = (
|
|||
local $ddclient::_l = ddclient::pushlogctx($h);
|
||||
ddclient::debug('updating host');
|
||||
push(@updates, [@_]);
|
||||
$ddclient::config{$h}{status} = 'good';
|
||||
$ddclient::config{$h}{ip} = delete($ddclient::config{$h}{wantip});
|
||||
$ddclient::config{$h}{mtime} = $ddclient::now;
|
||||
$ddclient::recap{$h}{status} = 'good';
|
||||
$ddclient::recap{$h}{ip} = delete($ddclient::config{$h}{wantip});
|
||||
$ddclient::recap{$h}{mtime} = $ddclient::now;
|
||||
}
|
||||
ddclient::debug('returning from update');
|
||||
}),
|
||||
|
@ -83,12 +83,6 @@ my @test_cases = (
|
|||
'mtime' => $ddclient::now,
|
||||
'status-ipv4' => 'good',
|
||||
},
|
||||
want_cfg_changes => {
|
||||
'atime' => $ddclient::now,
|
||||
'ipv4' => '192.0.2.1',
|
||||
'mtime' => $ddclient::now,
|
||||
'status-ipv4' => 'good',
|
||||
},
|
||||
%$_,
|
||||
};
|
||||
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
|
||||
|
@ -107,12 +101,6 @@ my @test_cases = (
|
|||
'mtime' => $ddclient::now,
|
||||
'status-ipv6' => 'good',
|
||||
},
|
||||
want_cfg_changes => {
|
||||
'atime' => $ddclient::now,
|
||||
'ipv6' => '2001:db8::1',
|
||||
'mtime' => $ddclient::now,
|
||||
'status-ipv6' => 'good',
|
||||
},
|
||||
},
|
||||
{
|
||||
desc => 'legacy, fresh, usev6=webv6',
|
||||
|
@ -128,12 +116,6 @@ my @test_cases = (
|
|||
'mtime' => $ddclient::now,
|
||||
'status-ipv6' => 'good',
|
||||
},
|
||||
want_cfg_changes => {
|
||||
'atime' => $ddclient::now,
|
||||
'ipv6' => '2001:db8::1',
|
||||
'mtime' => $ddclient::now,
|
||||
'status-ipv6' => 'good',
|
||||
},
|
||||
},
|
||||
{
|
||||
desc => 'legacy, fresh, usev4=webv4 usev6=webv6',
|
||||
|
@ -150,12 +132,6 @@ my @test_cases = (
|
|||
'mtime' => $ddclient::now,
|
||||
'status-ipv4' => 'good',
|
||||
},
|
||||
want_cfg_changes => {
|
||||
'atime' => $ddclient::now,
|
||||
'ipv4' => '192.0.2.1',
|
||||
'mtime' => $ddclient::now,
|
||||
'status-ipv4' => 'good',
|
||||
},
|
||||
},
|
||||
map({
|
||||
my %cfg = %{delete($_->{cfg})};
|
||||
|
@ -211,9 +187,6 @@ my @test_cases = (
|
|||
want_recap_changes => {
|
||||
'warned-min-interval' => $ddclient::now,
|
||||
},
|
||||
want_cfg_changes => {
|
||||
'warned-min-interval' => $ddclient::now,
|
||||
},
|
||||
%$_,
|
||||
};
|
||||
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
|
||||
|
@ -238,11 +211,6 @@ my @test_cases = (
|
|||
'ipv4' => '192.0.2.1',
|
||||
'mtime' => $ddclient::now,
|
||||
},
|
||||
want_cfg_changes => {
|
||||
'atime' => $ddclient::now,
|
||||
'ipv4' => '192.0.2.1',
|
||||
'mtime' => $ddclient::now,
|
||||
},
|
||||
%$_,
|
||||
};
|
||||
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
|
||||
|
@ -265,9 +233,6 @@ my @test_cases = (
|
|||
want_recap_changes => {
|
||||
'warned-min-error-interval' => $ddclient::now,
|
||||
},
|
||||
want_cfg_changes => {
|
||||
'warned-min-error-interval' => $ddclient::now,
|
||||
},
|
||||
%$_,
|
||||
};
|
||||
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
|
||||
|
@ -293,12 +258,6 @@ my @test_cases = (
|
|||
'mtime' => $ddclient::now,
|
||||
'status-ipv4' => 'good',
|
||||
},
|
||||
want_cfg_changes => {
|
||||
'atime' => $ddclient::now,
|
||||
'ipv4' => '192.0.2.1',
|
||||
'mtime' => $ddclient::now,
|
||||
'status-ipv4' => 'good',
|
||||
},
|
||||
%$_,
|
||||
};
|
||||
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
|
||||
|
@ -317,7 +276,6 @@ for my $tc (@test_cases) {
|
|||
# $cachef is an object that stringifies to a filename.
|
||||
local $ddclient::globals{cache} = "$cachef";
|
||||
my %cfg = (
|
||||
%{$tc->{recap} // {}}, # Simulate a previous update.
|
||||
web => 'v4',
|
||||
webv4 => 'v4',
|
||||
webv6 => 'v6',
|
||||
|
|
Loading…
Reference in a new issue