File Coverage

lib/Nagios/Object.pm
Criterion Covered Total %
statement 229 308 74.3
branch 99 172 57.5
condition 44 78 56.4
subroutine 41 58 70.6
pod 8 36 22.2
total 421 652 64.5


line stmt bran cond sub pod time code
1             ###########################################################################
2             # #
3             # Nagios::Object #
4             # Maintained by Duncan Ferguson #
5             # Written by Albert Tobey #
6             # Copyright 2003-2009, Albert P Tobey #
7             # Copyright 2009, Albert P Tobey and Duncan Ferguson #
8             # #
9             # This program is free software; you can redistribute it and/or modify it #
10             # under the terms of the GNU General Public License as published by the #
11             # Free Software Foundation; either version 2, or (at your option) any #
12             # later version. #
13             # #
14             # This program is distributed in the hope that it will be useful, but #
15             # WITHOUT ANY WARRANTY; without even the implied warranty of #
16             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
17             # General Public License for more details. #
18             # #
19             ###########################################################################
20             package Nagios::Object;
21 18     18   3180 use warnings;
  18         46  
  18         687  
22 18     18   89 use strict qw( subs vars );
  18         31  
  18         758  
23 18     18   112 use Carp;
  18         31  
  18         1461  
24 18     18   92 use Exporter;
  18         55  
  18         639  
25 18     18   11579 use Data::Dumper;
  18         84548  
  18         1363  
26 18     18   160 use Scalar::Util qw(blessed);
  18         126  
  18         8025181  
