[augeas-devel] How to write lens so that it can parse empty file.

Nathaniel Cook nvcook42 at gmail.com
Thu May 31 16:27:00 UTC 2012


Raphaël,

Thanks that helps a lot. I am very new at this so I appreciate the
suggestions. Makes sense now that you explain that an empty file is
"\n". As for the file you can only have one gridname entry, so to keep
it simple I was going to force it to be first in the file or not at
all. I tried this but

let len = (gridname | Util.empty)? . (data_source | Util.empty)*

but I get an ambiguos concatenation error,  which makes sense but I
don' t know how to get around it. How can I enforce only one gridname
entry?

Nathaniel Cook

On Thu, May 31, 2012 at 9:13 AM, Raphaël Pinson
<raphael.pinson at camptocamp.com> wrote:
> You could also make a larger use of common modules (Util, Rx, Sep, Build) to
> simply the lens. Here is my take for the lens:
>
>
>
> module Gmetad =
>
> autoload xfm
>
> let quoted =
>      let quote = Util.del_str "\""
>   in quote . store Rx.word. quote
>
> let data_source =
>      let host = [ label "host" . store Rx.word ]
>   in Build.key_value_line "data_source" Sep.space
>       (quoted . Sep.space
>       . Build.opt_list host Sep.space)
>
>
> let gridname = Build.key_value_line "gridname" Sep.space quoted
>
> let lns  = (gridname | data_source | Util.empty)*
>
> let filter = incl "/etc/gmetad.conf"
> let xfm = transform lns filter
>
>
>
>
> and for the test file:
>
>
> module Test_gmetad =
>    let conf = "gridname \"grid\"
> data_source \"group_name\" ds1 ds2 ds3.example.com
> data_source \"group_other\" www1 www2 www3.example.com
> "
>    test Gmetad.lns get  conf =
>    { "gridname" = "grid" }
>    { "data_source" = "group_name"
>      { "host" = "ds1" }
>      { "host" = "ds2" }
>      { "host" = "ds3.example.com" } }
>    { "data_source" = "group_other"
>      { "host" = "www1" }
>      { "host" = "www2" }
>      { "host" = "www3.example.com" } }
>
>
>
> Raphaël
>
>
>
>
> On Thu, May 31, 2012 at 4:57 PM, Raphaël Pinson
> <raphael.pinson at camptocamp.com> wrote:
>>
>>
>> On Thu, May 31, 2012 at 4:38 PM, Nathaniel Cook <nvcook42 at gmail.com>
>> wrote:
>>>
>>> I have been working on writing a simplified lens for the ganglia
>>> gmetad.conf file. I have the lens working as I like but when I try to
>>> use augeas to add entries to the file I get errors on save if the file
>>> doesn't exist or is empty. It says it cannot parse the entire input:
>>>
>>> /augeas/files/etc/gmetad.conf/error = "parse_failed"
>>> /augeas/files/etc/gmetad.conf/error/pos = "0"
>>> /augeas/files/etc/gmetad.conf/error/line = "1"
>>> /augeas/files/etc/gmetad.conf/error/char = "0"
>>> /augeas/files/etc/gmetad.conf/error/lens =
>>> "/usr/share/augeas/lenses/gmetad.aug:22.12-.56:"
>>> /augeas/files/etc/gmetad.conf/error/message = "Get did not match entire
>>> input"
>>>
>>>
>>> Here is the lens:
>>>
>>>
>>> module Gmetad =
>>>    autoload xfm
>>>
>>>    let quote = Util.del_str "\""
>>>    let space = del /[ \t]+/ " "
>>>    let eol = Util.del_str "\n"
>>>    let empty =  del /[ \t]*/ "" . eol
>>>
>>>    let host = store /[a-zA-Z0-9._]+/
>>>    let hosts = ( space . [ seq "hosts" . host ] )+
>>>    let group = [ label "group" . quote . store /[a-zA-Z0-9._ ]+/ . quote
>>> ]
>>>    let data_source = [ counter "hosts" .  label "data_source" .
>>> Util.del_str "data_source" . space . group . [ label "hosts" . hosts ]
>>> ]
>>>
>>>    let gridname = [ label "gridname" . Util.del_str "gridname" .
>>> space . quote . store /[a-zA-Z0-9._]+/ . quote ]
>>>
>>>    let lns  = (gridname . empty)* . (data_source . empty)*
>>>
>>>    let filter = incl "/etc/gmetad.conf"
>>>    let xfm = transform lns filter
>>>
>>>
>>> Here is the test module:
>>>
>>> module Test_gmetad =
>>>    let conf = "gridname \"grid\"
>>> data_source \"group_name\" ds1 ds2 ds3.example.com
>>> data_source \"group_other\" www1 www2 www3.example.com
>>> "
>>>    test Gmetad.lns get  conf =
>>>    { "gridname" = "grid" }
>>>    { "data_source"
>>>            { "group" = "group_name" }
>>>            { "hosts"
>>>                { "1" = "ds1" }
>>>                { "2" = "ds2" }
>>>                { "3" = "ds3.example.com" }
>>>            }
>>>    }
>>>    { "data_source"
>>>        { "group" = "group_other" }
>>>        { "hosts"
>>>            { "1" = "www1" }
>>>            { "2" = "www2" }
>>>            { "3" = "www3.example.com" }
>>>        }
>>>    }
>>>
>>>    let empty = ""
>>>
>>>    test Gmetad.lns get empty = ?
>>>
>>
>>
>> An empty (or non existent) file is not an empty string, but a single
>> carriage return. The test should thus be:
>>
>> test Gmetad.lns get "\n" = ?
>>
>> which fails since the lens cannot parse a single carriage return. This is
>> the reason why it fails in augtool.
>>
>>
>> Doesn't this format not support empty lines? If it does, I'd advise to use
>> Util.eol in gridname and data_source, and write lns as:
>>
>> let lns = (gridname | data_source | Util.empty)*
>>
>> or does the order strictly matter?
>>
>>
>> Raphaël
>>
>




More information about the augeas-devel mailing list