[augeas-devel] [PATCH] Add a lense for parsing /etc/syslog.conf and tests.
Raphaël Pinson
raphink at gmail.com
Wed Nov 3 20:12:35 UTC 2010
Hi Mat,
The lens and test apply and work fine on my tree, and the lens looks great,
congrats.
Raphael
On Wed, Nov 3, 2010 at 5:04 PM, Mathieu Arnold <mat at mat.cc> wrote:
> From: Mathieu Arnold <mat at FreeBSD.org>
>
> ---
> lenses/syslog.aug | 248 +++++++++++++++++++++++++++++++++++
> lenses/tests/test_syslog.aug | 293
> ++++++++++++++++++++++++++++++++++++++++++
> tests/Makefile.am | 1 +
> 3 files changed, 542 insertions(+), 0 deletions(-)
> create mode 100644 lenses/syslog.aug
> create mode 100644 lenses/tests/test_syslog.aug
>
> diff --git a/lenses/syslog.aug b/lenses/syslog.aug
> new file mode 100644
> index 0000000..91d0d3a
> --- /dev/null
> +++ b/lenses/syslog.aug
> @@ -0,0 +1,248 @@
> +(*
> +Module: Syslog
> + parses /etc/syslog.conf
> +
> +Author: Mathieu Arnold <mat at FreeBSD.org>
> +
> +About: Reference
> + This lens tries to keep as close as possible to `man 5 resolv.conf`
> where possible.
> + An online source being :
> + http://www.freebsd.org/cgi/man.cgi?query=syslog.conf&sektion=5
> +
> +About: Licence
> + This file is licensed under the BSD License.
> +
> +About: Lens Usage
> + To be documented
> +
> +About: Configuration files
> + This lens applies to /etc/syslog.conf. See <filter>.
> +
> + *)
> +module Syslog =
> + autoload xfm
> +
> +
> (************************************************************************
> + * Group: USEFUL PRIMITIVES
> +
> *************************************************************************)
> +
> + (* Group: Comments and empty lines *)
> +
> + (* Variable: empty *)
> + let empty = Util.empty
> + (* Variable: eol *)
> + let eol = Util.eol
> + (* Variable: sep_tab *)
> + let sep_tab = Sep.tab
> +
> + (* View: comment
> + Map comments into "#comment" nodes
> + Can't use Util.comment as #+ and #! have a special meaning *)
> + let comment =
> + [ label "#comment" . del /#[ \t]*/ "# "
> + . store /([^ \t\n+!-].*[^ \t\n]|[^ \t\n+!-])/ . eol ]
> +
> + (* Group: single characters macro *)
> +
> + (* Variable: comma
> + Deletes a comma and default to it
> + *)
> + let comma = Util.del_str ","
> + (* Variable: colon
> + Deletes a colon and default to it
> + *)
> + let colon = Util.del_str ":"
> + (* Variable: semicolon
> + Deletes a semicolon and default to it
> + *)
> + let semicolon = Util.del_str ";"
> + (* Variable: at
> + Deletes a at and default to it
> + *)
> + let at = Util.del_str "@"
> + (* Variable: dot
> + Deletes a dot and default to it
> + *)
> + let dot = Util.del_str "."
> + (* Variable: pipe
> + Deletes a pipe and default to it
> + *)
> + let pipe = Util.del_str "|"
> + (* Variable: plus
> + Deletes a plus and default to it
> + *)
> + let plus = Util.del_str "+"
> + (* Variable: bang
> + Deletes a bang and default to it
> + *)
> + let bang = Util.del_str "!"
> +
> + (* Variable: opt_hash
> + deletes an optional # sign
> + *)
> + let opt_hash = del /#?/ ""
> + (* Variable: opt_plus
> + deletes an optional + sign
> + *)
> + let opt_plus = del /\+?/ ""
> +
> + (* Group: various macros *)
> +
> + (* Variable: word
> + our version can't start with [_.-] because it would mess up the
> grammar
> + *)
> + let word = /[A-Za-z0-9][A-Za-z0-9_.-]*/
> +
> + (* Variable: comparison
> + a comparison is an optional ! with optionaly some of [<=>]
> + *)
> + let comparison = /(!|[<=>]+|![<=>]+)/
> +
> + (* Variable: token
> + alphanum or "*"
> + *)
> + let token = /([a-z0-9]+|\*)/
> +
> + (* Variable: file_r
> + a file begins with a / and get almost anything else after
> + *)
> + let file_r = /\/[^ \t\n]+/
> +
> + (* Variable: loghost_r
> + Matches a hostname, that is labels speparated by dots, labels
> can't
> + start or end with a "-". maybe a bit too complicated for what
> it's worth *)
> + let loghost_r =
> /[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*/
> +
> + (* Group: Function *)
> +
> + (* View: label_opt_list
> + Uses Build.opt_list to generate a list of labels
> +
> + Parameters:
> + l:string - the label name
> + r:lens - the lens going after the label
> + s:lens - the separator lens passed to Build.opt_list
> + *)
> + let label_opt_list (l:string) (r:lens) (s:lens) = Build.opt_list [
> label l . r ] s
> +
> + (* View: label_opt_list_or
> + Either label_opt_list matches something or it emits a single label
> + with the "or" string.
> +
> + Parameters:
> + l:string - the label name
> + r:lens - the lens going after the label
> + s:lens - the separator lens passed to Build.opt_list
> + or:string - the string used if the label_opt_list does not match
> anything
> + *)
> + let label_opt_list_or (l:string) (r:lens) (s:lens) (or:string) =
> + ( label_opt_list l r s | [ label l . store or ] )
> +
> +
> +
> (************************************************************************
> + * Group: LENSE DEFINITION
> +
> *************************************************************************)
> +
> + (* Group: selector *)
> +
> + (* View: facilities
> + a list of facilities, separated by commas
> + *)
> + let facilities = label_opt_list "facility" (store token) comma
> +
> + (* View: selector
> + a selector is a list of facilities, an optional comparison and a
> level
> + *)
> + let selector = facilities . dot .
> + [ label "comparison" . store comparison]? .
> + [ label "level" . store token ]
> +
> + (* View: selectors
> + a list of selectors, separated by semicolons
> + *)
> + let selectors = label_opt_list "selector" selector semicolon
> +
> + (* Group: action *)
> +
> + (* View: file
> + a file may start with a "-" meaning it does not gets sync'ed
> everytime
> + *)
> + let file = [ Build.xchgs "-" "no_sync" ]? . [ label "file" . store
> file_r ]
> +
> + (* View: loghost
> + a loghost is an @ sign followed by the hostname and a possible
> port
> + *)
> + let loghost = at . [ label "hostname" . store loghost_r ] .
> + (colon . [ label "port" . store /[0-9]+/ ] )?
> +
> + (* View: users
> + a list of users or a "*"
> + *)
> + let users = label_opt_list_or "user" (store word) comma "*"
> +
> + (* View: logprogram
> + a log program begins with a pipe
> + *)
> + let logprogram = pipe . [ label "program" . store /[^ \t\n][^\n]+[^
> \t\n]/ ]
> +
> + (* View: action
> + an action is either a file, a host, users, or a program
> + *)
> + let action = (file | loghost | users | logprogram)
> +
> + (* Group: Entry *)
> +
> + (* View: entry
> + an entry contains selectors and an action
> + *)
> + let entry = [ label "entry" .
> + selectors . sep_tab .
> + [ label "action" . action ] . eol ]
> +
> + (* View: entries
> + entries are either comments/empty lines or entries
> + *)
> + let entries = (empty | comment | entry)*
> +
> + (* Group: Program matching *)
> +
> + (* View: programs
> + a list of programs
> + *)
> + let programs = label_opt_list_or "program" (store word) comma "*"
> +
> + (* View: program
> + a program begins with an optional hash, a bang, and an optional +
> or -
> + *)
> + let program = [ label "program" . opt_hash . bang .
> + ( opt_plus | [ Build.xchgs "-" "reverse" ] ) .
> + programs . eol . entries ]
> +
> + (* Group: Hostname maching *)
> +
> + (* View: hostnames
> + a list of hostnames
> + *)
> + let hostnames = label_opt_list_or "hostname" (store Rx.word) comma
> "*"
> +
> + (* View: hostname
> + a program begins with an optional hash, and a + or -
> + *)
> + let hostname = [ label "hostname" . opt_hash .
> + ( plus | [ Build.xchgs "-" "reverse" ] ) .
> + hostnames . eol . entries ]
> +
> + (* Group: Top of the tree *)
> +
> + (* View: lns
> + generic entries then programs or hostnames matching blocs
> + *)
> + let lns = entries . ( program | hostname )*
> +
> + (* Variable: filter
> + all you need is /etc/syslog.conf
> + *)
> + let filter = incl "/etc/syslog.conf"
> +
> + let xfm = transform lns filter
> +
> diff --git a/lenses/tests/test_syslog.aug b/lenses/tests/test_syslog.aug
> new file mode 100644
> index 0000000..3685535
> --- /dev/null
> +++ b/lenses/tests/test_syslog.aug
> @@ -0,0 +1,293 @@
> +module Test_syslog =
> +
> + let conf="# $FreeBSD: src/etc/syslog.conf,v 1.30.2.1 2009/08/03
> 08:13:06 kensmith Exp $
> +#
> +
> +daemon.info /var/log/cvsupd.log
> +security.* -/var/log/security
> +*.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err
> /var/log/messages
> +uucp,news.crit /var/log/spooler
> +*.emerg *
> +daemon.!info /var/log/foo
> +daemon.<=info /var/log/foo
> +daemon.!<=info /var/log/foo
> +*.* @syslog.far.away
> +*.* @syslog.far.away:123
> +*.* foo,bar
> +*.* |\"/usr/bin/soft arg\"
> +!startslip
> +# get that out
> +*.* /var/log/slip.log
> +!pppd,ppp
> +
> +*.* /var/log/ppp.log
> +!+startslip
> +*.* /var/log/slip.log
> +!-startslip
> +*.* /var/log/slip.log
> +#!pppd
> +*.* /var/log/ppp.log
> ++foo.example.com
> +daemon.info /var/log/cvsupd.log
> ++foo.example.com,bar.example.com
> +daemon.info /var/log/cvsupd.log
> +#+bar.example.com
> +daemon.info /var/log/cvsupd.log
> +-foo.example.com
> +daemon.info /var/log/cvsupd.log
> ++*
> +daemon.info /var/log/cvsupd.log
> +!*
> +daemon.info /var/log/cvsupd.log
> +"
> +
> + test Syslog.lns get conf =
> + { "#comment" = "$FreeBSD: src/etc/syslog.conf,v 1.30.2.1
> 2009/08/03 08:13:06 kensmith Exp $" }
> + { }
> + { }
> + { "entry"
> + { "selector" { "facility" = "daemon" } { "level" = "info" } }
> + { "action" { "file" = "/var/log/cvsupd.log" } }
> + }
> + { "entry"
> + { "selector" { "facility" = "security" } { "level" = "*" } }
> + { "action" { "no_sync" } { "file" = "/var/log/security" } }
> + }
> + { "entry"
> + { "selector" { "facility" = "*" } { "level" = "notice" } }
> + { "selector" { "facility" = "authpriv" } { "level" = "none" } }
> + { "selector" { "facility" = "kern" } { "level" = "debug" } }
> + { "selector" { "facility" = "lpr" } { "level" = "info" } }
> + { "selector" { "facility" = "mail" } { "level" = "crit" } }
> + { "selector" { "facility" = "news" } { "level" = "err" } }
> + { "action" { "file" = "/var/log/messages" } }
> + }
> + { "entry"
> + { "selector" { "facility" = "uucp" } { "facility" = "news" } {
> "level" = "crit" } }
> + { "action" { "file" = "/var/log/spooler" } }
> + }
> + { "entry"
> + { "selector" { "facility" = "*" } { "level" = "emerg" } }
> + { "action" { "user" = "*" } }
> + }
> + { "entry"
> + { "selector" { "facility" = "daemon" } { "comparison" = "!" } {
> "level" = "info" } }
> + { "action" { "file" = "/var/log/foo" } }
> + }
> + { "entry"
> + { "selector" { "facility" = "daemon" } { "comparison" = "<=" }
> { "level" = "info" } }
> + { "action" { "file" = "/var/log/foo" } }
> + }
> + { "entry"
> + { "selector" { "facility" = "daemon" } { "comparison" = "!<=" }
> { "level" = "info" } }
> + { "action" { "file" = "/var/log/foo" } }
> + }
> + { "entry"
> + { "selector" { "facility" = "*" } { "level" = "*" } }
> + { "action" { "hostname" = "syslog.far.away" } }
> + }
> + { "entry"
> + { "selector" { "facility" = "*" } { "level" = "*" } }
> + { "action" { "hostname" = "syslog.far.away" } { "port" = "123"
> } }
> + }
> + { "entry"
> + { "selector" { "facility" = "*" } { "level" = "*" } }
> + { "action" { "user" = "foo" } { "user" = "bar" } }
> + }
> + { "entry"
> + { "selector" { "facility" = "*" } { "level" = "*" } }
> + { "action" { "program" = "\"/usr/bin/soft arg\"" } }
> + }
> + { "program"
> + { "program" = "startslip" }
> + { "#comment" = "get that out" }
> + { "entry"
> + { "selector" { "facility" = "*" } { "level" = "*" } }
> + { "action" { "file" = "/var/log/slip.log" } }
> + }
> + }
> + { "program"
> + { "program" = "pppd" }
> + { "program" = "ppp" }
> + { }
> + { "entry"
> + { "selector" { "facility" = "*" } { "level" = "*" } }
> + { "action" { "file" = "/var/log/ppp.log" } }
> + }
> + }
> + { "program"
> + { "program" = "startslip" }
> + { "entry"
> + { "selector" { "facility" = "*" } { "level" = "*" } }
> + { "action" { "file" = "/var/log/slip.log" } }
> + }
> + }
> + { "program"
> + { "reverse" }
> + { "program" = "startslip" }
> + { "entry"
> + { "selector" { "facility" = "*" } { "level" = "*" } }
> + { "action" { "file" = "/var/log/slip.log" } }
> + }
> + }
> + { "program"
> + { "program" = "pppd" }
> + { "entry"
> + { "selector" { "facility" = "*" } { "level" = "*" } }
> + { "action" { "file" = "/var/log/ppp.log" } }
> + }
> + }
> + { "hostname"
> + { "hostname" = "foo.example.com" }
> + { "entry"
> + { "selector" { "facility" = "daemon" } { "level" = "info" } }
> + { "action" { "file" = "/var/log/cvsupd.log" } }
> + }
> + }
> + { "hostname"
> + { "hostname" = "foo.example.com" }
> + { "hostname" = "bar.example.com" }
> + { "entry"
> + { "selector" { "facility" = "daemon" } { "level" = "info" } }
> + { "action" { "file" = "/var/log/cvsupd.log" } }
> + }
> + }
> + { "hostname"
> + { "hostname" = "bar.example.com" }
> + { "entry"
> + { "selector" { "facility" = "daemon" } { "level" = "info" } }
> + { "action" { "file" = "/var/log/cvsupd.log" } }
> + }
> + }
> + { "hostname"
> + { "reverse" }
> + { "hostname" = "foo.example.com" }
> + { "entry"
> + { "selector" { "facility" = "daemon" } { "level" = "info" } }
> + { "action" { "file" = "/var/log/cvsupd.log" } }
> + }
> + }
> + { "hostname"
> + { "hostname" = "*" }
> + { "entry"
> + { "selector" { "facility" = "daemon" } { "level" = "info" } }
> + { "action" { "file" = "/var/log/cvsupd.log" } }
> + }
> + }
> + { "program"
> + { "program" = "*" }
> + { "entry"
> + { "selector" { "facility" = "daemon" } { "level" = "info" } }
> + { "action" { "file" = "/var/log/cvsupd.log" } }
> + }
> + }
> +
> + (* changing file *)
> + test Syslog.lns put "*.* /var\n" after
> + set "/entry[1]/action/file" "/foo"
> + = "*.* /foo\n"
> +
> + (* removing entry *)
> + test Syslog.lns put "*.* /var\n" after
> + rm "/entry[1]"
> + = ""
> +
> + (* changing facility and level *)
> + test Syslog.lns put "*.* /var\n" after
> + set "/entry[1]/selector/facility" "daemon" ;
> + set "/entry[1]/selector/level" "info"
> + = "daemon.info /var\n"
> +
> + (* insert a facility *)
> + test Syslog.lns put "daemon.* /var\n" after
> + insa "facility" "/entry/selector/facility" ;
> + set "/entry/selector/facility[2]" "mail"
> + = "daemon,mail.* /var\n"
> +
> + (* creating an entry *)
> + test Syslog.lns put "" after
> + set "/entry/selector/facility" "daemon" ;
> + set "/entry/selector/level" "info" ;
> + set "/entry/action/file" "/var"
> + = "daemon.info\t/var\n"
> +
> + (* inserting an entry before *)
> + test Syslog.lns put "*.* /var\n" after
> + insb "entry" "/entry" ;
> + set "/entry[1]/selector/facility" "daemon" ;
> + set "/entry[1]/selector/level" "info" ;
> + set "/entry[1]/action/file" "/foo"
> + = "daemon.info /foo\n*.*\t/var\n"
> +
> + (* inserting an entry after *)
> + test Syslog.lns put "*.* /var\n" after
> + insa "entry" "/entry" ;
> + set "/entry[2]/selector/facility" "daemon" ;
> + set "/entry[2]/selector/level" "info" ;
> + set "/entry[2]/action/file" "/foo"
> + = "*.* /var\ndaemon.info\t/foo\n"
> +
> + (* insert sync on a file *)
> + test Syslog.lns put "*.* /var\n" after
> + insb "no_sync" "/entry/action/file"
> + = "*.* -/var\n"
> +
> + (* changing file to remote host *)
> + test Syslog.lns put "*.* /var\n" after
> + rm "/entry/action/file" ;
> + set "/entry/action/hostname" "far.far.away"
> + = "*.* @far.far.away\n"
> +
> + (* changing file to * *)
> + test Syslog.lns put "*.* /var\n" after
> + rm "/entry/action/file" ;
> + set "/entry/action/user" "*"
> + = "*.* *\n"
> +
> + (* changing file to users *)
> + test Syslog.lns put "*.* /var\n" after
> + rm "/entry/action/file" ;
> + set "/entry/action/user[1]" "john" ;
> + set "/entry/action/user[2]" "paul" ;
> + set "/entry/action/user[3]" "george" ;
> + set "/entry/action/user[4]" "ringo"
> + = "*.* john,paul,george,ringo\n"
> +
> + (* changing file to program *)
> + test Syslog.lns put "*.* /var\n" after
> + rm "/entry/action/file" ;
> + set "/entry/action/program" "/usr/bin/foo"
> + = "*.* |/usr/bin/foo\n"
> +
> + (* inserting a matching program *)
> + test Syslog.lns put "" after
> + insa "program" "/" ;
> + set "/program/program" "foo"
> + = "!foo\n"
> +
> + (* inserting an entry to a matching program *)
> + test Syslog.lns put "!foo\n" after
> + set "/program/entry/selector/facility" "*" ;
> + set "/program/entry/selector/level" "*" ;
> + set "/program/entry/action/file" "/foo"
> + = "!foo\n*.*\t/foo\n"
> +
> + (* inserting a matching hostname *)
> + test Syslog.lns put "" after
> + insa "hostname" "/" ;
> + set "/hostname/hostname" "foo.foo.away"
> + = "+foo.foo.away\n"
> +
> + (* inserting an entry to a matching hostname *)
> + test Syslog.lns put "+foo.foo.away\n" after
> + set "/hostname/entry/selector/facility" "*" ;
> + set "/hostname/entry/selector/level" "*" ;
> + set "/hostname/entry/action/file" "/foo"
> + = "+foo.foo.away\n*.*\t/foo\n"
> +
> + (* inserting a reverse matching hostname *)
> + test Syslog.lns put "" after
> + insa "hostname" "/" ;
> + set "/hostname/reverse" "" ;
> + set "/hostname/hostname" "foo.foo.away"
> + = "-foo.foo.away\n"
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index 11e5319..ef3c604 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -80,6 +80,7 @@ lens_tests = \
> lens-sshd.sh \
> lens-sysconfig.sh \
> lens-sysctl.sh \
> + lens-syslog.sh \
> lens-vsftpd.sh \
> lens-webmin.sh \
> lens-wine.sh \
> --
> 1.7.3.2
>
> _______________________________________________
> augeas-devel mailing list
> augeas-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/augeas-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/augeas-devel/attachments/20101103/a8254e6c/attachment.htm>
More information about the augeas-devel
mailing list