[augeas-devel] [Interfaces] Draft lense
Free Ekanayaka
free at 64studio.com
Wed Aug 20 17:03:13 UTC 2008
Hi Raphaël,
|--==> Raphaël Pinson writes:
[...]
RP> I think he has a bzr branch on Launchpad with his work. Haven't seen a
RP> single line myself so far though.
I see.
RP> Sorry, my mistake. Util.del_ws_spc is for the spaces only, while you can put
RP> Util.indent in the beginning of each entry. del_ws_spc deletes /[ \t]+/
RP> while indent deletes /[ \t]*/.
RP> In any case, you will probably end up using the \ trick instead for spc, and
RP> indent in front of each entry.
RP> sshd.aug has a similar issue with "AcceptEnv" entries. David got around this
RP> by using seq inside the entry instead of outside.
RP> let array_entry (k:string) =
RP> let value = store /[^ \t\n]+/ in
RP> [ key k . [ sep . seq k . value]* . eol ]
RP> let accept_env = array_entry "AcceptEnv"
RP> which maps AcceptEnv like this
RP> let accept_env = "Protocol 2\nAcceptEnv LC_PAPER LC_NAME LC_ADDRESS
RP> LC_TELEPHONE LC_MEASUREMENT \nAcceptEnv LC_IDENTIFICATION LC_ALL\n"
RP> test Sshd.lns get accept_env =
RP> { "Protocol" = "2" }
RP> { "AcceptEnv"
RP> { "1" = "LC_PAPER" }
RP> { "2" = "LC_NAME" }
RP> { "3" = "LC_ADDRESS" }
RP> { "4" = "LC_TELEPHONE" }
RP> { "5" = "LC_MEASUREMENT" } }
RP> { "AcceptEnv"
RP> { "6" = "LC_IDENTIFICATION" }
RP> { "7" = "LC_ALL" } }
RP> This way, it doesn't affect the rest of the file, but still fixes the
RP> mapping issue that you're facing.
Yeah, I thought something like that too, but if you have a
configuration like:
auto lo eth0
auto eth1
it would generate a tree like:
{ "auto"
{ "1" = "lo" }
{ "2" = "eth0" } }
{ "auto"
{ "1" = "eth1" } }
which is closer to the actual configuration file, but probably less
parsable than:
{ "auto" = "lo" }
{ "auto" = "eth0" }
{ "auto" = "eth1" }
RP> I faced this issue in inifile.aug and bbhosts.aug (and more). You could get
RP> around it with something like
RP> let iface = type "iface" . entry "family" . entry "method" . eol
RP> . (option|comment|empty)*
RP> let mapping = type "mapping" . eol
RP> . (option|comment|empty)*
RP> let stanza = iface
RP> | auto
RP> | allow_auto
RP> | allow_hotplug
RP> | mapping
RP> let lns = (comment|empty)* . stanza*
Smart idea, even the placement of the comments in the tree can result
a little bit odd sometimes. I've modified the lens accordingly and it
works (below you find the new version of the files). The only problem
is that I came across a weird bug which I believe is related with
Util.comment.
Basically I have to define my option lens like this:
let option = [ del /[ \t]*/ " " . key ( /[abcdefghijklmopqrstuvwxyz-]+/ - words ) . spc . value_to_eol . eol ]
instead of:
let option = [ del /[ \t]*/ " " . key ( /[a-z-]+/ - words ) . spc . value_to_eol . eol ]
Note that the former declaration is exactly the same as the latter,
but it excludes the letter "n", which of course makes the lens fail
with all options starting with a word containing "n". However the lens
works beautifully in all other cases.
If I don't exclude the "n" character and declare the option lens with
the regular [a-z-], I get this error:
lenses/interfaces.aug:27.3-.111:Failed to compile iface
lenses/interfaces.aug:27.82-.99:exception: overlapping lenses in tree union.put
Example matched by both: 'comment/'
First lens: lenses/interfaces.aug:24.16-.95
Second lens: lenses/util.aug:21.4-22.55
lenses/interfaces.aug:28.3-.77:Failed to compile mapping
lenses/interfaces.aug:28.52-.67:exception: overlapping lenses in tree union.put
Example matched by both: 'comment/'
First lens: lenses/interfaces.aug:24.16-.95
Second lens: lenses/util.aug:21.4-22.55
As far as I can tell this happens only with "n", Weird enough, isn't
it? :) It makes me think to something related with \n
RP> Oh yes, forgot to tell you that you need Util.empty when yo use
RP> Util.comment, since once comments are mapped, you still need to remove empty
RP> lines.
Yes, I had figured out it :)
Ciao!
Free
============= interfaces.aug ==================
(* Intefraces module for Augeas *)
(* Author: Free Ekanayaka <free at 64studio.com> *)
module Interfaces =
autoload xfm
(* Define useful primitives *)
let eol = Util.eol
let value_to_eol = store /([^\\ \t\n].*[^\\ \t\n]|[^\\ \t\n])/
let value_to_spc = store /[^\\ \t\n]+/
let spc = del /([ \t]+|[ \t]*\\\n[ \t]*)/ " "
(* Define comment *)
let comment = Util.comment
let empty = Util.empty
(* Define a generic entry *)
let entry (l:string) = [ spc . label l . value_to_spc ]
(* Define stanzas *)
let type (r:regexp) (t:string) = del r t . label t . spc . value_to_spc
let words = /(iface|auto|allow-[a-z-]+|mapping)/
let option = [ del /[ \t]*/ " " . key ( /[abcdefghijklmopqrstuvwxyz-]+/ - words ) . spc . value_to_eol . eol ]
let auto = [ type /(allow-)?auto/ "auto" . eol . (comment|empty)* ]
let iface = [ type /iface/ "iface" . entry "family" . entry "method" . eol . (option | comment | empty)* ]
let mapping = [ type /mapping/ "mapping" . eol . (option|comment|empty)* ]
let hotplug = [ type /allow-hotplug/ "allow-hotplug" . eol . (comment|empty)* ]
(* Define stanza *)
let stanza = (iface | auto | mapping | hotplug)
(* Define lens *)
let lns = ( comment | empty )* . stanza*
let filter = incl "/etc/network/interfaces"
. Util.stdexcl
let xfm = transform lns filter
============= test_interfaces.aug ==================
module Test_interfaces =
let conf ="# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
# The loopback network interface
auto lo
allow-hotplug eth1
iface lo inet loopback
mapping eth0
script /usr/local/sbin/map-scheme
map HOME eth0-home
map WORK eth0-work
iface eth0-home inet static
address 192.168.1.1
# netmask 255.255.255.0
up flush-mail
iface eth0-work inet dhcp
allow-auto eth1
iface eth1 inet dhcp
"
test Interfaces.lns get conf =
{ "comment" = "This file describes the network interfaces available on your system"}
{ "comment" = "and how to activate them. For more information, see interfaces(5)." }
{ "comment" = "The loopback network interface" }
{}
{ "auto" = "lo" }
{ "allow-hotplug" = "eth1"
{} }
{ "iface" = "lo"
{ "family" = "inet"}
{ "method" = "loopback"} {} }
{ "mapping" = "eth0"
{ "script" = "/usr/local/sbin/map-scheme"}
{ "map" = "HOME eth0-home"}
{ "map" = "WORK eth0-work"}
{} }
{ "iface" = "eth0-home"
{ "family" = "inet"}
{ "method" = "static"}
{ "address" = "192.168.1.1" }
{ "comment" = "netmask 255.255.255.0" }
{ "up" = "flush-mail" }
{} }
{ "iface" = "eth0-work"
{ "family" = "inet"}
{ "method" = "dhcp"}
{} }
{ "auto" = "eth1" }
{ "iface" = "eth1"
{ "family" = "inet"}
{ "method" = "dhcp"} }
More information about the augeas-devel
mailing list