File Coverage

blib/lib/Zabbix/Tiny.pm
Criterion Covered Total %
statement 90 102 88.2
branch 23 34 67.6
condition 0 3 0.0
subroutine 13 13 100.0
pod 2 6 33.3
total 128 158 81.0


line stmt bran cond sub pod time code
1             package Zabbix::Tiny;
2 4     4   2109 use strict;
  4         9  
  4         135  
3 4     4   19 use warnings;
  4         7  
  4         93  
4 4     4   1617 use Moo;
  4         28006  
  4         19  
5 4     4   4449 use Carp;
  4         10  
  4         169  
6 4     4   786 use LWP;
  4         67403  
  4         95  
7 4     4   531 use JSON;
  4         8093  
  4         23  
8              
9 4     4   1449 use Data::Dumper;
  4         9675  
  4         3510  
10              
11             our $VERSION = "1.09";
12              
13             has 'server' => (
14             is => 'rw',
15             required => 1,
16             );
17             has 'user' => (
18             is => 'rw',
19             required => 1,
20             );
21             has 'password' => (
22             is => 'rw',
23             required => 1,
24             );
25             has 'zabbix_method' => ( is => 'ro' );
26             has 'zabbix_params' => ( is => 'ro' );
27             has 'auth' => ( is => 'ro' );
28             has 'ua' => (
29             is => 'ro',
30             lazy => 1,
31             default => sub { LWP::UserAgent->new },
32             );
33             has 'id' => ( is => 'ro', default => sub { 1 } );
34             has 'post_response' => ( is => 'ro' );
35             has 'last_response' => ( is => 'ro' );
36             has 'json_request' => ( is => 'ro' );
37             has 'json_response' => ( is => 'ro' );
38             has 'verify_hostname' => ( is => 'rw', default => sub { 1 } );
39             has 'ssl_opts' => ( is => 'rw' );
40             has 'delay' => ( is => 'rw' );
41             has 'request' => ( is => 'ro' );
42             has 'json_prepared' => ( is => 'ro' );
43             has 'json_executed' => ( is => 'ro', default => sub { 0 } );
44             has 'redo' => ( is => 'ro' );
45              
46             my @content_type = ( 'content-type', 'application/json', );
47              
48             sub BUILD {
49 4     4 0 22 my $self = shift;
50 4         56 my $ua = $self->ua;
51 4         52 my $url = $self->server;
52 4         34 my $json_data = {
53             jsonrpc => '2.0',
54             id => $self->id,
55             method => 'user.login',
56             params => {
57             user => $self->user,
58             password => $self->password,
59             },
60             };
61 4 50       19 if ( $self->verify_hostname == 0 ) {
62 0         0 $ua->ssl_opts( verify_hostname => 0 );
63             }
64              
65 4 50       30 if ( $self->ssl_opts ) {
66 0         0 $ua->ssl_opts( %{ $self->{ssl_opts} } );
  0         0  
67             }
68             }
69              
70             sub login {
71 4     4 0 1773 my $self = shift;
72 4         14 my $id = $self->id;
73 4         76 my $ua = $self->ua;
74 4         36 my $url = $self->server;
75 4         47 my $json_data = {
76             jsonrpc => '2.0',
77             id => $id,
78             method => 'user.login',
79             params => {
80             user => $self->user,
81             password => $self->password,
82             },
83             };
84 4         68 my $json = encode_json($json_data);
85 4         30 my $response = $ua->post( $url, @content_type, Content => $json );
86              
87 4 50       22165 if ( $response->{_rc} !~ /2\d\d/ ) {
88 0         0 croak("$response->{_msg}");
89             }
90              
91 4 50       36 my $content = decode_json( $response->{_content} ) or die($!);
92              
93 4 100       18 if ( $content->{error} ) {
94 1         3 my $error_data = $content->{error}->{data};
95 1         2 my $error_msg = $content->{error}->{message};
96 1         3 my $error_code = $content->{error}->{code};
97 1         6 my $error = "Error from Zabbix (code $error_code): $error_msg $error_data";
98 1         18 croak($error);
99             }
100              
101 3         30 $self->{auth} = $content->{'result'};
102             }
103              
104             sub prepare {
105 7     7 1 16 my $self = shift;
106 7         11 my $method = shift;
107             #my $id = new String::Random;
108 7         22 $self->{ id }++;
109 7 100       20 if ($method) {
110 4         11 $self->{zabbix_method} = $method;
111 4         12 undef $self->{zabbix_params};
112 4         12 my @args = @_;
113 4 100       14 if ( scalar @args == 1 ) {
114 2         6 $self->{zabbix_params} = $args[0];
115             }
116             else {
117 2         5 my %params = @args;
118 2         5 $self->{zabbix_params} = \%params;
119             }
120             }
121 7 100       20 unless ($self->{zabbix_method} eq 'apiinfo.version') {
122 3 50       15 login($self) if ( !$self->auth );
123             }
124 7 50       23 if ( !$self->zabbix_method ) {
125 0         0 croak("No Zabbix API method defined");
126             }
127             $self->{request} = {
128 7         44 jsonrpc => '2.0',
129             id => $self->id,
130             method => $self->zabbix_method,
131             params => $self->zabbix_params,
132             };
133 7 100       24 unless ($self->{zabbix_method} eq 'apiinfo.version') {
134 3         9 $self->{request}->{auth} = $self->auth;
135             }
136 7 50       100 $self->{json_prepared} = encode_json( $self->request ) or die($!);
137             }
138              
139             sub execute {
140 4     4 0 8 my $self = shift;
141 4         84 my $ua = $self->ua;
142 4         63 $self->{post_response} = $ua->post( $self->server, @content_type,
143             Content => $self->json_prepared );
144 4         14426 $self->{json_request} = $self->{post_response}->{'_request'}->{_content};
145 4         18 $self->{json_response} = $self->post_response->{_content};
146 4 100       21 if ( $self->post_response->{_content} eq q{} ) {
147 1         17 croak( "Empty response received from the Zabbix API. This can indicate an error on the API side like running out of memory." );
148             }
149 3         21 $self->{last_response} = decode_json( $self->{post_response}->{_content} );
150 3         10 my $method = $self->zabbix_method;
151 3         7 my $params = $self->zabbix_params;
152 3         13 prepare($self); ## Rerun prepare to get the new request id.
153             }
154              
155             sub do {
156 4     4 1 750 my $self = shift;
157 4         9 my $method = shift;
158 4         10 my @args = @_;
159 4 100       16 if ($method) {
160 3         18 prepare( $self, $method, @args );
161             }
162 4         15 execute($self);
163 3 50       13 if ( $self->{last_response}->{error} ) {
164 0         0 my $error = $self->{last_response}->{error}->{data};
165 0 0 0     0 if ( ( !$self->{redo} )
166             && ( $error eq 'Session terminated, re-login, please.' ) )
167             {
168 0         0 $self->{redo}++;
169 0         0 delete( $self->{auth} );
170 0         0 prepare($self);
171 0         0 &do($self); ## Need to use "&" because "do" is a perl keyword.
172             }
173             else {
174 0         0 croak("Error: $error");
175             }
176             }
177             else {
178 3 50       13 delete( $self->{redo} ) if $self->redo;
179 3         7 $self->{json_executed} = 1;
180 3         18 return $self->{last_response}->{'result'};
181             }
182             }
183              
184             sub DEMOLISH {
185 4     4 0 4866 my $self = shift;
186 4         13 my $method = shift;
187 4         71 my $ua = $self->ua;
188 4         58 my $auth = $self->auth;
189 4         15 my $url = $self->server;
190             my $json_data = {
191             jsonrpc => '2.0',
192             id => ++$self->{ id },
193 4         20 method => 'user.logout',
194             auth => $auth,
195             };
196 4         26 my $json = encode_json($json_data);
197 4         19 $self->{post_response} = $ua->post( $url, @content_type, Content => $json );
198             }
199              
200             1;
201              
202             __END__