File Coverage

blib/lib/Zabbix/API.pm
Criterion Covered Total %
statement 26 126 20.6
branch 0 26 0.0
condition 0 2 0.0
subroutine 9 22 40.9
pod 13 13 100.0
total 48 189 25.4


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