File Coverage

blib/lib/Mojo/Cloudflare.pm
Criterion Covered Total %
statement 57 98 58.1
branch 12 36 33.3
condition 3 11 27.2
subroutine 10 15 66.6
pod 5 5 100.0
total 87 165 52.7


line stmt bran cond sub pod time code
1             package Mojo::Cloudflare;
2              
3             =head1 NAME
4              
5             Mojo::Cloudflare - Talk with the Cloudflare API using Mojo::UserAgent
6              
7             =head1 VERSION
8              
9             0.04
10              
11             =head1 DESCRIPTION
12              
13             L is an (async) client for the
14             L.
15              
16             =head1 SYNOPSIS
17              
18             use Mojo::Cloudflare;
19             my $cf = Mojo::Cloudflare->new(
20             email => 'sample@example.com',
21             key => '8afbe6dea02407989af4dd4c97bb6e25',
22             zone => 'example.com',
23             );
24              
25             # add a record
26             $cf->record({
27             content => 'mojolicio.us',
28             name => 'direct.example.pm',
29             type => 'CNAME',
30             })->save;
31              
32             # retrieve and update records
33             for my $record ($cf->records->all) {
34             warn $record->name;
35             $record->ttl(1)->save; # update a record
36             }
37              
38             # update a record
39             $cf->record({
40             content => 'mojolicio.us',
41             id => 'some_id_fom_cloudflare', # <-- cause update instead of insert
42             name => 'direct.example.pm',
43             type => 'CNAME',
44             })->save;
45              
46             =cut
47              
48 3     3   800869 use Mojo::Base -base;
  3         5  
  3         19  
49 3     3   464 use Mojo::JSON::Pointer;
  3         4  
  3         26  
50 3     3   62 use Mojo::UserAgent;
  3         6  
  3         14  
51 3     3   1041 use Mojo::Cloudflare::Record;
  3         6  
  3         50  
52 3     3   1117 use Mojo::Cloudflare::RecordSet;
  3         6  
  3         25  
