File Coverage

blib/lib/Unix/Conf/Bind8/Conf/Logging.pm
Criterion Covered Total %
statement 21 157 13.3
branch 0 104 0.0
condition 0 6 0.0
subroutine 7 23 30.4
pod 10 10 100.0
total 38 300 12.6


line stmt bran cond sub pod time code
1             # Logging
2             #
3             # Copyright Karthik Krishnamurthy
4              
5             =head1 NAME
6              
7             Unix::Conf::Bind8::Conf::Logging - Class representing the 'logging'
8             directive in a Bind8 Configuration file.
9              
10             =head1 SYNOPSIS
11              
12             use Unix::Conf::Bind8;
13             my ($conf, $logging, $channel, $ret);
14              
15             $conf = Unix::Conf::Bind8->new_conf (
16             FILE => '/etc/named.conf',
17             SECURE_OPEN => 1,
18             ) or $conf->die ("couldn't open `named.conf'");
19            
20             #
21             # Ways to get a Logging object.
22             #
23              
24             # or create a new logging object
25             $logging = $conf->new_logging (
26             CHANNELS => [
27             {
28             NAME => 'my_file_chan',
29             OUTPUT => 'file',
30             FILE => {
31             PATH => '/var/log/named/file_chan.log',
32             VERSIONS => 3,
33             SIZE => '10k',
34             },
35             SEVERITY => { NAME => 'debug', LEVEL => '3' },
36             'PRINT-TIME' => 'yes',
37             'PRINT-SEVERITY' => 'yes',
38             'PRINT-CATEGORY' => 'yes'
39             },
40             {
41             NAME => 'my_syslog_chan',
42             OUTPUT => 'syslog',
43             SYSLOG => 'daemon',
44             SEVERITY => { NAME => 'info' },
45             'PRINT-TIME' => 'yes',
46             'PRINT-SEVERITY' => 'yes',
47             'PRINT-CATEGORY' => 'yes'
48             },
49             ],
50             CATEGORIES => [
51             [ db => [ qw (my_file_chan default_debug default_syslog) ] ],
52             [ 'lame-servers' => [ qw (null) ], ],
53             [ cname => [ qw (null) ], ],
54             ['xfer-out' => [ qw (default_stderr) ], ]
55             ],
56             WHERE => 'FIRST',
57             ) or $logging->die ("couldn't create logging");
58              
59             # get an existing logging object
60             $logging = $conf->get_logging ()
61             or $logging->die ("couldn't get logging");
62            
63             #
64             # Operations that can be performed on a Logging object.
65             #
66              
67             # create new channel
68             $channel = $logging->new_channel (
69             NAME => 'new_chan',
70             OUTPUT => 'syslog',
71             SYSLOG => 'info',
72             SEVERITY => { NAME => 'debug', LEVEL => 3 },
73             'PRINT-TIME' => 'yes',
74             'PRINT-SEVERITY' => 'no',
75             'PRINT-CATEGORY => 'yes',
76             ) or $channel->die ("couldn't create `new_chan'");
77              
78             # or get an already defined channel
79             $channel = $logging->get_channel ('my_file_chan')
80             or $channel->die ("couldn't get `my_file_chan'");
81              
82             $ret = $logging->delete_channel ('my_file_chan')
83             or $ret->die ("couldn't delete channel `my_file_chan'");
84              
85             # For further operations on channel objects refer to the
86             # documentation for Unix::Conf::Bind8::Conf::Logging::Channel
87              
88             # delete define channel
89             $ret = $logging->delete_channel ('my_syslog_chan')
90             or $ret->die
91              
92             # iterate through defined channels
93             printf "%s\n", $_->name () for ($logging->channels ());
94              
95             # set channels for categories
96             $ret = $logging->category (
97             qw (eventlib new_chan default_syslog)
98             ) or $ret->die ("couldn't set channels for category `eventlib'");
99            
100             # delete categories
101             $ret = $logging->delete_category ('db')
102             or $ret->die ("coudn't delete category `db'");
103              
104             # print out defined categories
105             # note the difference in the usage for channels () and categories ().
106             print "$_\n" for ($logging->categories ());
107              
108             =head1 DESCRIPTION
109              
110             This class has methods to handle the various aspects of the logging statement.
111             Channels are implemented as a sub class, while categories are handled within
112             this class itself.
113              
114             =cut
115              
116             package Unix::Conf::Bind8::Conf::Logging;
117              
118 10     10   50 use strict;
  10         19  
  10         324  
