File Coverage

blib/lib/Zabbix/API.pm
Criterion Covered Total %
statement 27 116 23.2
branch 0 26 0.0
condition 0 2 0.0
subroutine 9 20 45.0
pod 11 11 100.0
total 47 175 26.8


line stmt bran cond sub pod time code
1             package Zabbix::API;
2              
3 11     11   1103674 use strict;
  11         33  
  11         477  
4 11     11   192 use warnings;
  11         35  
  11         351  
5 11     11   317 use 5.010;
  11         44  
  11         498  
6              
7 11     11   13768 use Params::Validate qw/:all/;
  11         231029  
  11         3142  
8 11     11   104 use Carp qw/carp croak confess cluck/;
  11         34  
  11         830  
9 11     11   1169 use Data::Dumper;
  11         11964  
  11         608  
10 11     11   65 use Scalar::Util qw/weaken/;
  11         26  
  11         1259  
11              
12 11     11   15295 use JSON;
  11         359565  
  11         220  
13 11     11   35674 use LWP::UserAgent;
  11         1070985  
  11         25591  
14              
15             our $VERSION = '0.009';
16              
17             sub new {
18              
19 0     0 1   my $class = shift;
20 0           my %args = validate(@_, { server => 1,
21             verbosity => 0,
22             env_proxy => 0,
23             lazy => 0,
24             ua => { optional => 1 } });
25              
26 0           my $self = \%args;
27              
28             # defaults
29 0 0         $self->{verbosity} = 0 unless exists $self->{verbosity};
30 0 0         $self->{env_proxy} = 0 unless exists $self->{env_proxy};
31 0 0         $self->{lazy} = 0 unless exists $self->{lazy};
32              
33 0 0         $self->{ua} = LWP::UserAgent->new(agent => 'Zabbix API client (libwww-perl)',
34             from => 'fabrice.gabolde@uperto.com',
35             show_progress => $self->{verbosity},
36             env_proxy => $self->{env_proxy},)
37             unless $self->{ua};
38              
39 0           $self->{cookie} = '';
40              
41 0           bless $self, $class;
42              
43 0           return $self;
44              
45             }
46              
47             sub useragent {
48              
49 0     0 1   return shift->{ua};
50              
51             }
52              
53             sub verbosity {
54              
55             ## mutator for verbosity
56              
57 0     0 1   my ($self, $value) = @_;
58              
59 0 0         if (defined $value) {
60              
61 0           $self->{verbosity} = $value;
62 0           $self->{ua}->{show_progress} = $value;
63 0           return $self->{verbosity};
64              
65             } else {
66              
67 0           return $self->{verbosity};
68              
69             }
70              
71             }
72              
73             sub cookie {
74              
75 0     0 1   my $self = shift;
76              
77 0           return $self->{cookie};
78              
79             }
80              
81             sub login {
82              
83 0     0 1   my $self = shift;
84              
85 0           my %args = validate(@_, { user => 1,
86             password => 1 });
87              
88 0           my $response = $self->raw_query(method => 'user.login',
89             params => \%args);
90              
91 0           $self->{cookie} = '';
92              
93 0           my $decoded = eval { decode_json($response->decoded_content) };
  0            
94              
95 0 0         if ($@) {
96              
97             # probably could not connect at all
98 0           croak sprintf('Could not connect: %s (%s)', $response->message, $response->code);
99              
100             }
101              
102 0 0         if ($decoded->{error}) {
103              
104 0           croak 'Could not log in: '.$decoded->{error}->{data};
105              
106             }
107              
108 0           $self->{cookie} = $decoded->{result};
109              
110 0           $self->{user} = $args{user};
111              
112 0           return $self;
113              
114             }
115              
116             sub logout {
117              
118 0     0 1   my $self = shift;
119              
120 0           my $decoded = decode_json($self->raw_query(method => 'user.logout')->decoded_content);
121              
122 0 0         if ($decoded->{error}) {
123              
124 0           croak 'Could not log out: '.$decoded->{error}->{data};
125              
126             }
127              
128 0           $self->{cookie} = '';
129              
130 0           delete $self->{user};
131              
132 0           return $self;
133              
134             }
135              
136             sub raw_query {
137              
138 0     0 1   my ($self, %args) = @_;
139              
140 0           state $global_id = int(rand(10000));
141              
142             # common parameters
143 0           $args{'jsonrpc'} = '2.0';
144 0   0       $args{'auth'} = $self->cookie || '';
145 0           $args{'id'} = $global_id++;
146              
147 0           my $response = eval { $self->{ua}->post($self->{server},
  0            
148             'Content-Type' => 'application/json-rpc',
149             Content => encode_json(\%args)) };
150              
151 0 0         if ($@) {
152              
153 0           my $error = $@;
154              
155 0           confess $error;
156              
157             }
158              
159 0           given ($self->{verbosity}) {
160              
161 0           when (1) {
162              
163 0           print $response->as_string;
164              
165             }
166              
167 0           when (2) {
168              
169 0           print Dumper($response);
170              
171             }
172              
173 0           default {
174              
175             }
176              
177             }
178              
179 0           return $response;
180              
181             }
182              
183             sub query {
184              
185 0     0 1   my $self = shift;
186              
187 0           my %args = validate(@_, { method => { TYPE => SCALAR },
188             params => { TYPE => HASHREF,
189             optional => 1 }});
190              
191 0           my $response = $self->raw_query(%args);
192              
193 0 0         if ($response->is_success) {
194              
195 0           my $decoded = decode_json($response->decoded_content);
196              
197 0 0         if ($decoded->{error}) {
198              
199 0           croak 'Zabbix server replied: '.$decoded->{error}->{data};
200              
201             }
202              
203 0           return $decoded->{result};
204              
205             }
206              
207 0           croak 'Received HTTP error: '.$response->decoded_content;
208              
209             }
210              
211             sub api_version {
212              
213 0     0 1   my $self = shift;
214              
215 0           my $response = $self->query(method => 'apiinfo.version');
216              
217 0           return $response;
218              
219             }
220              
221             sub fetch {
222              
223 0     0 1   my $self = shift;
224 0           my $class = shift;
225              
226 0           my %args = validate(@_,
227             { params => { type => HASHREF,
228             default => {} } });
229              
230 0           $class =~ s/^(?:Zabbix::API::)?/Zabbix::API::/;
231              
232             ## no critic (ProhibitStringyEval)
233 0           eval "require $class";
234             ## use critic
235              
236 0 0         if ($@) {
237              
238 0           my $error = $@;
239              
240 0           croak qq{Could not load class '$class': $error};
241              
242             }
243              
244 0           my $response = $self->query(method => $class->prefix('.get'),
245             params => {
246 0           %{$args{params}},
247             $class->extension
248             });
249              
250 0           my $things = [ map { $class->new(root => $self, data => $_) } @{$response} ];
  0            
  0            
251              
252 0           return $things;
253              
254             }
255              
256             sub fetch_single {
257              
258 0     0 1   my ($self, @args) = @_;
259              
260 0           my $results = $self->fetch(@args);
261 0           my $result_count = scalar @{$results};
  0            
262              
263 0 0         if ($result_count > 1) {
264              
265 0           croak qq{Too many results for 'fetch_single': expected 0 or 1, got $result_count"};
266              
267             }
268              
269 0           return $results->[0];
270              
271             }
272              
273             1;
274             __END__