27             @Nagios::Object::ISA = qw( Exporter );
28              
29             # NOTE: due to CPAN version checks this cannot currently be changed to a
30             # standard version string, i.e. '0.21'
31             our $VERSION = '47';
32             our $pre_link = undef;
33             our $fast_mode = undef;
34             our %nagios_setup;
35              
36             # constants for flags in %nagios_setup
37             # note: might ditch version stuff soon (atobey, 2008-02-24)
38 0     0 0 0 sub NAGIOS_NO_INHERIT { 1 << 1 } # cannot inherit from template
39 5138     5138 0 12385 sub NAGIOS_PERL_ONLY { 1 << 2 } # perl module only attribute
40 0     0 0 0 sub NAGIOS_V1 { 1 << 3 } # nagios v1 attribute
41 9     9 0 72 sub NAGIOS_V2 { 1 << 4 } # nagios v2 attribute
42 266     266 0 575 sub NAGIOS_V1_ONLY { 1 << 5 } # not valid for nagios v2
43 0     0 0 0 sub NAGIOS_V2_ONLY { 1 << 6 } # not valid for nagios v1
44 0     0 0 0 sub NAGIOS_NO_DISPLAY { 1 << 7 } # should not be displayed by gui
45 0     0 0 0 sub NAGIOS_V3 { 1 << 8 } # nagios v3 attribute
46 0     0 0 0 sub NAGIOS_V3_ONLY { 1 << 9 } # not valid for nagios v1 or v2
47 2408     2408 0 6350 sub NAGIOS_GROUP_SYNC { 1 << 10 } # keep sync'ed with members method in group object
48              
49             # export constants - the :all tag will export them all
50             our %EXPORT_TAGS = (
51             all => [
52             qw(NAGIOS_NO_INHERIT NAGIOS_PERL_ONLY NAGIOS_V1 NAGIOS_V2 NAGIOS_V3 NAGIOS_V1_ONLY NAGIOS_V2_ONLY NAGIOS_V3_ONLY NAGIOS_NO_DISPLAY NAGIOS_GROUP_SYNC)
53             ]
54             );
55             Exporter::export_ok_tags('all');
56              
57             # we also export %nagios_setup only if it is asked for by name
58             push( @Nagios::Object::EXPORT_OK, '%nagios_setup' );
59              
60             # all the data needed to set up all the objects
61             # Object => {
62             # attribute => [ Type, Flags ]
63             # }
64             # Type: a type for validation _and_ for linking objects, so we know which
65             # fields should point to an object rather than containing a scalar.
66             # If the type is an array reference, it indicates that the entry
67             # may have more than one value assigned.
68             # Flags: Really these are bitwise ORed flags, but recorded here as simple
69             # integers for brevity. The flags are defined as constants toward
70             # the top of this file.
71             %nagios_setup = (
72             Service => {
73             use => [ 'Nagios::Service', 10 ],
74             service_description => [ 'STRING', 10 ],
75             display_name => [ 'STRING', 280 ],
76             host_name => [ ['Nagios::Host'], 10 ],
77             servicegroups => [ ['Nagios::ServiceGroup'], 280 ],
78             hostgroup_name => [ ['Nagios::HostGroup'], 256 ],
79             is_volatile => [ 'BINARY', 280 ],
80             check_command => [ 'Nagios::Command', 280 ],
81             max_check_attempts => [ 'INTEGER', 280 ],
82             normal_check_interval => [ 'INTEGER', 280 ],
83             retry_check_interval => [ 'INTEGER', 280 ],
84             check_interval => [ 'INTEGER', 280 ],
85             retry_interval => [ 'INTEGER', 280 ],
86             initial_state => [ [qw(o d u)], 280 ],
87             active_checks_enabled => [ 'BINARY', 280 ],
88             passive_checks_enabled => [ 'BINARY', 280 ],
89             check_period => [ 'Nagios::TimePeriod', 280 ],
90             parallelize_check => [ 'BINARY', 280 ],
91             obsess_over_service => [ 'BINARY', 280 ],
92             check_freshness => [ 'BINARY', 280 ],
93             freshness_threshold => [ 'INTEGER', 280 ],
94             event_handler => [ 'Nagios::Command', 280 ],
95             event_handler_enabled => [ 'BINARY', 280 ],
96             low_flap_threshold => [ 'INTEGER', 280 ],
97             high_flap_threshold => [ 'INTEGER', 280 ],
98             flap_detection_enabled => [ 'BINARY', 280 ],
99             flap_detection_options => [ [qw(o d u)], 280 ],
100             process_perf_data => [ 'BINARY', 280 ],
101             retain_status_information => [ 'BINARY', 280 ],
102             retain_nonstatus_information => [ 'BINARY', 280 ],
103             notification_period => [ 'Nagios::TimePeriod', 280 ],
104             notification_interval => [ 'INTEGER', 280 ],
105             notification_options => [ [qw(u w c r)], 280 ],
106             contacts => [ ['Nagios::Contact'], 280 ],
107             contact_groups => [ ['Nagios::ContactGroup'], 280 ],
108             notifications_enabled => [ 'BINARY', 280 ],
109             stalking_options => [ [qw(o w u c)], 280 ],
110             failure_prediction_enabled => [ 'BINARY', 16 ],
111             first_notification_delay => [ 'INTEGER', 280 ],
112             action_url => [ 'STRING', 280 ],
113             notes => [ 'STRING', 280 ],
114             notes_url => [ 'STRING', 280 ],
115             name => [ 'service_description', 134 ],
116             comment => [ 'comment', 280 ],
117             file => [ 'filename', 280 ]
118             },
119             ServiceGroup => {
120             use => [ 'Nagios::ServiceGroup', 18 ],
121             servicegroup_name => [ 'STRING', 18 ],
122             alias => [ 'STRING', 16 ],
123             members => [ [ 'Nagios::Host', 'Nagios::Service' ], 16 ],
124             servicegroup_members => [ ['Nagios::ServiceGroup'], 280 ],
125             name => [ 'servicegroup_name', 22 ],
126             comment => [ 'comment', 22 ],
127             file => [ 'filename', 22 ]
128             },
129             Host => {
130             use => [ 'Nagios::Host', 10 ],
131             host_name => [ 'STRING', 10 ],
132             alias => [ 'STRING', 280 ],
133             address => [ 'STRING', 280 ],
134             parents => [ ['Nagios::Host'], 280 ],
135             hostgroups => [ ['Nagios::HostGroup'], 1304 ],
136             check_command => [ 'STRING', 280 ],
137             max_check_attempts => [ 'INTEGER', 280 ],
138             checks_enabled => [ 'BINARY', 280 ],
139             initial_state => [ [qw(o d u)], 280 ],
140             active_checks_enabled => [ 'BINARY', 280 ],
141             passive_checks_enabled => [ 'BINARY', 280 ],
142             check_freshness => [ 'BINARY', 280 ],
143             check_interval => [ 'INTEGER', 280 ],
144             retry_interval => [ 'INTEGER', 768 ],
145             obsess_over_host => [ 'BINARY', 280 ],
146             freshness_threshold => [ 'INTEGER', 280 ],
147             event_handler => [ 'STRING', 280 ],
148             event_handler_enabled => [ 'BINARY', 280 ],
149             check_period => [ 'Nagios::TimePeriod', 280 ],
150             low_flap_threshold => [ 'INTEGER', 280 ],
151             high_flap_threshold => [ 'INTEGER', 280 ],
152             flap_detection_enabled => [ 'BINARY', 280 ],
153             flap_detection_options => [ [qw(o d u)], 280 ],
154             process_perf_data => [ 'BINARY', 280 ],
155             retain_status_information => [ 'BINARY', 280 ],
156             retain_nonstatus_information => [ 'BINARY', 280 ],
157             notification_period => [ 'Nagios::TimePeriod', 280 ],
158             notification_interval => [ 'INTEGER', 280 ],
159             notification_options => [ [qw(d u r)], 280 ],
160             notifications_enabled => [ 'BINARY', 280 ],
161             stalking_options => [ [qw(o d u)], 280 ],
162             contacts => [ ['Nagios::Contact'], 280 ],
163             contact_groups => [ ['Nagios::ContactGroup'], 16 ],
164             failure_prediction_enabled => [ 'BINARY', 16 ],
165             first_notification_delay => [ 'INTEGER', 280 ],
166             action_url => [ 'STRING', 280 ],
167             notes => [ 'STRING', 280 ],
168             notes_url => [ 'STRING', 280 ],
169             name => [ 'host_name', 280 ],
170             comment => [ 'comment', 280 ],
171             file => [ 'filename', 280 ]
172             },
173             HostGroup => {
174             use => [ 'Nagios::HostGroup', 280 ],
175             hostgroup_name => [ 'STRING', 280 ],
176             alias => [ 'STRING', 280 ],
177             contact_groups => [ ['Nagios::ContactGroup'], 40 ],
178             members => [ ['Nagios::Host'], 1304 ],
179             hostgroup_members => [ ['Nagios::HostGroup'], 280 ],
180             name => [ 'hostgroup_name', 280 ],
181             comment => [ 'comment', 280 ],
182             file => [ 'filename', 280 ]
183             },
184             Contact => {
185             use => [ 'Nagios::Contact', 280 ],
186             contact_name => [ 'STRING', 280 ],
187             alias => [ 'STRING', 280 ],
188             host_notification_period => [ 'Nagios::TimePeriod', 280 ],
189             service_notification_period => [ 'Nagios::TimePeriod', 280 ],
190             host_notification_options => [ [qw(d u r n)], 280 ],
191             service_notification_options => [ [qw(w u c r n)], 280 ],
192             host_notification_commands => [ ['Nagios::Command'], 280 ],
193             service_notification_commands => [ ['Nagios::Command'], 280 ],
194             email => [ 'STRING', 280 ],
195             pager => [ 'STRING', 280 ],
196             host_notifications_enabled => [ 'BINARY', 280 ],
197             service_notifications_enabled => [ 'BINARY', 280 ],
198             can_submit_commands => [ 'BINARY', 280 ],
199             retain_status_information => [ 'BINARY', 280 ],
200             retain_nonstatus_information => [ 'BINARY', 280 ],
201             address1 => [ 'STRING', 16 ],
202             address2 => [ 'STRING', 16 ],
203             address3 => [ 'STRING', 16 ],
204             address4 => [ 'STRING', 16 ],
205             address5 => [ 'STRING', 16 ],
206             address6 => [ 'STRING', 16 ],
207             contactgroups => [ ['Nagios::ContactGroup'], 1040 ],
208             name => [ 'contact_name', 280 ],
209             comment => [ 'comment', 280 ],
210             file => [ 'filename', 280 ]
211             },
212             ContactGroup => {
213             use => [ 'Nagios::ContactGroup', 280 ],
214             contactgroup_name => [ 'STRING', 280 ],
215             alias => [ 'STRING', 280 ],
216             members => [ ['Nagios::Contact'], 1304 ],
217             contactgroup_members => [ ['Nagios::ContactGroup'], 280 ],
218             name => [ 'contactgroup_name', 280 ],
219             comment => [ 'comment', 280 ],
220             file => [ 'filename', 280 ]
221             },
222             Command => {
223             use => [ 'Nagios::Command', 280 ],
224             command_name => [ 'STRING', 280 ],
225             command_line => [ 'STRING', 280 ],
226             name => [ 'command_name', 280 ],
227             comment => [ 'comment', 280 ],
228             file => [ 'filename', 280 ]
229             },
230             TimePeriod => {
231             use => [ 'Nagios::TimePeriod', 280 ],
232             timeperiod_name => [ 'STRING', 280 ],
233             alias => [ 'STRING', 280 ],
234             sunday => [ 'TIMERANGE', 280 ],
235             monday => [ 'TIMERANGE', 280 ],
236             tuesday => [ 'TIMERANGE', 280 ],
237             wednesday => [ 'TIMERANGE', 280 ],
238             thursday => [ 'TIMERANGE', 280 ],
239             friday => [ 'TIMERANGE', 280 ],
240             saturday => [ 'TIMERANGE', 280 ],
241             january => [ 'TIMERANGE', 768 ],
242             february => [ 'TIMERANGE', 768 ],
243             march => [ 'TIMERANGE', 768 ],
244             april => [ 'TIMERANGE', 768 ],
245             may => [ 'TIMERANGE', 768 ],
246             june => [ 'TIMERANGE', 768 ],
247             july => [ 'TIMERANGE', 768 ],
248             august => [ 'TIMERANGE', 768 ],
249             september => [ 'TIMERANGE', 768 ],
250             october => [ 'TIMERANGE', 768 ],
251             november => [ 'TIMERANGE', 768 ],
252             december => [ 'TIMERANGE', 768 ],
253             name => [ 'timeperiod_name', 280 ],
254             comment => [ 'comment', 280 ],
255             file => [ 'filename', 280 ]
256             },
257             ServiceEscalation => {
258             use => [ 'Nagios::ServiceEscalation', 280 ],
259             host_name => [ ['Nagios::Host'], 280 ],
260             hostgroup_name => [ ['Nagios::HostGroup'], 280 ],
261             service_description => [ 'Nagios::Service', 280 ],
262             contacts => [ ['Nagios::Contact'], 280 ],
263             contact_groups => [ ['Nagios::ContactGroup'], 280 ],
264             first_notification => [ 'INTEGER', 280 ],
265             last_notification => [ 'INTEGER', 280 ],
266             notification_interval => [ 'INTEGER', 280 ],
267             escalation_period => [ 'Nagios::TimePeriod', 16 ],
268             escalation_options => [ [qw(w u c r)], 16 ],
269             name => [ 'generated', 280 ],
270             comment => [ 'comment', 280 ],
271             file => [ 'filename', 280 ]
272             },
273             ServiceDependency => {
274             use => [ 'Nagios::ServiceDependency', 280 ],
275             dependent_host_name => [ ['Nagios::Host'], 280 ],
276             dependent_service_description => [ 'Nagios::Service', 280 ],
277             hostgroup_name => [ ['Nagios::HostGroup'], 280 ],
278             dependent_hostgroup_name => [ ['Nagios::HostGroup'], 280 ],
279             host_name => [ ['Nagios::Host'], 280 ],
280             service_description => [ 'Nagios::Service', 280 ],
281             inherits_parent => [ 'INTEGER', 280 ],
282             execution_failure_criteria => [ [qw(o w u c n)], 280 ],
283             execution_failure_options => [ [qw(o w u c n)], 280 ],
284             notification_failure_criteria => [ [qw(o w u c n)], 280 ],
285             notification_failure_options => [ [qw(o w u c n)], 280 ],
286             name => [ 'generated', 280 ],
287             comment => [ 'comment', 280 ],
288             file => [ 'filename', 280 ]
289             },
290             HostEscalation => {
291             use => [ 'Nagios::HostEscalation', 280 ],
292             host_name => [ ['Nagios::Host'], 280 ],
293             hostgroup => [ ['Nagios::HostGroup'], 280 ],
294             contacts => [ ['Nagios::Contact'], 280 ],
295             contact_groups => [ ['Nagios::ContactGroup'], 280 ],
296             first_notification => [ 'INTEGER', 280 ],
297             last_notification => [ 'INTEGER', 280 ],
298             notification_interval => [ 'INTEGER', 280 ],
299             name => [ 'host_name', 280 ],
300             comment => [ 'comment', 280 ],
301             escalation_options => [ [qw(d u r)], 280 ],
302             file => [ 'filename', 280 ]
303             },
304             HostDependency => {
305             use => [ 'Nagios::HostDependency', 280 ],
306             dependent_host_name => [ ['Nagios::Host'], 280 ],
307             dependent_hostgroup_name => [ ['Nagios::HostGroup'], 280 ],
308             host_name => [ ['Nagios::Host'], 280 ],
309             hostgroup_name => [ ['Nagios::HostGroup'], 280 ],
310             inherits_parent => [ 'INTEGER', 16 ],
311             notification_failure_criteria => [ [qw(o w u c n)], 280 ],
312             notification_failure_options => [ [qw(o w u c n)], 280 ],
313             execution_failure_criteria => [ [qw(o w u c n)], 16 ],
314             execution_failure_options => [ [qw(o w u c n)], 280 ],
315             name => [ 'generated', 280 ],
316             comment => [ 'comment', 280 ],
317             file => [ 'filename', 280 ]
318             },
319              
320             # Nagios 1.0 only
321             HostGroupEscalation => {
322             use => [ 'Nagios::HostGroupEscalation', 40 ],
323             hostgroup => [ 'Nagios::HostGroup', 40 ],
324             contact_groups => [ ['Nagios::ContactGroup'], 40 ],
325             first_notification => [ 'INTEGER', 40 ],
326             last_notification => [ 'INTEGER', 40 ],
327             notification_interval => [ 'INTEGER', 40 ],
328             name => [ 'hostgroup', 44 ],
329             comment => [ 'comment', 44 ],
330             file => [ 'filename', 44 ]
331             },
332              
333             # Nagios 2.0 only
334             HostExtInfo => {
335             use => [ 'HostExtInfo', 18 ],
336             host_name => [ 'Nagios::Host', 18 ],
337             hostgroup => [ ['Nagios::HostGroup'], 18 ],
338             notes => [ 'STRING', 16 ],
339             notes_url => [ 'STRING', 16 ],
340             action_url => [ 'STRING', 16 ],
341             icon_image => [ 'STRING', 16 ],
342             icon_image_alt => [ 'STRING', 16 ],
343             vrml_image => [ 'STRING', 16 ],
344             statusmap_image => [ 'STRING', 16 ],
345             '2d_coords' => [ 'STRING', 16 ],
346             '3d_coords' => [ 'STRING', 16 ],
347             name => [ 'host_name', 20 ],
348             comment => [ 'comment', 20 ],
349             file => [ 'filename', 20 ]
350             },
351              
352             # Nagios 2.0 only
353             ServiceExtInfo => {
354             use => [ 'ServiceExtInfo', 18 ],
355             host_name => [ ['Nagios::Host'], 18 ],
356             hostgroup => [ ['Nagios::HostGroup'], 18 ],
357             service_description => [ 'Nagios::Service', 18 ],
358             notes => [ 'STRING', 16 ],
359             notes_url => [ 'STRING', 16 ],
360             action_url => [ 'STRING', 16 ],
361             icon_image => [ 'STRING', 16 ],
362             icon_image_alt => [ 'STRING', 16 ],
363             name => [ 'generated', 20 ],
364             comment => [ 'comment', 20 ],
365             file => [ 'filename', 20 ]
366             }
367             );
368              
369             # create a package for every key in %nagios_setup
370             foreach ( keys(%nagios_setup) ) {
371             create_object_and_methods($_);
372             }
373              
374             =head1 NAME
375              
376             Nagios::Object - Creates perl objects to represent Nagios objects
377              
378             =head1 DESCRIPTION
379              
380             This module contains the code for creating perl objects to represent any of the Nagios objects. All of the perl classes are auto-generated at compile-time, so it's pretty trivial to add new attributes or even entire objects. The following is a list of currently supported classes:
381              
382             Nagios::TimePeriod
383             Nagios::Command
384             Nagios::Contact
385             Nagios::ContactGroup
386             Nagios::Host
387             Nagios::Service
388             Nagios::HostGroup
389             Nagios::ServiceEscalation
390             Nagios::HostDependency
391             Nagios::HostEscalation
392             Nagios::HostGroupEscalation
393             Nagios::ServiceDependency
394             -- next two are for status.dat in Nagios 2.x
395             Nagios::Info
396             Nagios::Program
397              
398             =head1 EXAMPLE
399              
400             use Nagios::Object;
401             my $generic_host = Nagios::Host->new(
402             register => 0,
403             parents => undef,
404             check_command => $some_command,
405             max_check_attempts => 3,
406             checks_enabled => 1,
407             event_handler => $some_command,
408             event_handler_enabled => 0,
409             low_flap_threshold => 0,
410             high_flap_threshold => 0,
411             flap_detection_enabled => 0,
412             process_perf_data => 1,
413             retain_status_information => 1,
414             retain_nonstatus_information => 1,
415             notification_interval => $timeperiod,
416             notification_options => [qw(d u r)],
417             notifications_enabled => 1,
418             stalking_options => [qw(o d u)]
419             );
420              
421             # this will automatically 'use' $generic_host
422             my $localhost = $generic_host->new(
423             host_name => "localhost",
424             alias => "Loopback",
425             address => "127.0.0.1"
426             );
427              
428             my $hostname = $localhost->host_name();
429             printf "max check attempts for $hostname is %s.\n",
430             $localhost->max_check_attempts;
431            
432             $localhost->set_event_handler(
433             Nagios::Command->new(
434             command_name => "new_event_handler",
435             command_line => "/bin/true"
436             )
437             );
438              
439             =head1 METHODS
440              
441             =over 4
442              
443             =item new()
444              
445             Create a new object of one of the types listed above.
446              
447             Calling new() on an existing object will use the LHS object as the template for
448             the object being created. This is mainly useful for creating objects without
449             involving Nagios::Object::Config (like in the test suite).
450              
451             Nagios::Host->new( ... );
452              
453             =cut
454              
455             # ---------------------------------------------------------------------------- #
456             sub new {
457 596     596 1 31292 my $parent = shift;
458 596 100       1033 my $type = ref($parent) ? ref($parent) : $parent;
459 596 50       1427 croak "single argument form of new() no longer supported"
460             if ( @_ % 2 == 1 );
461 596         1722 my %args = @_; # passed-in arguments hash
462              
463 596 100 66     3254 if ( $type eq 'Nagios::Object' && $args{Type} ) {
464 573         1198 $type = delete $args{Type};
465             }
466              
467             # for referencing %nagios_setup
468 596         1864 my $nagios_setup_key = ( split( /::/, $type ) )[1];
469              
470             #print "type: $type, key: $nagios_setup_key\n";
471              
472 596 50       1556 confess
473             "invalid type '$type' for Nagios::Object - does not exist in \%nagios_setup"
474             if ( !exists $nagios_setup{$nagios_setup_key} );
475              
476             # set everything to undef by default
477 16458         27834 my %default
478 596         638 = map { $_ => undef } keys %{ $nagios_setup{$nagios_setup_key} };
  596         3533  
479              
480             # if pre_link is set, don't set objects' resolved/registered flag
481 596 100       3248 if ($pre_link) {
482 572         1046 $default{_has_been_resolved} = undef;
483 572         1030 $default{_has_been_registered} = undef;
484             }
485              
486             # _validate will be called by _set, which will croak if this is wrong
487             else {
488 24         43 $default{_has_been_resolved} = 1;
489 24         42 $default{_has_been_registered} = 1;
490             }
491              
492             # instantiate an object
493 596         1748 my $self = bless( \%default, $type );
494 596         2013 $self->{_nagios_setup_key} = $nagios_setup_key;
495              
496             # fill in the object with it's data from %args
497             # if $pre_link is set, it is expected it will mostly be filled in
498             # after instantiation, so probably not much will happen here
499 596         3453 foreach my $key ( keys %default ) {
500 18246 100 100     43556 if ( exists( $args{$key} ) && defined( $args{$key} ) ) {
501              
502             # timeranges must be parsed into ARRAYs, so parse it here so that
503             # users don't have to figure out the arrays and so we don't have
504             # to export parse_time_range
505 109 100       267 if ( $nagios_setup{$nagios_setup_key}->{$key}[0] eq 'TIMERANGE' )
506             {
507 15         35 $args{$key} = parse_time_range( $args{$key} );
508             }
509 109         192 $default{$key} = $args{$key};
510             }
511             }
512              
513             # this lets Nagios::Object sanely build heirarchies without Object::Config
514             # by letting the caller say $parent->new() rather than, e.g.
515             # Nagios::TimePeriod->new( use => 'parent name' )
516 596 100       2606 if ( ref($parent) ) {
517 1         3 $self->{_use} = $parent;
518 1         8 $self->{use} = $parent->name;
519             }
520              
521 596         2222 return $self;
522             }
523              
524 25040     25040 0 96527 sub setup_key { $_[0]->{_nagios_setup_key} }
525              
526             # ---------------------------------------------------------------------------- #
527             # parse the time range text
528             sub parse_time_range ($) {
529 16     16 0 2044 my $text = shift;
530 16 50 33     97 return $text if ( !defined($text) || ref($text) );
531 16         31 $text =~ s/\s+//g;
532 16 50       34 return undef if ( !$text );
533              
534 16         23 my @retval = ();
535              
536             # convert time to seconds since midnight
537             sub t2s {
538 38     38 0 47 my $t = shift;
539 38         79 my ( $h, $m, $s ) = split /:/, $t, 3;
540 38 50       86 $s = 0 if ( !$s );
541 38         197 $s += $h * 3600;
542 38         42 $s += $m * 60;
543 38         102 return $s;
544             }
545              
546 16         40 foreach my $range ( split /,/, $text ) {
547 19         39 my ( $start, $end ) = split /-/, $range;
548 19         41 push( @retval, [ t2s($start), t2s($end) ] );
549             }
550              
551 16 50       63 return wantarray ? @retval : \@retval;
552             }
553              
554             # ---------------------------------------------------------------------------- #
555             # opposite of parse_time_range
556             sub dump_time_range ($) {
557 190     190 0 226 my $range = shift;
558 190 100       499 return undef if ( !$range );
559 53 50       154 return $range if ( !ref($range) );
560              
561             # convert seconds from midnight to Nagios time format
562             sub s2t {
563 0     0 0 0 my $s = shift;
564 0         0 my $hr = sprintf "%02d", int( $s / 3600 );
565 0         0 my $min = $s % 3600;
566 0         0 my $sec = $min % 60;
567 0         0 $min = sprintf "%02d", int( $min / 60 );
568 0 0       0 return $sec == 0 ? "$hr:$min" : "$hr:$min:$sec";
569             }
570              
571 0         0 my @retval = ();
572 0         0 foreach (@$range) {
573 0         0 push( @retval, s2t( $_->[0] ) . '-' . s2t( $_->[1] ) );
574             }
575 0         0 return join ',', @retval;
576             }
577              
578             =item dump()
579              
580             Output a Nagios define { } block from an object. This is still EXPERIMENTAL,
581             but may eventually be robust enough to use for a configuration GUI. Passing
582             in a single true argument will tell it to flatten the object inheritance on dump.
583              
584             print $object->dump();
585             print $object->dump(1); # flatten
586              
587             =cut
588              
589             # ---------------------------------------------------------------------------- #
590             sub dump {
591 170     170 1 97454 my ( $self, $flatten ) = @_;
592 170         504 my $retval = 'define ';
593              
594 170         889 $retval .= lc( ( split /::/, ref($self) )[1] ) . " {\n";
595              
596 170         570 foreach my $attribute ( $self->list_valid_attributes ) {
597 5070         14026 my $value = $self->$attribute();
598 5070 50 33     13898 next if ( $attribute eq 'register' && !defined $value );
599              
600 5070         12353 my $attrtype = $self->attribute_type($attribute);
601              
602 5070 100 66     26437 if ( blessed $value && UNIVERSAL::can( $value, 'name' ) ) {
    100          
    100          
603              
604             # maybe add an additional check against %nagios_setup
605 180         429 $value = $value->name;
606             }
607             elsif ( $attrtype eq 'TIMERANGE' ) {
608 190         300 $value = dump_time_range($value);
609             }
610             elsif ( ref($value) eq 'ARRAY' ) {
611 317 100       672 $value = join ',', map { blessed $_ ? $_->name : $_ } @$value;
  575         2251  
612             }
613              
614 5070 100 66     29190 if ( exists $self->{$attribute} && defined $self->{$attribute} ) {
    50          
615 1472         5020 $retval .= "\t$attribute $value\n";
616             }
617             elsif ($flatten) {
618 0         0 $retval .= "\t$attribute " . $value . "\n";
619             }
620             }
621              
622 170         1346 $retval .= "}\n";
623             }
624              
625             sub template {
626 20003     20003 0 22835 my $self = shift;
627              
628 20003 100 100     106665 if ( exists $self->{_use} && blessed $self->{_use} ) {
    100          
629 11012         23934 return $self->{_use};
630             }
631              
632             # when objects are built by Nagios::Object::Config, it's necessary
633             # to run another step after parsing to link up all of the objects
634             # this method does it on-demand
635             elsif ( $self->{use} ) {
636 67 50       125 if ( my $parser = $self->{object_config_object} ) {
637 67         157 $parser->resolve($self);
638 67         153 return $self->{_use};
639             }
640             else {
641 0         0 confess
642             "Unable to walk object heirarchy without object configuration.";
643             }
644             }
645             }
646              
647             =item name()
648              
649             This method is common to all classes created by this module. It should always return the textual name for an object. It is used internally by the Nagios::Object modules to allow polymorphism (which is what makes this module so compact). This is the only way to retrieve the name of a template, since they are identified by their "name" field.
650              
651             my $svc_desc = $service->name;
652             my $hostname = $host->name;
653              
654             Which is just short for:
655              
656             my $svc_desc = $service->service_description;
657             my $hostname = $service->host_name;
658              
659             =cut
660              
661             # ---------------------------------------------------------------------------- #
662             my $_name_hack;
663              
664             sub name {
665 1321     1321 1 8593 my $self = shift;
666              
667 1321 100       2568 if ( !$self->register ) {
668 55         218 return $self->{name};
669             }
670             else {
671 1266         2982 my $name_method = $self->_name_attribute;
672 1266 100       2709 if ( $name_method eq 'generated' ) {
673 34         61 $_name_hack++;
674             return
675 34         162 ref($self) . '-'
676             . $_name_hack; # FIXME: this should work but feels wrong
677             }
678              
679 1232         2929 my $name = $self->$name_method();
680              
681             # recurse down on references to get the names, then generate something
682             # more sensible
683 1232 50 66     3021 if ( ref($name) && UNIVERSAL::can( $name, 'name' ) ) {
684 0         0 $name = lc( ref($self) ) . '-' . $name->name;
685 0         0 $name =~ s/^nagios:://;
686 0         0 $name =~ s/::/_/g;
687             }
688 1232         4429 return $name;
689             }
690             }
691              
692             # ---------------------------------------------------------------------------- #
693             # not autogenerated, but needs to exist
694             sub set_name {
695 59     59 0 93 my ( $self, $val ) = @_;
696 59 50       168 confess "cannot set name of objects with multi-key identity"
697             if ( ref $self->{name} eq 'ARRAY' );
698 59         159 $self->{name} = $val;
699             }
700              
701             =item register()
702              
703             Returns true/undef to indicate whether the calling object is registerable or not.
704              
705             if ( $object->register ) { print $object->name, " is registerable." }
706              
707             =cut
708              
709             # ---------------------------------------------------------------------------- #
710             sub register {
711 1864     1864 1 2152 my $self = shift;
712 1864 100 66     5561 return undef if ( defined $self->{register} && $self->{register} == 0 );
713 1769         4396 return 1;
714             }
715              
716             # not autogenerated, but needs to exist
717             sub set_register {
718 58     58 0 178 my ( $self, $value ) = @_;
719 58         180 $self->{register} = $value;
720             }
721              
722             # ---------------------------------------------------------------------------- #
723              
724             =item has_attribute()
725              
726             Returns true/undef to indicate whether the calling object has the attribute specified as the only argument.
727              
728             # check to see if $object has attribute "command_line"
729             die if ( !$object->has_attribute("command_line") );
730              
731             =cut
732              
733 0     0 1 0 sub has_attribute { exists $nagios_setup{ $_[0]->setup_key }->{ $_[1] } }
734              
735             =item list_attributes()
736              
737             Returns a list of valid attributes for the calling object.
738              
739             my @host_attributes = $host->list_attributes();
740              
741             =cut
742              
743 503     503 1 549 sub list_attributes { keys( %{ $nagios_setup{ $_[0]->setup_key } } ) }
  503         1193  