119 10     10   77 use warnings;
  10         17  
  10         250  
120 10     10   49 use Unix::Conf;
  10         19  
  10         191  
121              
122 10     10   55 use Unix::Conf::Bind8::Conf::Directive;
  10         15  
  10         404  
123             our @ISA = qw (Unix::Conf::Bind8::Conf::Directive);
124              
125 10     10   50 use Unix::Conf::Bind8::Conf;
  10         16  
  10         230  
126 10     10   49 use Unix::Conf::Bind8::Conf::Lib;
  10         17  
  10         1323  
127 10     10   6656 use Unix::Conf::Bind8::Conf::Logging::Channel;
  10         32  
  10         20875  
128              
129             =over 4
130              
131             =item new ()
132              
133             Arguments
134             CHANNELS => {
135             NAME => 'channel-name',
136             OUTPUT => 'value', # syslog|file|null
137             FILE => { # only if OUTPUT eq 'file'
138             PATH => 'file-name',
139             VERSIONS => number,
140             SIZE => size_spec,
141             },
142             SYSLOG => 'facility-name',# only if OUTPUT eq 'syslog'
143             SEVERITY => 'severity-name',
144             'PRINT-TIME' => 'value', # yes|no
145             'PRINT-SEVERITY' => 'value', # yes|no
146             'PRINT-CATEGORY' => 'value', # yes|no
147             }
148             or
149             CHANNELS => [
150             {
151             NAME => 'channel-name',
152             OUTPUT => 'value', # syslog|file|null
153             FILE => { # only if OUTPUT eq 'file'
154             PATH => 'file-name',
155             VERSIONS => number,
156             SIZE => size_spec,
157             },
158             SYSLOG => 'facility-name',# only if OUTPUT eq 'syslog'
159             SEVERITY => 'severity-name',
160             'PRINT-TIME' => 'value', # yes|no
161             'PRINT-SEVERITY' => 'value', # yes|no
162             'PRINT-CATEGORY' => 'value', # yes|no
163             },
164             ],
165             CATEGORIES => [
166             [ CATEGORY-NAME => [ qw (channel1 channel2) ] ],
167             ],
168             WHERE => 'FIRST'|'LAST'|'BEFORE'|'AFTER'
169             WARG => Unix::Conf::Bind8::Conf::Directive subclass object
170             # WARG is to be provided only in case WHERE eq 'BEFORE
171             # or WHERE eq 'AFTER'
172             PARENT => reference, # to the Conf object datastructure.
173              
174             Class constructor.
175             Create a new Unix::Conf::Bind8::Conf::Logging object, initialize it, and
176             return it on success, or an Err object on failure. Do not use this constructor
177             directly. Use the Unix::Conf::Bind8::Conf::new_logging () method instead.
178              
179             =cut
180              
181             sub new
182             {
183             # discard the invocant class
184 0     0 1   shift ();
185 0           my %args = @_;
186 0           my $new = bless ({});
187 0           my $ret;
188              
189 0 0         $args{PARENT} || return (Unix::Conf->_err ('new', "PARENT not specified"));
190 0 0         $ret = $new->_parent ($args{PARENT}) or return ($ret);
191 0 0         if ($args{CHANNELS}) {
192 0           my $channels;
193 0 0 0       if (ref ($args{CHANNELS}) && UNIVERSAL::isa ($args{CHANNELS}, 'HASH')) {
194 0           $channels = [ $args{CHANNELS} ]
195             }
196             else {
197 0           $channels = $args{CHANNELS};
198             }
199 0           for (@{$channels}) {
  0            
200 0 0         $ret = $new->new_channel (%{$_}) or return ($ret);
  0            
201             }
202             }
203 0 0         if ($args{CATEGORIES}) {
204 0           for (@{$args{CATEGORIES}}) {
  0            
205 0 0         $ret = $new->category (@{$_}) or return ($ret);
  0            
206             }
207             }
208 0 0         $ret = Unix::Conf::Bind8::Conf::_add_logging ($new) or return ($ret);
209 0 0         $args{WHERE} = 'LAST' unless ($args{WHERE});
210 0 0         $ret = Unix::Conf::Bind8::Conf::_insert_in_list ($new, $args{WHERE}, $args{WARG})
211             or return ($ret);
212 0           return ($new);
213             }
214              
215             =item category ()
216              
217             Arguments
218             'CATEGORY-NAME',
219             LIST
220             or
221             [ LIST ] # of legal channel names
222              
223             Object method.
224             Get/Set the object's channel attribute. If the an array reference is passed
225             as the second argument, sets the catetgory 'CATEGORY-NAME' channels to the
226             elements of the array ref.
227             Returns true if able to set channels if array ref passed as the second
228             argument, an Err object otherwise. If second argument is not passed, then
229             returns the channels set for category as an array reference if defined,
230             an Err object otherwise.
231              
232             =cut
233              
234             sub category
235             {
236 0     0 1   my $self = shift ();
237 0           my $category = shift ();
238              
239 0 0         return (Unix::Conf->_err ('category', "illegal category `$category'"))
240             unless (__valid_category ($category));
241 0 0         if (@_) {
242 0           my ($channels, $ret, $chan);
243 0 0         if (ref ($_[0])) {
244 0 0         return (Unix::Conf->_err ('category', "expected arguments LIST or [ LIST ]"))
245             unless (UNIVERSAL::isa ($_[0], 'ARRAY'));
246 0           $channels = $_[0];
247             }
248             else {
249 0           $channels = \@_;
250             }
251 0           for (@$channels) {
252 0 0         $ret = __valid_channel ($self, $_) or return ($ret)
253             }
254              
255 0           for (@$channels) {
256 0           $self->{categories}{$category}{$_} = 1;
257             # don't set for predef channels as we can't get them
258 0 0         next if (_is_predef_channel ($_));
259 0 0         $chan = $self->get_channel ($_) or return ($chan);
260 0 0         $ret = $chan->_add_category ($category) or return ($ret);
261             }
262 0           $self->dirty (1);
263 0           return (1);
264             }
265             return (
266 0           defined ($self->{categories}{$category}) ?
267 0 0         [ keys (%{$self->{categories}{$category}}) ] :
268             Unix::Conf->_err ('category', "category `$category' not defined")
269             );
270             }
271              
272             =item add_to_category ()
273              
274             Arguments
275             category,
276             LIST # of channel names
277              
278             Object method.
279             Adds to the channels defined for category `categtory' and returns true on success,
280             an Err object otherwise.
281              
282             =cut
283              
284             sub add_to_category
285             {
286 0     0 1   my $self = shift ();
287 0           my $category = shift ();
288 0           my ($ret, $chan);
289              
290 0 0         return (Unix::Conf->_err ("add_to_category", "illegal category `$category'"))
291             unless (__valid_category ($category));
292 0 0         return (Unix::Conf->_err ("add_to_category", "channels to be added not passed"))
293             unless (@_);
294              
295 0           for (@_) {
296 0 0         $ret = __valid_channel ($self, $_) or return ($ret);
297 0 0         return (Unix::Conf->_err ("add_to_category", "channel `$_' already defined for $category"))
298             if ($self->{categories}{$category}{$_});
299             }
300              
301             # set categories used for channel
302 0           for (@_) {
303             # don't set for predef channels as we can't get them
304 0 0         next if (_is_predef_channel ($_));
305 0 0         $chan = $self->get_channel ($_) or return ($chan);
306 0 0         $ret = $chan->_add_category ($category) or return ($ret);
307             }
308              
309 0           @{$self->{categories}{$category}}{@_} = (1) x @_;
  0            