53              
54             our $VERSION = '0.04';
55              
56             =head1 ATTRIBUTES
57              
58             =head2 api_url
59              
60             Holds the endpoint where we communicate. Default is
61             L.
62              
63             =head2 email
64              
65             $str = $self->email;
66             $self = $self->email($str);
67              
68             The e-mail address associated with the API key.
69              
70             =head2 key
71              
72             $str = $self->key;
73             $self = $self->key($str);
74              
75             This is the API key made available on your Account page.
76              
77             =head2 zone
78              
79             $str = $self->zone;
80             $self = $self->zone($str);
81              
82             The zone (domain) to act on.
83              
84             =cut
85              
86             has api_url => 'https://www.cloudflare.com/api_json.html';
87             has email => '';
88             has key => '';
89             has zone => '';
90             has _ua => sub { Mojo::UserAgent->new };
91              
92             =head1 METHODS
93              
94             =head2 add_record
95              
96             Will be deprecated. Use L instead.
97              
98             =cut
99              
100             sub add_record {
101 0     0 1 0 my ($self, $args, $cb) = @_;
102 0         0 my %args;
103              
104 0         0 %args = map { ($_, $args->{$_}); } grep { defined $args->{$_}; } qw( type name content ttl );
  0         0  
  0         0  
105              
106 0         0 $args{_class} = 'Mojo::Cloudflare::Record';
107 0         0 $args{a} = 'rec_new';
108 0 0       0 $args{prio} = $args->{priority} if defined $args->{priority};
109 0   0     0 $args{ttl} ||= 1;
110              
111 0         0 return $self->_post(\%args, $cb);
112             }
113              
114             =head2 delete_record
115              
116             Will be deprecated. Use L instead.
117              
118             =cut
119              
120             sub delete_record {
121 1     1 1 4610 my ($self, $id, $cb) = @_;
122              
123 1         7 $self->_post({a => 'rec_delete', id => $id, _class => 'Mojo::Cloudflare::Record'}, $cb,);
124             }
125              
126             =head2 edit_record
127              
128             Will be deprecated. Use L instead.
129              
130             =cut
131              
132             sub edit_record {
133 1     1 1 3463 my ($self, $args, $cb) = @_;
134 1         2 my %args;
135              
136 1         3 %args = map { ($_, $args->{$_}); } grep { defined $args->{$_}; } qw( id type name content ttl );
  3         7  
  5         8  
137              
138 1         3 $args{_class} = 'Mojo::Cloudflare::Record';
139 1         2 $args{a} = 'rec_edit';
140 1 50       5 $args{prio} = $args->{priority} if defined $args->{priority};
141 1 50       5 $args{service_mode} = $args->{service_mode} ? 1 : 0 if defined $args->{service_mode};
    50          
142              
143 1         4 return $self->_post(\%args, $cb);
144             }
145              
146             =head2 record
147              
148             $record_obj = $self->record(\%record_construction_args);
149              
150             Returns a L object.
151              
152             =cut
153              
154             sub record {
155 0     0 1 0 my $self = shift;
156 0 0       0 my $args = @_ ? @_ > 1 ? {@_} : $_[0] : {};
    0          
157 0         0 my $obj = Mojo::Cloudflare::Record->new({});
158 0         0 $obj->$_($args->{$_}) for grep { $obj->can($_) } keys %$args;
  0         0  
159 0         0 Scalar::Util::weaken($obj->_cf($self)->{_cf});
160 0         0 $obj;
161             }
162              
163             =head2 records
164              
165             $records_obj = $self->records($offset);
166             $self = $self->records($offset, sub {
167             my($self, $err, $records_obj) = @_;
168             });
169              
170             Used to retrieve L objects. The return value will
171             be a L object.
172              
173             C<$offset> is optional and defaults to "all", which will retrieve all the DNS
174             records instead of the limit of 180 set by CloudFlare.
175              
176             =cut
177              
178             sub records {
179 1     1 1 772 my ($self, $offset, $cb) = @_;
180              
181 1 50       4 if (ref $offset eq 'CODE') {
182 0         0 $cb = $offset;
183 0         0 $offset = 'all';
184             }
185              
186 1 50 33     7 if (!defined $offset or $offset eq 'all') {
187 1         21 my $record_set = Mojo::Cloudflare::RecordSet->new({count => 0, has_more => undef, objs => []});
188 1         34 Scalar::Util::weaken($record_set->_cf($self)->{_cf});
189 1 50       17 return $cb ? $self->_all_records_nb($record_set, $cb) : $self->_all_records($record_set);
190             }
191             else {
192 0         0 return $self->_post({a => 'rec_load_all', o => $offset, _class => 'Mojo::Cloudflare::RecordSet'}, $cb);
193             }
194             }
195              
196             sub _all_records {
197 1     1   2 my ($self, $record_set) = @_;
198 1         2 my $has_more = 1;
199 1         1 my $offset = 0;
200              
201 1         9 while ($has_more) {
202 1         7 my $json = $self->_post({a => 'rec_load_all', o => $offset, _class => 'Mojo::Cloudflare::RecordSet'});
203              
204 1         43 $record_set->data->{count} += $json->get('/count');
205 1 50       55 push @{$record_set->data->{objs}}, @{$json->get('/objs') || []};
  1         16  
  1         6  
206 1         35 $has_more = $json->get('/has_more');
207 1 50       36 $offset += $has_more ? $json->get('/count') : 0;
208             }
209              
210 1         5 return $record_set;
211             }
212              
213             sub _all_records_nb {
214 0     0   0 my ($self, $record_set, $cb) = @_;
215 0         0 my $offset = 0;
216 0         0 my $retriever;
217              
218             $retriever = sub {
219 0     0   0 my ($self, $err, $json) = @_;
220 0         0 my $offset;
221              
222 0 0       0 return $self->$cb($err, $record_set) if $err;
223              
224 0         0 $offset += $json->get('/count');
225 0         0 $record_set->data->{count} = $offset;
226 0 0       0 push @{$record_set->data->{objs}}, @{$json->get('/objs') || []};
  0         0  
  0         0  
227              
228 0 0       0 return $self->$cb('', $record_set) unless $json->get('/has_more');
229 0         0 return $self->_post({a => 'rec_load_all', o => $offset, _class => 'Mojo::Cloudflare::RecordSet'}, $retriever);
230 0         0 };
231              
232 0         0 $self->_post({a => 'rec_load_all', _class => 'Mojo::Cloudflare::RecordSet'}, $retriever);
233             }
234              
235             sub _post {
236 3     3   6 my ($self, $data, $cb) = @_;
237 3         6 my $class = delete $data->{_class};
238              
239 3 50       9 $data->{a} or die "Internal error: Unknown action";
240 3   33     78 $data->{email} ||= $self->email;
241 3   33     95 $data->{tkn} ||= $self->key;
242 3 50       78 $data->{z} = $self->zone if $data->{a} =~ /^rec/;
243              
244 3 50       24 unless ($cb) {
245 3         44 my $tx = $self->_ua->post($self->api_url, form => $data);
246 3         66434 my ($err, $obj) = $class->_new_from_tx($tx);
247              
248 3 50       53 die $err if $err;
249 3         72 Scalar::Util::weaken($obj->_cf($self)->{_cf});
250 3         129 return $obj;
251             }
252              
253 0           Scalar::Util::weaken($self);
254             $self->_ua->post(
255             $self->api_url,
256             form => $data,
257             sub {
258 0     0     my ($err, $obj) = $class->_new_from_tx($_[1]);
259              
260 0           Scalar::Util::weaken($obj->_cf($self)->{_cf});
261 0           $self->$cb($err, $obj);
262             },
263 0           );
264              
265 0           return $self;
266             }
267              
268             =head1 COPYRIGHT AND LICENSE
269              
270             Copyright (C) 2014, Jan Henning Thorsen
271              
272             This program is free software, you can redistribute it and/or modify it under
273             the terms of the Artistic License version 2.0.
274              
275             =head1 AUTHOR
276              
277             Jan Henning Thorsen - C
278              
279             =cut
280              
281             1;