File Coverage

blib/lib/Net/DynDNS/GoDaddy.pm
Criterion Covered Total %
statement 84 85 98.8
branch 17 18 94.4
condition 14 15 93.3
subroutine 17 18 94.4
pod 4 4 100.0
total 136 140 97.1


line stmt bran cond sub pod time code
1             package Net::DynDNS::GoDaddy;
2              
3 5     5   102226 use strict;
  5         36  
  5         141  
4 5     5   28 use warnings;
  5         7  
  5         143  
5              
6 5     5   26 use Carp qw(croak);
  5         10  
  5         233  
7 5     5   3022 use Data::Dumper;
  5         36956  
  5         368  
8 5     5   37 use Exporter qw(import);
  5         11  
  5         279  
9 5     5   2483 use File::HomeDir;
  5         28195  
  5         287  
10 5     5   3452 use HTTP::Tiny;
  5         257658  
  5         265  
11 5     5   2645 use JSON;
  5         50960  
  5         29  
12              
13             our $VERSION = '0.04';
14              
15             our @EXPORT = qw(host_ip_get host_ip_set);
16             our @EXPORT_OK = qw(api_key_get api_key_set);
17             our %EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK]);
18              
19             my $home_dir;
20              
21             BEGIN {
22 5     5   1093 $home_dir = File::HomeDir->my_home;
23             }
24              
25             use constant {
26 5         4115 URL => 'https://api.godaddy.com',
27             API_KEY_FILE => "$home_dir/godaddy_api.json",
28 5     5   490 };
  5         16  
29              
30             my $client = HTTP::Tiny->new;
31             my ($key, $secret);
32              
33             sub api_key_get {
34 6 100 66 6 1 601 return($key, $secret) if $key && $secret;
35              
36             {
37 5         10 local $/;
  5         19  
38 5 100       181 open my $fh, '<', API_KEY_FILE
39 1         190 or croak "GoDaddy API key/secret file ${\API_KEY_FILE} doesn't exist";
40              
41 4         146 my $data = decode_json(<$fh>);
42              
43 4         20 $key = $data->{api_key};
44 4         76 $secret = $data->{api_secret};
45             }
46              
47 4         22 return($key, $secret);
48             }
49             sub api_key_set {
50 5     5 1 2922 my ($key, $secret) = @_;
51              
52 5 100 100     38 if (! $key || ! $secret) {
53 2         186 croak "api_key_set() requires an API key and an API secret sent in";
54             }
55              
56 3         14 my $data = {
57             api_key => $key,
58             api_secret => $secret,
59             };
60              
61 3 50       340 open my $fh, '>', API_KEY_FILE
62 0         0 or croak "Can't open ${\API_KEY_FILE} for writing";
63              
64 3         133 print $fh JSON->new->pretty->encode($data);
65              
66 3         312 return 1;
67             }
68             sub host_ip_get {
69 4     4 1 1591 my ($host, $domain) = @_;
70              
71 4 100 100     93 if (! defined $host || ! defined $domain) {
72 2         298 croak "host_ip_get() requires a hostname and domain name sent in";
73             }
74              
75 2         13 my $ip = _get($host, $domain);
76              
77 2         7 return $ip;
78             }
79             sub host_ip_set {
80 6     6 1 2034 my ($host, $domain, $ip) = @_;
81              
82 6 100 100     60 if (! defined $host || ! defined $domain || ! defined $ip) {
      100        
83 3         398 croak "host_ip_set() requires a hostname, domain and IP sent in";
84             }
85              
86 3 100       21 if ($ip !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
87 1         92 croak "host_ip_get() received an invalid IP: $ip";
88             }
89              
90 2         8 my $response = _set($host, $domain, $ip);
91              
92 2         6 return $response;
93             }
94              
95             sub _api_key_file {
96             # Returns the path and filename of the API key file (used for testing)
97 1     1   92 return API_KEY_FILE;
98             }
99             sub _get {
100             # Fetch the current IP of the host/domain pair
101              
102 2     2   7 my ($host, $domain) = @_;
103              
104 2         9 my $route = "/v1/domains/$domain/records/A/$host";
105              
106 2         8 my $uri = URL . $route;
107              
108 2         8 my ($api_key, $api_secret) = api_key_get();
109              
110 2         14 my $api_auth = "$api_key:$api_secret";
111              
112 2         12 my $headers = {
113             'Authorization' => "sso-key $api_auth"
114             };
115              
116 2         15 my $response = $client->request('GET', $uri, {headers => $headers});
117              
118 2         58 my $status = $response->{status};
119              
120 2 100       9 if ($status != 200) {
121 1         11 warn "Failed to connect to $uri to get your address: $response->{content}";
122 1         4 return '';
123             }
124              
125 1         9 my $ip = decode_json($response->{content})->[0]{data};
126              
127 1         5 return $ip;
128             }
129             sub _set {
130             # Set the host to a new IP
131              
132 2     2   6 my ($host, $domain, $ip) = @_;
133              
134 2         8 my $route = "/v1/domains/$domain/records/A/$host";
135              
136 2         6 my $uri = URL . $route;
137              
138 2         6 my ($api_key, $api_secret) = api_key_get();
139              
140 2         9 my $api_auth = "$api_key:$api_secret";
141              
142 2         10 my $headers = {
143             'Authorization' => "sso-key $api_auth",
144             'Content-Type' => 'application/json',
145             };
146              
147 2         8 my $content = [{ data => $ip }];
148 2         16 my $content_json = encode_json($content);
149              
150 2         15 my $response = $client->request(
151             'PUT',
152             $uri,
153             {
154             headers => $headers,
155             content => $content_json
156             }
157             );
158              
159 2         46 my $status = $response->{status};
160              
161 2 100       7 if ($status != 200) {
162 1         10 warn "Failed to connect to $uri to get your address: $response->{content}";
163 1         4 return 0;
164             }
165              
166 1         5 return $response->{success};
167             }
168       0     sub __placeholder {}
169              
170             1;
171             __END__