File Coverage

blib/lib/Monit/HTTP.pm
Criterion Covered Total %
statement 104 128 81.2
branch 19 34 55.8
condition 12 32 37.5
subroutine 19 22 86.3
pod 8 8 100.0
total 162 224 72.3


line stmt bran cond sub pod time code
1             #!/bin/false
2             # ABSTRACT: An OOP interface to Monit.
3             # PODNAME: Monit::HTTP
4              
5 6     6   1422173 use warnings;
  6         16  
  6         449  
6 6     6   41 use strict;
  6         15  
  6         161  
7 6     6   73 use v5.10;
  6         22  
8              
9             package Monit::HTTP;
10             $Monit::HTTP::VERSION = '0.08';
11 6     6   4481 use HTTP::Tiny ();
  6         308248  
  6         276  
12 6     6   2928 use XML::Fast;
  6         99975  
  6         414  
13 6     6   53 use Carp qw( croak );
  6         32  
  6         1305  
14              
15             our (
16             %MONIT_ACTIONS,
17             %MONIT_ACTIONS_REV,
18             %MONIT_STATUS,
19             %MONIT_STATUS_REV,
20             %MONIT_TYPES,
21             %MONIT_TYPES_REV,
22             %MONIT_MONITOR,
23             %MONIT_MONITOR_REV,
24             );
25              
26             my $STATUS_URL_TEMPLATE = 'http://%s%s:%d/_status?format=xml';
27             my $COMMAND_URL_TEMPLATE = 'http://%s:%d/%s';
28              
29             BEGIN {
30              
31 6     6   43 %MONIT_ACTIONS_REV = (
32             'stop' => 'ACTION_STOP',
33             'start' => 'ACTION_START',
34             'restart' => 'ACTION_RESTART',
35             'monitor' => 'ACTION_MONITOR',
36             'unmonitor' => 'ACTION_UNMONITOR',
37             );
38 6         48 %MONIT_ACTIONS = reverse %MONIT_ACTIONS_REV;
39              
40 6         41 %MONIT_MONITOR_REV = (
41             0 => 'off',
42             1 => 'monitored',
43             2 => 'initializing',
44             );
45 6         26 %MONIT_MONITOR = reverse %MONIT_MONITOR_REV;
46              
47 6         32 %MONIT_STATUS_REV = (
48             0 => 'Running',
49             32 => 'Connection Failed',
50             512 => 'Does not exist',
51             );
52 6         23 %MONIT_STATUS = reverse %MONIT_STATUS_REV;
53              
54 6         71 %MONIT_TYPES_REV = (
55             0 => 'TYPE_FILESYSTEM',
56             1 => 'TYPE_DIRECTORY',
57             2 => 'TYPE_FILE',
58             3 => 'TYPE_PROCESS',
59             4 => 'TYPE_HOST',
60             5 => 'TYPE_SYSTEM',
61             6 => 'TYPE_FIFO',
62             7 => 'TYPE_STATUS',
63             );
64 6         324 %MONIT_TYPES = reverse %MONIT_TYPES_REV;
65              
66             }
67              
68             # This creates constants from all the above values
69             # perl 5.10 has strange issues just going:
70             # use constant reverse %{ MONIT_TYPES() }
71             # So work around it with do {}
72 6     6   37 use constant do { my %foo = reverse( %MONIT_TYPES_REV ); \%foo };
  6         26  
  6         10  
  6         53  
  6         928  
73 6     6   36 use constant do { my %foo = reverse( %MONIT_ACTIONS_REV ); \%foo };
  6         10  
  6         8  
  6         29  
  6         507  
74              
75 6     6   39 use parent qw(Exporter);
  6         9  
  6         67  
