File Coverage

lib/WebService/Uptrack.pm
Criterion Covered Total %
statement 32 83 38.5
branch 0 20 0.0
condition 0 9 0.0
subroutine 12 19 63.1
pod 3 3 100.0
total 47 134 35.0


line stmt bran cond sub pod time code
1             package WebService::Uptrack;
2              
3 4     4   174336 use warnings;
  4         11  
  4         183  
4 4     4   23 use strict;
  4         8  
  4         306  
5 4     4   24 use Carp;
  4         10  
  4         458  
6 4     4   20931 use Data::Dumper;
  4         81909  
  4         5443  
7 4     4   5589 use Readonly;
  4         91376  
  4         620  
8              
9 4     4   11071 use Moose;
  4         3123648  
  4         39  
10 4     4   39183 use Moose::Util::TypeConstraints;
  4         12  
  4         278  
11 4     4   15675 use MooseX::StrictConstructor;
  4         176939  
  4         35  
12              
13             require HTTP::Request;
14             require HTTP::Response;
15             require JSON::XS;
16             require LWP::UserAgent;
17              
18 4     4   48254 use version; our $VERSION = qv('0.0.2');
  4         11096  
  4         30  
19              
20             # DEFAULT VALUES
21             Readonly our $API_URL => 'https://uptrack.ksplice.com/api';
22              
23             # ATTRIBUTES AND PRIVATE METHODS
24              
25             # debug flag
26             has 'debug' => (
27             is => 'rw',
28             isa => 'Int',
29             default => 0,
30             );
31              
32             # Uptrack API URL
33             has 'url' => (
34             is => 'ro',
35             isa => 'Str',
36             default => $API_URL,
37             required => 1,
38             trigger => \&_url_trim,
39             );
40              
41             sub _url_trim {
42 0     0   0 my( $self, $url, $old_url ) = @_;
43              
44 0         0 $self->_debug( "\$url: $url", 3 );
45 0         0 $url =~ s|/$||;
46 0         0 $self->_debug( "\$url: $url", 3 );
47 0         0 return( $url );
48             }
49              
50             # Uptrack API credentials
51             has 'credentials' => (
52             is => 'ro',
53             isa => 'HashRef',
54             required => 1,
55             );
56              
57             # LWP::UserAgent
58             has '_ua' => (
59             is => 'ro',
60             isa => duck_type( 'UserAgent', [ qw( new request ) ] ),
61             lazy_build => 1,
62             required => 1,
63             );
64              
65 1     1   14 sub _build__ua { return( LWP::UserAgent->new ) }
66              
67             # JSON
68             has '_json' => (
69             is => 'ro',
70             isa => duck_type( 'JSON', [ qw( new decode_json ) ] ),
71             lazy_build => 1,
72             required => 1,
73             );
74              
75 1     1   45 sub _build__json { return( JSON::XS->new ) }
76              
77             sub _request {
78 0     0     my( $self, $params ) = @_;
79              
80 0           $self->_debug( Data::Dumper->Dump( [$params], [qw(*params)] ), 3 );
81              
82             # parse params
83 0   0       my( $type ) = $params->{type} || 'GET';
84 0   0       my( $call ) = $params->{call} || undef;
85 0   0       my( $args ) = $params->{args} || undef;
86              
87             # sanity check
88 0 0         unless ( defined( $call ) ) {
89 0           return;
90             }
91              
92             # we need credentials
93 0           my( $creds ) = [
94             'X-Uptrack-User' => $self->credentials->{'user'},
95             'X-Uptrack-Key' => $self->credentials->{'key'},
96             ];
97              
98             # build the URL
99 0           my( $url ) = $self->url . $call;
100 0           $self->_debug( "\$url: $url\n" );
101              
102             # instantiate the request
103 0           my( $request ) = HTTP::Request->new( $type, $url, $creds, $args );
104              
105 0           $request->header( Accept => 'application/json' );
106              
107             # send it
108 0           my( $response ) = $self->_ua->request( $request );
109              
110             # what did we get?
111 0 0         if ( $response->is_success ) {
112 0           my( $json ) = $response->decoded_content;
113              
114 0           my( $result ) = $self->_json->utf8->decode( $json );
115              
116             # we don't want JSON::XS::Booleans in the output
117 0 0         if ( ref( $result ) eq 'ARRAY' ) {
118 0           foreach my $element ( @{$result} ) {
  0            
119 0           $element = _sanitizeActive( $element );
120             }
121             }
122             else {
123 0           $result = _sanitizeActive( $result );
124             }
125              
126 0           return( $result );
127             }
128             else {
129             # oh no, error
130             return(
131             {
132 0           status => $response->code,
133             error => $response->as_string,
134             }
135             );
136             }
137             };
138              
139             sub _sanitizeActive {
140 0     0     my( $hashref ) = @_;
141              
142 0 0         if ( exists( $hashref->{active} ) ) {
143 0 0         $hashref->{active} = $hashref->{active} ? 1 : 0;
144             }
145              
146 0           return( $hashref );
147             }
148              
149             sub _debug {
150 0     0     my( $self, $message, $level ) = @_;
151              
152 0 0         defined( $level ) or $level = 1;
153              
154 0 0         if ( $self->debug >= $level ) {
155 0           carp( $message );
156             }
157             }
158              
159             # PUBLIC METHODS
160              
161             sub machines {
162 0     0 1   my( $self ) = @_;
163              
164 0           my( $params ) = {
165             call => "/1/machines",
166             };
167              
168 0           return( $self->_request( $params ) );
169             };
170              
171             sub describe {
172 0     0 1   my( $self, $uuid ) = @_;
173              
174 0 0         unless ( defined( $uuid ) ) {
175 0           return;
176             }
177              
178 0           my( $params ) = {
179             call => "/1/machine/$uuid/describe",
180             };
181              
182 0           return( $self->_request( $params ) );
183             };
184              
185             sub authorize {
186 0     0 1   my( $self, $uuid, $bool ) = @_;
187              
188 0 0 0       unless ( defined( $uuid ) && defined( $bool ) ) {
189 0           return;
190             }
191              
192             # normalize $bool
193 0 0         $bool = $bool ? 'true' : 'false';
194              
195             # encode the content
196 0           my( $json ) = $self->_json->utf8->encode( { authorized => $bool } );
197              
198 0           my( $params ) = {
199             type => "POST",
200             call => "/1/machine/$uuid/describe",
201             args => $json,
202             };
203              
204 0           return( $self->_request( $params ) );
205             }
206              
207             # done with Moose magic
208 4     4   4201 no Moose;
  4         10  
  4         41  