744              
745             sub list_valid_attributes {
746 170     170 0 318 my $self = shift;
747 170         418 my $package = $nagios_setup{ $self->setup_key };
748              
749 170         216 my @valid;
750 170         1147 foreach my $key ( keys %$package ) {
751 5138 100       10521 if ( ( $package->{$key}[1] & NAGIOS_PERL_ONLY ) == 0 ) {
752 5070         8769 push @valid, $key;
753             }
754             }
755              
756 170         3922 return sort @valid;
757             }
758              
759             =item attribute_type()
760              
761             Returns the type of data expected by the object's set_ method for the given attribute. For some fields like notification_options, it may return "char_flag."
762              
763             For "name" attributes, it will simply return whatever %setup_data contains.
764              
765             This method needs some TLC ...
766              
767             my $type = $host->attribute_type("notification_period");
768              
769             =cut
770              
771             sub attribute_type {
772 11548     11548 1 13574 my $self = $_[0];
773              
774             # self field type
775 11548         24901 my $type = $nagios_setup{ $_[0]->setup_key }->{ $_[1] }[0];
776 11548 100       26223 if ( ref($type) eq 'ARRAY' ) {
777 1795 100 66     6019 if ( @$type == 1 ) {
    100          
778 1113         2899 return $type->[0];
779             }
780             elsif ( @$type > 1 && length( $type->[0] ) == 1 ) {
781 678         1550 return "char_flag";
782             }
783              
784             #elsif ( $_[1] eq 'name' || @$type > 1 ) {
785             else {
786 4         19 return $type;
787             }
788             }
789             else {
790 9753         21455 return $type;
791             }
792             }
793              
794             =item attribute_is_list()
795              
796             Returns true if the attribute is supposed to be a list (ARRAYREF).
797              
798             if ( $object->attribute_is_list("members") ) {
799             $object->set_members( [$member] );
800             } else {
801             $object->set_members( $member );
802             }
803              
804             =cut
805              
806             sub attribute_is_list {
807 1200 50   1200 1 2731 my $type = ref( $_[0] ) ? ref( $_[0] ) : $_[0];
808 1200 100       2332 return 1
809             if ( ref $nagios_setup{ $_[0]->setup_key }->{ $_[1] }[0] eq 'ARRAY' );
810 635         2855 undef;
811             }
812              
813             # ---------------------------------------------------------------------------- #
814             # mostly these are only for use by other Nagios::Modules
815             sub resolved {
816 1903 100   1903 0 3697 if ( $_[1] ) { $_[0]->{_has_been_resolved} = $_[1] }
  541         1078  
817 1903         5736 return $_[0]->{_has_been_resolved};
818             }
819              
820             sub registered {
821 1447 100   1447 0 3273 if ( $_[1] ) { $_[0]->{_has_been_registered} = $_[1] }
  503         958  
822 1447         4919 return $_[0]->{_has_been_registered};
823             }
824              
825             sub validate_object_type {
826 1142 50   1142 0 2344 my $type = lc( ref( $_[1] ) ? ref( $_[1] ) : $_[1] );
827 1142         1335 $type =~ s/^nagios:://;
828 1142         4678 my ($result) = grep {/^$type$/i} keys %nagios_setup;
  16242         47486  
829 1142 50       5585 return defined $result ? "Nagios::$result" : undef;
830             }
831              
832             sub list_valid_fields {
833 0 0   0 0 0 my $type = ref( $_[0] ) ? ref(shift) : shift;
834 0         0 $type =~ s/^Nagios:://;
835 0         0 foreach my $key ( keys %nagios_setup ) {
836 0 0       0 if ( lc $key eq lc $type ) {
837 0         0 return keys %{ $nagios_setup{$key} };
  0         0  
838             }
839             }
840 0         0 return undef;
841             }
842              
843             # ---------------------------------------------------------------------------- #
844             # a validating set routine used by all of the autogenerated methods
845             sub _set ($ $ $) {
846 5836     5836   11922 my ( $self, $key, $value ) = @_;
847 5836 50       19151 croak "$key does not exist for this object ... template?"
848             if ( !exists( $self->{$key} ) );
849              
850 5836         11917 my $vf = $nagios_setup{ $self->setup_key };
851              
852 5836 100 66     19300 if ( !$pre_link && !$fast_mode && exists $vf->{$key} ) {
      100        
853              
854             # validate passed in arugments against arrayref in $vf (\%valid_fields)
855 2         3 $self->_validate( $key, $value, @{ $vf->{$key} } );
  2         21  
856             }
857              
858             # Nagios allows the usage of a '+' sign. This breaks member lists.
859             # Ignore the '+' sign completely for now.
860 5836 50 66     21496 if ( ref $vf->{$key}[0] eq 'ARRAY' && $value =~/^\+(.+)$/ ) {
861 0         0 $value = $1;
862             }
863              
864 5836 100 100     18021 if ( ref $vf->{$key}[0] eq 'ARRAY' && $value =~ /,/ ) {
865 287         1725 $value = [ split /\s*,\s*/, $value ];
866             }
867              
868             # set the value (which is an anonymous subroutine)
869 5836 50       10070 if ( defined($value) ) {
870 5836         19959 $self->{$key} = $value;
871             }
872             else {
873 0         0 $self->{$key} = undef;
874             }
875             }
876              
877             # ---------------------------------------------------------------------------- #
878             # verfiy that the type of an object is what it is supposed to be as specified
879             # in the hash in BEGIN
880             sub _validate {
881 2     2   6 my ( $self, $key, $value, $type, $flags ) = @_;
882              
883 2 50 33     9 croak "$key is required but is ($value) undefined"
884             if ( !defined $value
885             && ( $flags & NAGIOS_NO_INHERIT ) == NAGIOS_NO_INHERIT );
886              
887 2 50       6 return $value if ( !defined $value );
888              
889             # types in an arrayref indicate that the value may be a list as well
890             # lists may only be of single characters or objects for now
891 2 50 33     24 if ( ref $type eq 'ARRAY' ) {
    50 33        
    50          
    50          
    50          
    0          
892              
893             # only 1 entry in $type list, so it's probably a class
894 0 0 0     0 if ( @$type == 1 && $type->[0] =~ /^Nagios::.*$/ ) {
895              
896             # process single values as an arrayref anyways for consistency
897 0 0       0 if ( ref($value) ne 'ARRAY' ) { $value = [$value] }
  0         0  
898 0         0 foreach my $val (@$value) {
899 0 0       0 croak "object isa '"
900             . ref($val)
901             . "' when it should be a '$type'"
902             if ( ref($val) ne $type->[0] );
903             }
904             }
905              
906             # all other list entries must be single character type - a,s,d,f style
907             else {
908              
909             # map valid entries onto a hash for easy comparison
910 0         0 my %possible = map { $_ => 1 } @$type;
  0         0  
911              
912             # autosplit
913 0 0       0 if ( ref($value) ne 'ARRAY' ) {
914 0         0 $value = [ split /,/, $value ];
915             }
916 0         0 foreach my $v (@$value) {
917 0 0       0 croak "\"$v\" is an invalid entry for $key"
918             unless ( exists $possible{$v} );
919             }
920             }
921             }
922             elsif ( $type =~ /^Nagios::.*$/ ) {
923 0 0       0 croak "object isa '" . ref($value) . "' when it should be a '$type'"
924             if ( ref($value) ne $type );
925             }
926             elsif ( ref($value) eq 'ARRAY' && $type ne 'TIMERANGE' ) {
927 0         0 croak "$key cannot have multiple " . ref($value) . " values.";
928             }
929             elsif ( $type eq 'BINARY' ) {
930 0 0       0 confess "argument to set_$key must NOT be a reference"
931             if ( ref($value) );
932 0 0 0     0 croak "$key must be 1 or 0" if ( $value != 0 && $value != 1 );
933             }
934             elsif ( $type eq 'STRING' || $type eq 'INTEGER' ) {
935 2 50       6 confess "argument to set_$key must NOT be a reference"
936             if ( ref($value) );
937 2 50       17 croak "$key must have a length greater than 0"
938             if ( length($value) < 1 );
939 2 50 33     6 croak "$key must be an INTEGER"
940             if ( $type eq 'INTEGER' && $value =~ /[^\d]/ );
941             }
942             elsif ( $type eq 'TIMERANGE' ) {
943 0 0       0 croak "TIMERANGE must be an ARRAY refrerence"
944             if ( ref($value) ne 'ARRAY' );
945 0         0 foreach my $rng (@$value) {
946 0 0       0 croak "elements of TIMERANGE must be ARRAY refrerences"
947             if ( ref($rng) ne 'ARRAY' );
948 0 0 0     0 croak "start/end times in ranges must be an integer of seconds"
949             if ( $rng->[0] =~ /[^\d]/ || $rng->[1] =~ /[^\d]/ );
950             }
951             }
952             else {
953 0         0 confess "invalid call to _validate";
954             }
955              
956 2         5 return $value;
957             }
958              
959             # support "hostgroup" alongside "hostgroups" by piggybacking it
960             sub hostgroup_name {
961 0     0 0 0 my $self = shift;
962              
963             # Since this method is available in all objects, perform a check in
964             # the config to see if its actually valid on the object
965 0         0 (my $type = ref $self) =~ s/.*:://;
966 0 0       0 if(!$nagios_setup{$type}{hostgroup_name}) {
967 0         0 return;
968             }
969 0 0       0 if ( $self->can('hostgroup') ) {
970 0         0 return $self->hostgroup(@_);
971             }
972             else {
973 0         0 confess "Called hostgroup() on an object that doesn't support it.";
974             }
975             }
976              
977             sub set_hostgroup_name {
978 0     0 0 0 my $self = shift;
979 0 0       0 if ( $self->can('hostgroup') ) {
980 0         0 my @existing = $self->hostgroup;
981 0         0 return $self->set_hostgroup( [ @existing, shift ] );
982             }
983             else {
984 0         0 confess
985             "Called set_hostgroup() on an object that doesn't support it.";
986             }
987             }
988              
989             # support shorthand "host" for "host_name" ... this is really annoying and
990             # can probably also be automated, but for now it just needs to be fixed
991             sub host {
992 0     0 0 0 my $self = shift;
993 0 0       0 if ( $self->can('host_name') ) {
994 0         0 return $self->host_name(@_);
995             }
996             else {
997 0         0 confess "Called host() on an object that doesn't support it.";
998             }
999             }
1000              
1001             sub set_host {
1002 0     0 0 0 my $self = shift;
1003 0 0       0 if ( $self->can('set_host_name') ) {
1004 0         0 return $self->set_host_name(@_);
1005             }
1006             else {
1007 0         0 confess "Called set_host() on an object that doesn't support it.";
1008             }
1009             }
1010              
1011             # ---------------------------------------------------------------------------- #
1012             # ---------------------------------------------------------------------------- #
1013              
1014             # use %nagios_setup to create all of the known methods at compile time
1015 18         1967281 GENESIS: {
1016 18     18   269 no warnings;
  18         42  
1017              
1018             # this function can be called externally to create another object
1019             # type inside Nagios::Object with all the same capabilities as
1020             # those created at BEGIN - a hash like the one above will have
1021             # to be created and have the exact same name. It'll also have to
1022             # be a global within the namespace
1023             sub create_object_and_methods {
1024 270     270 0 361 my $object = shift;
1025              
1026             # create a package name
1027 270         449 my $pkg = 'Nagios::' . $object;
1028              
1029             # fill in @ISA for each class
1030 270         275 my $isa = do { \@{ $pkg . '::ISA' } };
  270         413  
  270         2347  
1031 270         2252 push( @$isa, 'Nagios::Object' );
1032              
1033             # save off this list of naming (think primary key) attributes
1034             # access them via method $obj->_name_attribute
1035 270         795 my $name_attr_list = $nagios_setup{$object}->{name}[0];
1036 270     1266   961 *{"$pkg\::_name_attribute"} = sub {$name_attr_list};
  270         1171  
  1266         2284  
1037              
1038             # create methods for each entry in $nagios_setup{$object}
1039 270         326 foreach my $method ( keys( %{ $nagios_setup{$object} } ) ) {
  270         1788  
1040              
1041             # name() is a special case and is implemented by hand
1042 4662 100       10703 next if ( $method eq 'name' );
1043              
1044             # the members() method in ServiceGroup is implemented manually (below)
1045             next
1046 4392 100 100     9463 if ( $pkg eq 'Nagios::ServiceGroup' && $method eq 'members' );
1047              
1048 4374         10765 $pkg->_make_method($method);
1049             }
1050              
1051 270         6459 *{"$pkg\::AUTOLOAD"} = \&Nagios::Object::AUTOLOAD;
  270         1394  
1052 270     0   823 *{"$pkg\::DESTROY"} = sub { };
  270         1382  
  0         0  
1053             }
1054              
1055             # create methods on-the-fly
1056             sub _make_method {
1057 4376     4376   6253 my ( $pkg, $method ) = @_;
1058              
1059             # create set_ method
1060 4376     4774   24803 *{"$pkg\::set_$method"} = sub { shift->_set( $method, @_ ); };
  4376         24365  
  4774         11509  
1061              
1062             # create get method
1063 4376         28977 *{"$pkg\::$method"} = sub {
1064 31710     31710   56251 my $self = shift;
1065 31710         61956 my $value = $self->{$method};
1066              
1067 31710 100 100     6423490 if ( defined $value || $method eq 'use' ) {
1068 11707         37308 return $value;
1069             }
1070             else {
1071 20003         37880 my $template = $self->template;
1072 20003 100 66     89266 if ( $template && $template->can($method) ) {
1073 11014         27026 return $template->$method;
1074             }
1075             }
1076 8989         28311 return undef;
1077 4376         647284 }; # end of anonymous "get" subroutine
1078             }
1079             }
1080              
1081 0     0   0 sub DESTROY { }
1082              
1083             sub AUTOLOAD {
1084 3     3   1397 our $AUTOLOAD;
1085              
1086             # this will break if there are ever more than 3 parts to a package name
1087 3         14 my ( $top, $setup_key, $method ) = split /::/, $AUTOLOAD;
1088 3         17 my $pkg = $top . '::' . $setup_key;
1089              
1090 3         4 my $setup_field = $method;
1091 3 50       12 if ( $method =~ /^set_(.*)$/ ) {
1092 0         0 $setup_field = $1;
1093             }
1094              
1095 3 100       12 if ( exists $nagios_setup{$setup_key}->{$setup_field} ) {
1096 2         14 $pkg->_make_method($setup_field);
1097             }
1098             else {
1099 1         16 confess
1100             "Invalid method call. $pkg does not know about method $method.";
1101             }
1102              
1103 2         5 goto \&{$AUTOLOAD};
  2         12  
1104             }
1105              
1106             # ---------------------------------------------------------------------------- #
1107             # ---------------------------------------------------------------------------- #
1108             # special-case methods coded straight into their packages
1109              
1110             1;
1111              
1112             package Nagios::Host;
1113             our $VERSION = $Nagios::Object::VERSION;
1114              
1115             # aliases
1116             sub hostgroups { shift->hostgroup(@_); }
1117             sub set_hostgroups { shift->set_hostgroup(@_); }
1118              
1119             1;
1120              
1121             package Nagios::HostGroup;
1122             our $VERSION = $Nagios::Object::VERSION;
1123              
1124             # aliases
1125 0     0   0 sub hostgroup { shift->hostgroup_name(@_); }
1126 0     0   0 sub set_hostgroup { shift->set_hostgroup_name(@_); }
1127              
1128             1;
1129              
1130             package Nagios::ServiceGroup;
1131 18     18   1429 use Carp;
  18         46  
  18         12175  