310 0           $self->dirty (1);
311 0           return (1);
312             }
313              
314             =item delete_from_category ()
315              
316             Arguments
317             category,
318             LIST # of channel names
319              
320             Object method.
321             Deletes from the channels defined for category `category' and returns true on success,
322             an Err object otherwise. If all the channels defined for that category is deleted,
323             the category itself is deleted.
324              
325             =cut
326              
327             sub delete_from_category
328             {
329 0     0 1   my $self = shift ();
330 0           my $category = shift ();
331 0           my ($ret, $chan);
332              
333 0 0         return (Unix::Conf->_err ("delete_from_category", "illegal category `$category'"))
334             unless (__valid_category ($category));
335 0 0         return (Unix::Conf->_err ("delete_from_category", "channels to be added not passed"))
336             unless (@_);
337              
338 0           for (@_) {
339 0 0         $ret = __valid_channel ($self, $_) or return ($ret);
340 0 0         return (Unix::Conf->_err ("delete_from_category", "channel `$_' not defined for $category"))
341             unless ($self->{categories}{$category}{$_});
342             }
343              
344             # delete categories used for channel
345 0           for (@_) {
346             # don't set for predef channels as we can't get them
347 0 0         next if (_is_predef_channel ($_));
348 0 0         $chan = $self->get_channel ($_) or return ($chan);
349 0 0         $ret = $chan->_delete_category ($category) or return ($ret);
350             }
351              
352 0           delete (@{$self->{categories}{$category}}{@_});
  0            
