File Coverage

blib/lib/Akamai/Open/DiagnosticTools.pm
Criterion Covered Total %
statement 11 13 84.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 16 18 88.8


line stmt bran cond sub pod time code
1             package Akamai::Open::DiagnosticTools;
2             BEGIN {
3 1     1   24497 $Akamai::Open::DiagnosticTools::AUTHORITY = 'cpan:PROBST';
4             }
5             # ABSTRACT: The Akamai Open DiagnosticTools API Perl client
6             $Akamai::Open::DiagnosticTools::VERSION = '0.02';
7 1     1   10 use strict;
  1         2  
  1         32  
8 1     1   5 use warnings;
  1         1  
  1         28  
9 1     1   18 use v5.10;
  1         3  
  1         62  
10              
11 1     1   522 use Moose;
  0            
  0            
12             use JSON;
13              
14             #XXX create a useful scheme for REST methods
15             use constant {
16             TOOLS_URI => '/diagnostic-tools',
17             DIG_URI => '/v1/dig',
18             MTR_URI => '/v1/mtr',
19             LOC_URI => '/v1/locations'
20             };
21              
22             extends 'Akamai::Open::Request::EdgeGridV1';
23              
24             has 'tools_uri' => (is => 'ro', default => TOOLS_URI);
25             has 'dig_uri' => (is => 'ro', default => DIG_URI);
26             has 'mtr_uri' => (is => 'ro', default => MTR_URI);
27             has 'loc_uri' => (is => 'ro', default => LOC_URI);
28             has 'baseurl' => (is => 'rw', trigger => \&Akamai::Open::Debug::debugger);
29             has 'last_error'=> (is => 'rw');
30              
31             sub validate_base_url {
32             my $self = shift;
33             my $base = $self->baseurl();
34             $self->debug->logger->debug('validating baseurl');
35             $base =~ s{/$}{} && $self->baseurl($base);
36             return;
37             }
38            
39             foreach my $f (qw/dig mtr locations/) {
40             before $f => sub {
41             my $self = shift;
42             my $param = @_;
43              
44             $self->validate_base_url();
45             my $uri = $self->baseurl() . $self->tools_uri();
46              
47             $self->debug->logger->debug("before hook called for $f") if($self->debug->logger->is_debug());
48              
49             #XXX create a useful scheme for REST methods
50             given($f) {
51             when($_ eq 'dig') {
52             $uri .= $self->dig_uri();
53             $self->request->method('GET');
54             }
55             when($_ eq 'mtr') {
56             $uri .= $self->mtr_uri();
57             $self->request->method('GET');
58             }
59             when($_ eq 'locations') {
60             $uri .= $self->loc_uri();
61             $self->request->method('GET');
62             }
63             }
64              
65             $self->debug->logger->info('filling request object with data');
66             $self->request->uri(URI->new($uri));
67             };
68             }
69              
70             sub dig {
71             my $self = shift;
72             my $param = shift;
73             my $valid_types_re = qr/^(?i:A|AAAA|PTR|SOA|MX|CNAME)$/;
74             my $data;
75              
76             $self->debug->logger->debug('dig() was called');
77              
78             unless(ref($param)) {
79             $self->last_error('parameter of dig() has to be a hashref');
80             $self->debug->logger->error($self->last_error());
81             return(undef);
82             }
83              
84             unless(defined($param->{'hostname'}) && defined($param->{'queryType'})) {
85             $self->last_error('hostname and queryType are mandatory options for dig()');
86             $self->debug->logger->error($self->last_error());
87             return(undef);
88             }
89              
90             unless($param->{'queryType'} =~ m/$valid_types_re/) {
91             $self->last_error('queryType has to be one of A, AAAA, PTR, SOA, MX or CNAME');
92             $self->debug->logger->error($self->last_error());
93             return(undef);
94             }
95              
96             unless(defined($param->{'location'}) || defined($param->{'sourceIp'})) {
97             $self->last_error('either location or sourceIp has to be set');
98             $self->debug->logger->error($self->last_error());
99             return(undef);
100             }
101              
102             $self->request->uri->query_form($param);
103             $self->sign_request();
104             $self->response($self->user_agent->request($self->request()));
105              
106             $self->debug->logger->info(sprintf('HTTP response code for dig() call is %s', $self->response->code()));
107             $data = decode_json($self->response->content());
108             given($self->response->code()) {
109             when($_ == 200) {
110             if(defined($data->{'dig'}->{'errorString'})) {
111             $self->last_error($data->{'dig'}->{'errorString'});
112             $self->debug->logger->error($self->last_error());
113             return(undef);
114             } else {
115             return($data->{'dig'});
116             }
117             }
118             when($_ =~m/^5\d\d/) {
119             $self->last_error('the server returned a 50x error');
120             $self->debug->logger->error($self->last_error());
121             return(undef);
122             }
123             }
124             $self->last_error(sprintf('%s %s %s', $data->{'httpStatus'} ,$data->{'title'} ,$data->{'problemInstance'}));
125             $self->debug->logger->error($self->last_error());
126             return(undef);
127             }
128              
129             sub mtr {
130             my $self = shift;
131             my $param = shift;
132             my $data;
133              
134             $self->debug->logger->debug('mtr() was called');
135              
136             unless(ref($param)) {
137             $self->last_error('parameter of mtr() has to be a hashref');
138             $self->debug->logger->error($self->last_error());
139             return(undef);
140             }
141              
142             unless(defined($param->{'destinationDomain'})) {
143             $self->last_error('destinationDomain is a mandatory options for mtr()');
144             $self->debug->logger->error($self->last_error());
145             return(undef);
146             }
147              
148             unless(defined($param->{'location'}) || defined($param->{'sourceIp'})) {
149             $self->last_error('either location or sourceIp has to be set');
150             $self->debug->logger->error($self->last_error());
151             return(undef);
152             }
153              
154             $self->request->uri->query_form($param);
155             $self->sign_request();
156             $self->response($self->user_agent->request($self->request()));
157              
158             $self->debug->logger->info(sprintf('HTTP response code for mtr() call is %s', $self->response->code()));
159             $data = decode_json($self->response->content());
160             given($self->response->code()) {
161             when($_ == 200) {
162             if(defined($data->{'mtr'}->{'errorString'})) {
163             $self->last_error($data->{'mtr'}->{'errorString'});
164             $self->debug->logger->error($self->last_error());
165             return(undef);
166             } else {
167             return($data->{'mtr'});
168             }
169             }
170             when($_ =~m/^5\d\d/) {
171             $self->last_error('the server returned a 50x error');
172             $self->debug->logger->error($self->last_error());
173             return(undef);
174             }
175             }
176             $self->last_error(sprintf('%s %s %s', $data->{'httpStatus'} ,$data->{'title'} ,$data->{'problemInstance'}));
177             $self->debug->logger->error($self->last_error());
178             return(undef);
179             }
180              
181             sub locations {
182             my $self = shift;
183             my $data;
184              
185             $self->debug->logger->debug('locations() was called');
186             $self->sign_request();
187             $self->response($self->user_agent->request($self->request()));
188             $self->debug->logger->info(sprintf('HTTP response code for locations() call is %s', $self->response->code()));
189             $data = decode_json($self->response->content());
190             given($self->response->code()) {
191             when($_ == 200) {
192             if(defined($data->{'errorString'})) {
193             $self->last_error($data->{'errorString'});
194             $self->debug->logger->error($self->last_error());
195             return(undef);
196             } else {
197             return($data->{'locations'});
198             }
199             }
200             when($_ =~m/^5\d\d/) {
201             $self->last_error('the server returned a 50x error');
202             $self->debug->logger->error($self->last_error());
203             return(undef);
204             }
205             }
206             $self->last_error(sprintf('%s %s %s', $data->{'httpStatus'} ,$data->{'title'} ,$data->{'problemInstance'}));
207             $self->debug->logger->error($self->last_error());
208             return(undef);
209             }
210              
211             1;
212              
213             __END__
214              
215             =pod
216              
217             =encoding utf-8
218              
219             =head1 NAME
220              
221             Akamai::Open::DiagnosticTools - The Akamai Open DiagnosticTools API Perl client
222              
223             =head1 VERSION
224              
225             version 0.02
226              
227             =head1 SYNOPSIS
228              
229             use Akamai::Open::Client;
230             use Akamai::Open::DiagnosticTools;
231              
232             my $client = Akamai::Open::Client->new();
233             $client->access_token('foobar');
234             $client->client_token('barfoo');
235             $client->client_secret('Zm9vYmFyYmFyZm9v');
236              
237             my $diag = Akamai::Open::DiagnosticTools->new(client => $client);
238             $diag->baseurl('http://mybaseurl.luna.akamaiapis.net');
239             my $loc = $diag->locations();
240             my $dig = $diag->dig({hostname => 'cpan.org', queryType => 'A', location => 'Frankfurt, Germany'});
241             my $mtr = $diag->mtr({destinationDomain => 'cpan.org', sourceIp => '23.62.61.24'});
242              
243             =head1 ABOUT
244              
245             I<Akamai::Open::DiagnosticTools> provides an API client for the
246             Akamai Open DiagnosticTools API which is described L<here|https://developer.akamai.com/api/luna/diagnostic-tools/reference.html>.
247              
248             =head1 USAGE
249              
250             All API calls for the DiagnosticTools API are described and explained
251             at the L<Akamai Open DiagnosticTools API Portal|https://developer.akamai.com/api/luna/diagnostic-tools/reference.html>.
252              
253             =head2 Akamai::Open::DiagnosticTools->new(client => $client)
254              
255             For every I<Akamai::Open> API call you'll need some client credentials.
256             These are provided by the L<Akamai::Open:Client|http://search.cpan.org/perldoc?Akamai::Open::Client>
257             module and can reviewed at the LUNA control center.
258              
259             A succesfull call to I<new()> will return a I<Moose> powered
260             I<Akamai::Open::DiagnosticTools> object.
261              
262             =head2 $diag->baseurl($baseurl)
263              
264             To successfully access an I<Akamai Open API> you'll need a baseurl,
265             which is provided by the I<LUNA control center Manage API Portal>
266             and is uniq to every configured API user and API itself.
267              
268             I<baseurl()> is a I<Moose> powered getter/setter method, to set
269             and receive the object's assigned baseurl.
270              
271             =head2 $diag->locations()
272              
273             To initiate diagnostinc actions inside the Akamai network, you'll
274             need the information about the locations from which diagnostic
275             actions are available.
276              
277             I<locations()> provides the informations. On success it returns a
278             Perl-style array reference. On error it returns I<undef> and sets
279             the I<last_error()> appropriate.
280              
281             =head2 $diag->mtr($hash_ref)
282              
283             I<mtr()> returns a network trace like the well know I<mtr> Unix command.
284              
285             I<mtr()> accepts the following parameters in $hash_ref as a Perl-style
286             hash reference:
287              
288             =over 4
289              
290             =item * destinationDomain
291              
292             The domain name you want to get information about. Example: I<cpan.org>.
293             This parameter is mandatory.
294              
295             =item * location
296              
297             Location of a Akamai Server you want to run mtr from. You can find
298             servers using the I<locations()> call. This paramter is optional.
299             Either location or sourceIp has to be passed to I<mtr()>
300              
301             =item * sourceIp
302              
303             A Akamai Server IP you want to run mtr from. This paramter is optional.
304             Either location or sourceIp has to be passed to I<mtr()>
305              
306             =back
307              
308             On success it returns a Perl-style hash reference. On error it returns
309             I<undef> and sets the I<last_error()> appropriate.
310              
311             The hash reference has the following format:
312              
313             {
314             'source' => ...,
315             'packetLoss' => '...',
316             'destination' => '...',
317             'errorString' => ...,
318             'analysis' => '...',
319             'host' => '...',
320             'avgLatency' => '...',
321             'hops' => [
322             {
323             'num' => '...',
324             'avg' => '...',
325             'last' => '...',
326             'stDev' => '...',
327             'host' => '...',
328             'worst' => '...',
329             'loss' => '...',
330             'sent' => '...',
331             'best' => '...'
332             }
333             ]
334             }
335              
336             =head2 $diag->dig($hash_ref)
337              
338             I<dig()> returns dns information like the well know I<dig> Unix command.
339              
340             I<dig()> accepts the following parameters in $hash_ref as a Perl-style
341             hash reference:
342              
343             =over 4
344              
345             =item * hostname
346              
347             The hostname you want to get information about. Example: I<cpan.org>.
348             This parameter is mandatory.
349              
350             =item * queryType
351              
352             The query type for the dig command call, valid types are A, AAAA,
353             PTR, SOA, MX and CNAME. This parameter is mandatory.
354              
355             =item * location
356              
357             Location of Akamai Server you want to run dig from. You can find
358             servers using the I<locations()> call. This paramter is optional.
359             Either location or sourceIp has to be passed to I<dig()>
360              
361             =item * sourceIp
362              
363             A Akamai Server IP you want to run dig from. This paramter is optional.
364             Either location or sourceIp has to be passed to I<dig()>
365              
366             =back
367              
368             On success it returns a Perl-style hash reference. On error it returns
369             I<undef> and sets the I<last_error()> appropriate.
370              
371             The hash reference has the following format:
372              
373             {
374             'authoritySection' => [
375             {
376             'recordType' => '...',
377             'domain' => '...',
378             'value' => '...',
379             'ttl' => '...',
380             'preferenceValues' => ...,
381             'recordClass' => '...'
382             }
383             ],
384             'answerSection' => [
385             {
386             'recordType' => '...',
387             'domain' => '...',
388             'value' => '...',
389             'ttl' => '...',
390             'preferenceValues' => ...,
391             'recordClass' => '...'
392             }
393             ],
394             'errorString' => ...,
395             'queryType' => '...',
396             'hostname' => '...',
397             'result' => '...'
398             }
399              
400             =head2 $diag->last_error()
401              
402             Just returns the last occured error.
403              
404             =head1 AUTHOR
405              
406             Martin Probst <internet+cpan@megamaddin.org>
407              
408             =head1 COPYRIGHT AND LICENSE
409              
410             This software is copyright (c) 2014 by Martin Probst.
411              
412             This is free software; you can redistribute it and/or modify it under
413             the same terms as the Perl 5 programming language system itself.
414              
415             =cut