Add support for ionos.com
This commit is contained in:
parent
af4ea14fda
commit
60e3cfeb4c
5 changed files with 145 additions and 0 deletions
|
@ -99,6 +99,8 @@ repository history](https://github.com/ddclient/ddclient/commits/master).
|
|||
[#726](https://github.com/ddclient/ddclient/pull/726)
|
||||
* `porkbun`: The update URL hostname is now configurable via the `server`
|
||||
option. [#752](https://github.com/ddclient/ddclient/pull/752)
|
||||
* `ionos`: Added support for updating Ionos records.
|
||||
[#743](https://github.com/ddclient/ddclient/pull/743)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ handwritten_tests = \
|
|||
t/protocol_directnic.pl \
|
||||
t/protocol_dnsexit2.pl \
|
||||
t/protocol_dyndns2.pl \
|
||||
t/protocol_ionos.pl \
|
||||
t/read_recap.pl \
|
||||
t/skip.pl \
|
||||
t/ssl-validate.pl \
|
||||
|
|
|
@ -38,6 +38,7 @@ Dynamic DNS services currently supported include:
|
|||
* [Hurricane Electric](https://dns.he.net)
|
||||
* [Infomaniak](https://faq.infomaniak.com/2376)
|
||||
* [INWX](https://www.inwx.com/)
|
||||
* [Ionos](https://ionos.com)
|
||||
* [Loopia](https://www.loopia.se)
|
||||
* [Mythic Beasts](https://www.mythic-beasts.com/support/api/dnsv2/dynamic-dns)
|
||||
* [NameCheap](https://www.namecheap.com)
|
||||
|
|
72
ddclient.in
72
ddclient.in
|
@ -1295,6 +1295,15 @@ our %protocols = (
|
|||
'max-interval' => setv(T_DELAY, 0, 'inf', 0),
|
||||
},
|
||||
),
|
||||
'ionos' => ddclient::Protocol->new(
|
||||
'update' => \&nic_ionos_update,
|
||||
'examples' => \&nic_ionos_examples,
|
||||
'cfgvars' => {
|
||||
%{$cfgvars{'protocol-common-defaults'}},
|
||||
'server' => setv(T_FQDNP, 0, 'ipv4.api.hosting.ionos.com', undef),
|
||||
'login' => undef,
|
||||
},
|
||||
),
|
||||
);
|
||||
$cfgvars{'merged'} = {
|
||||
map({ %{$protocols{$_}{'cfgvars'}} } keys(%protocols)),
|
||||
|
@ -7644,6 +7653,69 @@ Example ${program}.conf file entries:
|
|||
EoEXAMPLE
|
||||
}
|
||||
|
||||
######################################################################
|
||||
## nic_ionos_examples
|
||||
######################################################################
|
||||
sub nic_ionos_examples {
|
||||
my $self = shift;
|
||||
return <<EoEXAMPLE;
|
||||
o 'ionos'
|
||||
|
||||
The 'ionos' protocol is used by DNS service offered by ionos.com.
|
||||
|
||||
Configuration variables applicable to the 'ionos' protocol are:
|
||||
protocol=ionos ##
|
||||
password=dyndns-update-key ## the key created to update the host below
|
||||
fully.qualified.host ## the host registered with the service.
|
||||
|
||||
Example ${program}.conf file entries:
|
||||
## single host update
|
||||
protocol=ionos,
|
||||
password=dyndns-update-key
|
||||
myhost.com
|
||||
|
||||
Getting the DynDNS key (only available via Ionos API):
|
||||
|
||||
1. Create an API key
|
||||
2. Enable DynDNS for your host using the /dns/v1/dyndns API
|
||||
(documentation @ https://developer.hosting.ionos.es/docs/dns)
|
||||
3. In the API response, get the key value. The key is a long string
|
||||
from the "q=" parameter. The URL looks like this:
|
||||
https://ipv4.api.hosting.ionos.com/dns/v1/dyndns?q=XXXXXXXXXXXXXXX
|
||||
(in the example above the key is "XXXXXXXXXXXXXXX").
|
||||
|
||||
Note: Because the key is individual for each host, you cannot update
|
||||
multiple hosts with the same key.
|
||||
EoEXAMPLE
|
||||
}
|
||||
|
||||
######################################################################
|
||||
## nic_ionos_update
|
||||
## response contains "code 200" on succesfull completion
|
||||
######################################################################
|
||||
sub nic_ionos_update {
|
||||
my $self = shift;
|
||||
## update each configured host
|
||||
## should improve to update in one pass
|
||||
for my $h (@_) {
|
||||
local $_l = pushlogctx($h);
|
||||
my $ip = delete $config{$h}{'wantipv4'};
|
||||
info("setting IP address to $ip");
|
||||
my $url = opt('server', $h) . "/dns/v1/dyndns?q=" . opt('password', $h);
|
||||
my $reply = geturl(proxy => opt('proxy'), url => $url);
|
||||
|
||||
if (header_ok($reply)) {
|
||||
$recap{$h}{'ipv4'} = $ip;
|
||||
$recap{$h}{'mtime'} = $now;
|
||||
$recap{$h}{'status-ipv4'} = 'good';
|
||||
success("IP address set to $ip");
|
||||
} else {
|
||||
$recap{$h}{'status'} = 'failed';
|
||||
failed("server said: $reply");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Execute main() if this file is run as a script or run via PAR (https://metacpan.org/pod/PAR),
|
||||
# otherwise do nothing. This "modulino" pattern makes it possible to import this file as a module
|
||||
# and test its functions directly; there's no need for test-only command-line arguments or stdout
|
||||
|
|
69
t/protocol_ionos.pl
Normal file
69
t/protocol_ionos.pl
Normal file
|
@ -0,0 +1,69 @@
|
|||
use Test::More;
|
||||
BEGIN { eval { require Test::Warnings; } or skip($@, 1); }
|
||||
BEGIN { eval { require 'ddclient'; } or BAIL_OUT($@); }
|
||||
BEGIN {
|
||||
eval { require ddclient::t::HTTPD; 1; } or plan(skip_all => $@);
|
||||
ddclient::t::HTTPD->import();
|
||||
plan tests => 2;
|
||||
}
|
||||
|
||||
{
|
||||
package Logger;
|
||||
use parent qw(-norequire ddclient::Logger);
|
||||
sub new {
|
||||
my ($class, $parent) = @_;
|
||||
my $self = $class->SUPER::new(undef, $parent);
|
||||
$self->{logs} = [];
|
||||
return $self;
|
||||
}
|
||||
sub _log {
|
||||
my ($self, $args) = @_;
|
||||
push(@{$self->{logs}}, $args)
|
||||
if ($args->{label} // '') =~ qr/^(?:WARNING|FATAL|SUCCESS|FAILED)$/;
|
||||
return $self->SUPER::_log($args);
|
||||
}
|
||||
}
|
||||
|
||||
# Subtest for the protocol_ionos
|
||||
subtest 'Testing protocol_ionos' => sub {
|
||||
# Mock HTTP server
|
||||
httpd()->run(sub {
|
||||
my ($req) = @_;
|
||||
diag('==============================================================================');
|
||||
diag("Test server received request:\n" . $req->as_string());
|
||||
|
||||
return undef if $req->uri()->path() eq '/control';
|
||||
return [400, $textplain, ['invalid method: ' . $req->method()]] if $req->method() ne 'GET';
|
||||
return undef
|
||||
});
|
||||
|
||||
local $ddclient::globals{debug} = 1;
|
||||
local $ddclient::globals{verbose} = 1;
|
||||
my $l = Logger->new($ddclient::_l);
|
||||
|
||||
local %ddclient::config = (
|
||||
'host.my.example.com' => {
|
||||
'protocol' => 'ionos',
|
||||
'password' => 'mytestingpassword',
|
||||
'server' => httpd()->endpoint(),
|
||||
'wantipv4' => '1.2.3.4',
|
||||
},
|
||||
);
|
||||
|
||||
httpd()->reset([200, $textplain, []]);
|
||||
|
||||
{
|
||||
local $ddclient::_l = $l;
|
||||
|
||||
ddclient::nic_ionos_update(undef, 'host.my.example.com');
|
||||
}
|
||||
|
||||
my @requests = httpd()->reset();
|
||||
is(scalar(@requests), 1, "Single update request");
|
||||
|
||||
my $req = shift(@requests);
|
||||
is($req->uri()->path(), '/dns/v1/dyndns', "Correct request path");
|
||||
is($req->uri()->query(), 'q=mytestingpassword', "Correct request query");
|
||||
};
|
||||
|
||||
done_testing();
|
Loading…
Reference in a new issue