File Coverage

blib/lib/Oracle/ZFSSA/Client.pm
Criterion Covered Total %
statement 17 70 24.2
branch 0 22 0.0
condition 0 10 0.0
subroutine 6 10 60.0
pod 1 2 50.0
total 24 114 21.0


line stmt bran cond sub pod time code
1             package Oracle::ZFSSA::Client;
2              
3 1     1   74370 use 5.008;
  1         4  
4              
5 1     1   5 use strict;
  1         3  
  1         21  
6 1     1   5 use warnings;
  1         6  
  1         42  
7              
8 1     1   741 use LWP::UserAgent;
  1         56773  
  1         55  
9 1     1   767 use JSON;
  1         11254  
  1         7  
10              
11             our $VERSION = '0.01';
12              
13             # HTTP Return Codes
14 1     1   164 use HTTP::Status qw(:constants);
  1         2  
  1         941  
15              
16             sub new {
17              
18 0     0 0   my $class = shift;
19              
20 0           my %param = @_;
21              
22 0           my $self->{user} = delete $param{user};
23 0           $self->{password} = delete $param{password};
24 0           $self->{host} = delete $param{host};
25 0   0       $self->{port} = delete $param{port} || 215;
26 0   0       $self->{debug} = delete $param{debug} || 0;
27              
28 0 0 0       if (!defined($param{ssl}) || $param{ssl} != 0) {
29 0           $self->{ssl} = 1;
30             } else {
31 0           $self->{ssl} = 0;
32             }
33              
34 0 0 0       if (!defined($param{verify_hostname}) || $param{verify_hostname} != 0) {
35 0           $self->{verify_hostname} = 1;
36             } else {
37 0           $self->{verify_hostname} = 0;
38             }
39              
40 0 0         die "A user must be defined" if (!defined($self->{user}));
41 0 0         die "A password must be defined" if (!defined($self->{password}));
42 0 0         die "A host must be defined" if (!defined($self->{host}));
43              
44 0           my $url = $self->{host} . ":" . $self->{port};
45              
46 0 0         if ($self->{ssl}) {
47 0           $url = "https://" . $url;
48             } else {
49 0           $url = "http://" . $url;
50             }
51              
52 0           $self->{url} = $url;
53              
54             # Generate the first request and get a valid Session
55             #
56 0           $url = $url . '/api/access/v1';
57              
58             my $header = ['X-Auth-User' => $self->{user},
59             'X-Auth-Key' => $self->{password},
60 0           'Content-Type' => 'application/json; charset=utf-8'];
61 0           my $r = HTTP::Request->new('POST', $url, $header);
62 0           my $ua = LWP::UserAgent->new();
63              
64 0 0         if ($self->{debug} == 1) {
65 0     0     $ua->add_handler("request_send", sub { shift->dump; return });
  0            
  0            
66 0     0     $ua->add_handler("response_done", sub { shift->dump; return });
  0            
  0            
67             }
68              
69 0 0         if ($self->{verify_hostname} == 0) {
70             # Self signed Cert
71 0           $ua->ssl_opts( verify_hostname => 0,
72             SSL_verify_mode => 'SSL_VERIFY_NONE' );
73             }
74              
75             # We'll reuse this User Agent
76 0           $self->{ua} = $ua;
77              
78 0           my $res = $ua->request($r);
79              
80 0           my $session = "";
81 0 0         if ($res->code == HTTP_CREATED) {
82             # All proceeding request should had this header set
83 0           $session = $res->header('X-Auth-Session');
84             } else {
85             # You did not get a valid session
86 0           die $res->status_line . ": Unable to get valid X-Auth-Session";
87             }
88             #
89             # End Session Building
90              
91 0           $self->{session} = $session;
92              
93 0           bless $self, $class;
94 0           return $self;
95             }
96              
97             sub call {
98              
99 0     0 1   my ($self,$method,$uri,$json) = @_;
100              
101 0 0         $json = JSON->new->utf8->encode($json) if (defined($json));
102              
103 0           my $url = $self->{url} . $uri;
104             my $header = ['X-Auth-Session' => $self->{session},
105 0           'Content-Type' => 'application/json; charset=utf-8'];
106 0           my $r = HTTP::Request->new($method, $url, $header, $json);
107              
108 0           my $ua = $self->{ua};
109              
110 0           my $res = $ua->request($r);
111              
112 0 0         if ($res->is_success) {
113 0           return JSON->new->utf8->decode($res->decoded_content);
114             }
115 0           return;
116             }
117              
118             1;
119              
120             =pod
121              
122             =head1 NAME
123              
124             Oracle::ZFSSA::Client - Oracle ZFS Storage RESTful API Connector
125              
126             =head1 SYNOPSIS
127              
128             use Oracle::ZFSSA::Client;
129              
130             $zfssa = new Oracle::ZFSSA::Client(
131             user => $user,
132             password => $password,
133             host => "your.appliance.org"
134             );
135              
136             $json_param = {
137             your => 'params',
138             but => 'not required',
139             };
140              
141             $json_result = $zfssa->call('POST','/api/storage/v1/method',$json_param)
142              
143             # See ex/example.pl for more examples:
144             # https://github.com/whindsx/Oracle-ZFSSA-Client/blob/master/ex/example.pl
145              
146             =head1 DESCRIPTION
147              
148             This Perl module provides a simplified means of connecting to and
149             executing commands against an Oracle ZFSSA RESTful Application
150             Programming Interface. Responses are Perl C data structures.
151              
152             =head1 CONSTRUCTOR
153              
154             $zfssa = Oracle::ZFSSA::Client->new( %options )
155              
156             This method creates a new C and returns it.
157              
158             Key Default
159             ----------- -----------
160             user undef (Required)
161             password undef (Required)
162             host undef (Required)
163             port 215
164             ssl 1
165             verify_hostname 1
166             debug 0
167              
168             ssl - Connect to the API over HTTPS.
169              
170             verify_hostname - Disable SSL certificate verification.
171              
172             debug - Turns on raw HTTP request/response output from LWP::UserAgent.
173              
174             =head1 METHODS
175              
176             There is only one c method:
177              
178             =head2 call
179              
180             $zfssa->call('GET','/api/storage/v1/pools');
181              
182             The first parameter is the HTTP method, this is required.
183             The second parameter is the ZFSSA API method, this is also required.
184             The third and optional parameter is a hash of API parameters that will
185             become C encoded.
186            
187             For more information see:
188             https://docs.oracle.com/cd/E51475_01/html/E52433/index.html
189              
190             =head1 AUTHOR
191              
192             Wesley Hinds wesley.hinds@gmail.com
193              
194             =head1 AVAILABILITY
195              
196             The latest branch is avaiable from Github.
197              
198             https://github.com/whindsx/Oracle-ZFSSA-Client
199              
200             =head1 LICENSE AND COPYRIGHT
201              
202             Copyright 2018 Wesley Hinds.
203              
204             This program is free software; you can redistribute it and/or modify it
205             under the terms of the the Artistic License (2.0). You may obtain a
206             copy of the full license at:
207              
208             L
209              
210             Any use, modification, and distribution of the Standard or Modified
211             Versions is governed by this Artistic License. By using, modifying or
212             distributing the Package, you accept this license. Do not use, modify,
213             or distribute the Package, if you do not accept this license.
214              
215             If your Modified Version has been derived from a Modified Version made
216             by someone other than you, you are nevertheless required to ensure that
217             your Modified Version complies with the requirements of this license.
218              
219             This license does not grant you the right to use any trademark, service
220             mark, tradename, or logo of the Copyright Holder.
221              
222             This license includes the non-exclusive, worldwide, free-of-charge
223             patent license to make, have made, use, offer to sell, sell, import and
224             otherwise transfer the Package with respect to any patent claims
225             licensable by the Copyright Holder that are necessarily infringed by the
226             Package. If you institute patent litigation (including a cross-claim or
227             counterclaim) against any party alleging that the Package constitutes
228             direct or contributory patent infringement, then this Artistic License
229             to you shall terminate on the date that such litigation is filed.
230              
231             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
232             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
233             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
234             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
235             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
236             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
237             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
238             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
239              
240              
241             =cut