209             __PACKAGE__->meta->make_immutable;
210              
211             1; # Magic true value required at end of module
212             __END__
213              
214             =head1 NAME
215              
216             WebService::Uptrack - access KSplice Uptrack web API
217              
218             =head1 VERSION
219              
220             This document describes WebService::Uptrack version 0.0.2
221              
222             =head1 SYNOPSIS
223              
224             use WebService::Uptrack;
225            
226             my( $uptrack ) = WebService::Uptrack->new(
227             credentials => {
228             user => 'username',
229             key => 'uptrack-API-key',
230             },
231             );
232              
233             my( $machines ) = $uptrack->machines;
234              
235             foreach my $machine ( keys( %{$machines} ) ) {
236             my( $uuid ) = $machine->{uuid};
237             my( $status ) = $uptrack->describe( $uuid );
238              
239             };
240              
241             =head1 DESCRIPTION
242              
243             This module provides a Perl interface to the KSplice Uptrack web API. API documentation is located here:
244              
245             L<http://www.ksplice.com/uptrack/api>
246              
247             You need to provide a valid Uptrack API username and key in order to use this module; get this via the Uptrack web interface.
248              
249             =head1 INTERFACE
250              
251             =over
252              
253             =item WebService::Uptrack->new
254              
255             Instantiate a new C<WebService::Uptrack> object. You must provide your credentials as a hashref with the following format:
256              
257             {
258             user => 'username',
259             key => 'api-key',
260             }
261              
262             You can pass the following additional parameters at creation time:
263              
264             =over
265              
266             =item url
267              
268             C<url> is a string, defining the top-level API URL. By default it's set to C<https://uptrack.ksplice.com/api>.
269              
270             =item debug
271              
272             C<debug> is an integer; if it's set greater than 0, C<WebService::Uptrack> will emit debug info via L<Carp>.
273              
274             =item _ua
275              
276             C<_ua> must be a reference to a L<LWP::UserAgent> object or something that works the same.
277              
278             =item _json
279              
280             C<_json> must be a reference to a L<JSON::XS> object or something that works the same.
281              
282             =back
283              
284             =item machines
285              
286             The C<machines> API call. Consult the upstream documentation for specifics.
287              
288             =item describe
289              
290             The C<describe> API call. Consult the upstream documentation for specifics.
291              
292             =item authorize
293              
294             The C<authorize> API call. Consult the upstream documentation for specifics.
295              
296             =back
297              
298             =head1 DEPENDENCIES
299              
300             Carp, Data::Dumper, Readonly, Moose, Moose::Util::TypeConstraints, MooseX::StrictConstructor, HTTP::Request, HTTP::Response, LWP::UserAgent, JSON::XS
301              
302             =head1 INCOMPATIBILITIES
303              
304             None reported.
305              
306              
307             =head1 BUGS AND LIMITATIONS
308              
309             =for author to fill in:
310             A list of known problems with the module, together with some
311             indication Whether they are likely to be fixed in an upcoming
312             release. Also a list of restrictions on the features the module
313             does provide: data types that cannot be handled, performance issues
314             and the circumstances in which they may arise, practical
315             limitations on the size of data sets, special cases that are not
316             (yet) handled, etc.
317              
318             No bugs have been reported.
319              
320             Please report any bugs or feature requests to
321             C<bug-webservice-uptrack@rt.cpan.org>, or through the web interface at
322             L<http://rt.cpan.org>.
323              
324             =head1 THANKS
325              
326             Thanks to KSplice for making their API straightforward and easy to use, and thanks to The Harvard-MIT Data Center (L<http://www.hmdc.harvard.edu>) for employing me while I write this module.
327              
328             =head1 AUTHOR
329              
330             Steve Huff C<< <shuff at cpan dot org> >>
331              
332             =head1 LICENCE AND COPYRIGHT
333              
334             This module is free software; you can redistribute it and/or
335             modify it under the same terms as Perl itself. See L<perlartistic>.
336              
337             =head1 DISCLAIMER OF WARRANTY
338              
339             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
340             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
341             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
342             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
343             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
344             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
345             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
346             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
347             NECESSARY SERVICING, REPAIR, OR CORRECTION.
348              
349             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
350             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
351             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
352             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
353             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
354             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
355             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
356             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
357             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
358             SUCH DAMAGES.