76             our (%EXPORT_TAGS, @EXPORT_OK);
77              
78             %EXPORT_TAGS = (
79             constants => [qw/
80             ACTION_MONITOR
81             ACTION_RESTART
82             ACTION_START
83             ACTION_STOP
84             ACTION_UNMONITOR
85              
86             TYPE_DIRECTORY
87             TYPE_FIFO
88             TYPE_FILE
89             TYPE_FILESYSTEM
90             TYPE_HOST
91             TYPE_PROCESS
92             TYPE_SYSTEM
93             /],
94              
95             hashes => [qw/
96             %MONIT_ACTIONS
97             %MONIT_ACTIONS_REV
98             %MONIT_STATUS
99             %MONIT_STATUS_REV
100             %MONIT_TYPES
101             %MONIT_TYPES_REV
102             %MONIT_MONITOR
103             %MONIT_MONITOR_REV
104             /],
105             );
106              
107             @EXPORT_OK = (
108             @{$EXPORT_TAGS{constants}},
109             @{$EXPORT_TAGS{hashes}},
110             );
111              
112             Exporter::export_ok_tags( keys %EXPORT_TAGS );
113              
114              
115             sub new {
116 3     3 1 761607 my ($class, %self) = @_;
117              
118             # OOP stuff
119 3   33     28 $class = ref($class) || $class;
120 3         8 my $self = \%self;
121 3         9 bless $self, $class;
122              
123             # set some defaults, if not already set
124 3   100     36 $self->{hostname} ||= 'localhost';
125 3   50     22 $self->{port} ||= 2812;
126 3   50     16 $self->{use_auth} ||= 0;
127 3 50       26 if ($self->{use_auth}) {
128 0   0     0 $self->{username} ||= 'admin';
129 0   0     0 $self->{password} ||= 'monit';
130             }
131              
132 3         31 $self->{ua} = HTTP::Tiny->new( agent => sprintf('Perl %s/%s',__PACKAGE__,$Monit::HTTP::VERSION) );
133 3         383 $self->_generate_url;
134              
135 3         11 return $self
136             }
137              
138             sub _generate_url {
139              
140 5     5   12 my $self = shift;
141              
142 5         13 my $auth = '';
143 5 0 33     27 if (defined $self->{username} and defined $self->{password} and $self->{use_auth}) {
      33        
144             $auth = sprintf('%s:%s@',$self->{username},$self->{password})
145 0         0 }
146              
147             $self->{status_url} = sprintf($STATUS_URL_TEMPLATE,
148 5         41 $auth, $self->{hostname}, $self->{port});
149             }
150              
151              
152             sub set_hostname {
153 1     1 1 1784 my ($self, $hostname) = @_;
154 1         5 $self->{hostname} = $hostname;
155 1         5 $self->_generate_url;
156 1         4 return $hostname
157             }
158              
159              
160             sub set_port {
161 1     1 1 1253 my ($self, $port) = @_;
162 1         3 $self->{port} = $port;
163 1         7 $self->_generate_url;
164 1         2 return $port
165             }
166              
167              
168             sub set_username {
169 0     0 1 0 my ($self, $username) = @_;
170 0         0 $self->{username} = $username;
171 0         0 $self->_generate_url;
172 0         0 return $username
173             }
174              
175              
176             sub set_password {
177 0     0 1 0 my ($self, $password ) = @_;
178 0         0 $self->{password} = $password;
179 0         0 $self->_generate_url;
180 0         0 return $password
181             }
182              
183              
184             sub _fetch_info {
185 7     7   17 my ($self) = @_;
186              
187 7         254 my $res = $self->{ua}->get( $self->{status_url} );
188 7 100       128101 if ($res->{success}) {
189 3         11 $self->_set_xml($res->{content});
190 3         17 $self->{xml_hash} = xml2hash( $self->_get_xml );
191             }
192             else {
193             croak sprintf "Error while connecting to %s !\n" .
194             "Status: %s\nReason: %s\nContent: %s\n",
195 4   50     1261 $self->{status_url}, $res->{status}, $res->{reason}, $res->{content} || 'NIL';
196             }
197              
198 3         867 return 1
199             }
200              
201              
202             sub get_services {
203 5     5 1 8840 my ($self, $type) = @_;
204 5         10 my @services;
205 5   50     55 $type ||= '-1';
206              
207             croak "Don't understand this service type!\n"
208 5 50 33     63 unless $type == -1 or grep {$_ == $type} keys %{MONIT_TYPES()};
  0         0  
  0         0  
209              
210 5         31 $self->_fetch_info;
211              
212 1         2 for my $s (@{$self->{xml_hash}->{monit}->{service}}) {
  1         4  
213 2 50 33     7 if ($type == -1 or $s->{'-type'} == $type) {
214 2         4 push @services, $s->{name};
215             }
216             }
217 1         7 return @services;
218             }
219              
220              
221             sub _set_xml {
222 3     3   6 my ($self, $xml) = @_;
223 3         10 $self->{status_raw_content} = $xml;
224             }
225              
226              
227             sub _get_xml {
228 4     4   1339 my ($self) = @_;
229 4         18 return $self->{status_raw_content};
230             }
231              
232              
233             sub service_status {
234 2     2 1 3596 my ($self, $service) = @_;
235 2         4 my $status_href = {};
236              
237 2         7 $self->_fetch_info;
238              
239 2         3 for my $s (@{$self->{xml_hash}->{monit}->{service}}) {
  2         9  
240 4 100       11 if ($s->{name} eq $service) {
241              
242 2         7 $status_href->{host} = $self->{hostname};
243              
244             $status_href->{'type'} = $s->{'-type'}
245 2 50       19 if exists $s->{'-type'};
246              
247 2         5 for my $thing (qw/
248             children
249             collected_sec
250             collected_usec
251             euid
252             gid
253             group
254             monitor
255             monitormode
256             pid
257             ppid
258             name
259             pendingaction
260             status
261             status_hint
262             uid
263             uptime
264             /) {
265              
266             $status_href->{$thing} = $s->{$thing}
267 32 100       67 if exists $s->{$thing};
268              
269             } # main stuff loop
270              
271             # the 'system' (type 5) service sticks these things in to ->{system}, others are top level
272 2 50 33     12 if (my $sys = $s->{system} || $s) {
273 2         4 for my $thing (qw/ kilobyte kilobytetotal percent percenttotal /) {
274             $status_href->{memory}->{$thing} = $sys->{memory}->{$thing}
275 8 100       23 if exists $sys->{memory}->{$thing};
276             } # memory loop
277              
278 2         4 for my $thing (qw/ kilobyte percent /) {
279             $status_href->{swap}->{$thing} = $sys->{swap}->{$thing}
280 4 50       11 if exists $sys->{swap}->{$thing};
281             } # swap loop
282              
283 2         6 for my $thing (qw/ percent percenttotal /) {
284             $status_href->{cpu}->{$thing} = $sys->{cpu}->{$thing}
285 4 100       11 if exists $sys->{cpu}->{$thing};
286             } # cpu loop
287              
288 2         4 for my $thing (qw/ avg01 avg05 avg15 /) {
289             $status_href->{load}->{$thing} = $sys->{load}->{$thing}
290 6 100       15 if exists $sys->{load}->{$thing};
291             } # load loop
292              
293             }
294             }
295             }
296              
297             croak "Service $service does not exist\n"
298 2 50       4 unless scalar keys %{$status_href};
  2         9  
299              
300 2         9 return $status_href
301              
302             }
303              
304              
305             sub command_run {
306 0     0 1   my ($self, $service, $command) = @_;
307              
308             croak "Don't understand this action\n"
309 0 0         unless grep { $command eq $_ } keys %{MONIT_ACTIONS()};
  0            
  0            
310              
311 0 0         if (not defined $service) {
312 0           $self->{is_success} = 0;
313 0           croak "Service not specified\n";
314             }
315              
316             # if services does not exist throw error
317              
318 0           my $url = sprintf($COMMAND_URL_TEMPLATE, $self->{hostname}, $self->{port}, $service);
319              
320 0           my $res = $self->{ua}->post_form($url, { action => $command });
321             croak $res->{status}
322 0 0         unless $res->{success};
323              
324 0           return 1
325             }
326              
327             1; # End of Monit::HTTP
328              
329             __END__