353 0           delete ($self->{categories}{$category})
354 0 0         unless (keys (%{$self->{categories}{$category}}));
355 0           $self->dirty (1);
356 0           return (1);
357             }
358              
359             =item delete_category ()
360              
361             Arguments
362             'CATEGORY-NAME',
363              
364             Object method.
365             Deletes category named by 'CATEGORY-NAME', and returns true if successful,
366             an Err object otherwise.
367              
368             =cut
369              
370             sub delete_category
371             {
372 0     0 1   my ($self, $category) = @_;
373              
374 0 0         return (Unix::Conf->_err ('delete_category', "illegal category `$category'"))
375             unless (__valid_category ($category));
376 0 0         return (Unix::Conf->_err ('delete_category', "`$category' not explicitly defined"))
377             unless (defined ($self->{categories}{$category}));
378 0           delete ($self->{categories}{$category});
379 0           $self->dirty (1);
380 0           return (1);
381             }
382              
383             =item categories ()
384              
385             Object method.
386             Iterate through defined categories, returning names of all defined categories
387             in a list context, or one at a time in a scalar context.
388              
389             =cut
390              
391             sub categories
392             {
393             return (
394 0 0   0 1   wantarray () ? keys (%{$_[0]->{categories}}) : (each (%{$_[0]->{categories}}))[0]
  0            
  0            
395             );
396             }
397              
398             ################################## CHANNEL #####################################
399             # #
400              
401             # put this in the logging object later on, since it doesn't have to be shared
402             # across conf objects
403              
404             =item new_channel ()
405              
406             Arguments
407             {
408             NAME => 'channel-name',
409             OUTPUT => 'value', # syslog|file|null
410             FILE => 'file-name', # only if OUTPUT eq 'file'
411             SYSLOG => 'facility-name',# only if OUTPUT eq 'syslog'
412             SEVERITY => 'severity-name',
413             'PRINT-TIME' => 'value', # yes|no
414             'PRINT-SEVERITY' => 'value', # yes|no
415             'PRINT-CATEGORY' => 'value', # yes|no
416             }
417              
418             Object method.
419             This method is a wrapper around the class constructor for
420             Unix::Conf::Bind8::Conf::Logging::Channel. Use this method instead of the
421             accessing the constructor directly.
422             Returns a new Unix::Conf::Bind8::Conf::Logging::Channel object on success,
423             an Err object otherwise.
424              
425             =cut
426              
427             sub new_channel
428             {
429 0     0 1   my $self = shift ();
430 0           return (Unix::Conf::Bind8::Conf::Logging::Channel->new (@_, PARENT => $self));
431             }
432              
433             =item get_channel ()
434              
435             Arguments
436             'CHANNEL-NAME',
437              
438             Object method.
439             Returns a channel object for 'CHANNEL-NAME', if defined (either through a call
440             to new_channel (), or one defined while parsing the configuration file), an
441             Err object otherwise.
442              
443             =cut
444              
445             sub get_channel
446             {
447 0 0   0 1   return (Unix::Conf->_err ('get_channel', "channel name not specified"))
448             unless ($_[1]);
449 0           return (_get_channel (@_));
450             }
451              
452             =item delete_channel ()
453            
454             Arguments
455             'CHANNEL-NAME'
456              
457             Object method.
458             Deletes channel object for 'CHANNEL-NAME', if defined (either through a call
459             to new_channel (), or one defined while parsing the configuration file), an
460             Err object otherwise.
461              
462             =cut
463              
464             sub delete_channel
465             {
466 0     0 1   my ($self, $name) = @_;
467 0           my $channel;
468 0 0         $channel = _get_channel ($self, $name) or return ($channel);
469 0           return ($channel->delete ());
470             }
471              
472             =item channels ()
473              
474             Class/Object method
475             Iterates through the list of defined Unix::Conf::Bind8::Conf::Logging::Channel
476             objects, returning one at a time when called in scalar context, or a list of
477             all defined objects when called in list context.
478              
479             =cut
480              
481             sub channels
482             {
483             return (
484 0 0   0 1   wantarray () ? values (%{$_[0]->{channels}}) : (each (%{$_[0]->{channels}}))[1]
  0            
  0            
485             );
486             }
487              
488             sub _add_channel
489             {
490 0     0     my $obj = $_[0];
491            
492 0           my ($name, $parent);
493 0 0         return (Unix::Conf->_err ("_add_channel", "channel object not specified"))
494             unless ($obj);
495 0 0         $name = $obj->name () or return ($name);
496 0 0         $parent = $obj->_parent () or return ($parent);
497 0 0         return (Unix::Conf->_err ("_add_channel", "channel `$name' already defined"))
498             if ($parent->{channels}{$name});
499 0           $parent->{channels}{$name} = $obj;
500 0           return (1);
501             }
502              
503             sub _get_channel
504             {
505 0     0     my ($self, $name) = @_;
506              
507 0 0         return (Unix::Conf->_err ("_get_channel", "channel name not specified"))
508             unless ($name);
509 0 0         return (Unix::Conf->_err ("_get_channel", "channel `$name' not defined"))
510             unless ($self->{channels}{$name});
511 0           return ($self->{channels}{$name});
512             }
513              
514             sub _del_channel
515             {
516 0     0     my ($logging, $name) = @_;
517            
518 0 0         return (Unix::Conf->_err ("_del_channel", "channel object not specified"))
519             unless ($name);
520 0 0         return (Unix::Conf->_err ('_del_channel', "channel `$name' is predefined, cannot be deleted"))
521             if (_is_predef_channel ($name));
522 0 0         return (Unix::Conf->_err ("_del_channel", "channel `$name' not defined"))
523             unless ($logging->{channels}{$name});
524 0           delete ($logging->{channels}{$name});
525 0           return (1);
526             }
527              
528             sub _is_predef_channel
529             {
530 0     0     my $name = $_[0];
531              
532 0 0         return (Unix::Conf->_err ('_is_predef_channel', "`$name' not a predefined channel"))
533             if ($name !~ /^(default_syslog|default_debug|default_stderr|null)$/);
534 0           return (1);
535             }
536              
537             sub __valid_channel
538             {
539 0     0     my ($self, $name) = @_;
540            
541 0 0 0       return (Unix::Conf->_err ('__valid_channel', "invalid channel `$name'"))
542             unless (_is_predef_channel ($name) || _get_channel ($self, $name));
543 0           return (1);
544             }
545              
546             # END #
547             ################################## CHANNEL #####################################
548              
549              
550             sub __render
551             {
552 0     0     my $self = $_[0];
553 0           my $rendered;
554              
555 0           $rendered = "logging {\n";
556            
557             # render all channels
558 0           for (values (%{$self->{channels}})) {
  0            
559 0           $rendered .= $_->__render ();
560             }
561              
562 0           my $channels;
563             # render defined categories
564 0           for (keys (%{$self->{categories}})) {
  0            
565 0 0         $channels = $self->category ($_) or return ($channels);
566 0           local $" = "; ";
567 0           $rendered .= "\tcategory $_ { @$channels };\n"
568             }
569 0           $rendered .= "};";
570 0           return ($self->_rstring (\$rendered));
571             }
572              
573             1;
574             __END__