1132             our $VERSION = $Nagios::Object::VERSION;
1133              
1134             sub members {
1135 10     10   846 my $self = shift;
1136 10 100       33 if ( $self->{members} ) {
1137 6         11 my @copy = @{ $self->{members} };
  6         25  
1138 6         31 return \@copy;
1139             }
1140             else {
1141 4         20 return [];
1142             }
1143             }
1144              
1145             sub set_members {
1146 6     6   10 my $self = shift;
1147 6         10 my ( @objects, @members );
1148              
1149             # @members will be an arrayref of [ host_name => service_description ]
1150             # or Service objects, depending on whether Nagios::Object::Config
1151             # has resolved yet
1152 6 100       21 if ( $self->resolved ) {
1153 4         9 foreach my $item (@_) {
1154 6 50       17 confess
1155             "set_members() arguments must be objects after resolve_objects() has been called."
1156             unless ( ref($item) );
1157 6         12 push @members, $item;
1158             }
1159             }
1160              
1161             # also, before resolution, append to the list rather than replace it
1162             else {
1163 2 50       7 @members = @{ $self->{members} } if $self->{members};
  0         0  
1164 2         8 foreach my $item (@_) {
1165 2 50 33     20 if ( ref($item) eq 'ARRAY' && @$item == 2 ) {
    50 33        
1166 0         0 push @members, $item;
1167             }
1168             elsif ( defined($item) && length($item) ) {
1169 2         9 push @members, $self->_split_members($item);
1170             }
1171             else {
1172 0         0 confess "Don't know what to do with a $item!";
1173             }
1174             }
1175             }
1176              
1177 6         39 $self->{members} = \@members;
1178             }
1179              
1180             sub _split_members {
1181 2     2   5 my ( $self, $string ) = @_;
1182 2         2 my @out;
1183 2         20 my @pieces = split /\s*,\s*/, $string;
1184 2         11 for ( my $i = 0; $i < @pieces; $i += 2 ) {
1185 6         24 push @out, [ $pieces[$i] => $pieces[ $i + 1 ] ];
1186             }
1187              
1188             #warn Data::Dumper::Dumper(\@out);
1189 2         10 return @out;
1190             }
1191              
1192             1;
1193              
1194             package Nagios::Service;
1195             our $VERSION = $Nagios::Object::VERSION;
1196              
1197             1;
1198              
1199             __END__