[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [augeas-devel] Default label for a node in a path expression



Hi David,


On Mon, Jan 6, 2014 at 11:04 PM, David Lutterkort <lutter watzmann net> wrote:
There's regularly people asking how to write idempotent set expressions. With labeled nodes, we have the usual trick:

    set foo[.='bar'] 'bar'

which creates the 'foo' node with the 'bar' value if it doesn't exist.

Yes, I agree with both - that it's not wel supported right now, and that it is needed. The underlying problem is that there's no good way to infer from a path _expression_ where the newly created node  should go in case the path _expression_ doesn't match.

Rather than put something in the XPath language, I think it would be cleaner to do this explicitly in a dedicated command. I can think of a few ways to do that. The simplest would be a aug_set_or_create(expr, path, value) that goes something like this:

if aug_match(expr) == 1
  aug_set(expr, value)
elsif aug_match(expr) == 0
  aug_set(path, value)
else
  complain
end

Here, EXPR is an XPath _expression_, and PATH is a literal path that has enough information to create nodes from unambiguously. Maybe we'd need to also allow a BASE (XPath _expression_) so that not all of PATH needs to be fixed, and both EXPR and PATH would be relative to that.


That looks good and simple enough. However, it means we'll have to create a new call for all the calls for this kind: set, setm, clear, clearm, defnode, maybe even a way to make insert more idempotent with these paths.

 
But thinking of a scenario where you want to create an entry in /etc/hosts if it's not there, that might still not be enough, and we might ultimately need to introduce an 'if' statement into the language that aug_srun accepts - though that has all kinds of ripple effects as you now also need to define expressions for that if statement ...


Right. One option that was mentioned on IRC yesterday would be to use an embedded language to add this logic, to avoid implementing yet another interpreter. Lua obviously comes to mind. We could then have an aug_lua call, which would supersede aug_srun and take Lua commands as input. Lua would then call the C methods to control Augeas. aug_lua would automatically get a pre-set Augeas handler with the options passed to the C lib.

Eventually, augtool could have a --lua|-l option which would make it use aug_lua instead of aug_srun as the interpreter:

    #!/usr/bin/augtool -lsf
    if augeas.match('/files/path/to/some/node') == 0
      augeas.set('/some/path', 'value')
    elsif …
       augeas.insert('label', 'path', 'before')
    end
     
 

So I've thought maybe we could add to the XPath language:

    set /path/to/*[default() = "foo"][. = "bar"] "bar"

If no node matching /path/to/* is found, then a new node would be created using label "foo". This would allow for multiple level defaults, such as:

    set /path/to/*[default() = "foo"][. = "bar"]/*[default = "foz"][. = "baz"] "baz"

and defaults would be applied at each level. I don't know about the feasability of this, but it would bring the most flexibility and it would allow to easily write idempotent set commands for seq nodes, too:

    set /path/to/*[default() = "01"][. = "bar"] "bar"

I think that's an elegant approach, though I am not sure how understandable this would be to users. At the very least, I'd use a different syntax than the '[ ... ]' predicates (right now '=' means comparison, not assignment), something like

set /path/to/*<01>[. = "bar"]

That will lead to headaches in parse_name in pathx.c, since we will then disallow '{' in file names. Maybe

set /path/to/*[<01> . = "bar"]

would reduce the need to restrict what characters we like in file names ...


I'm not sure if this would be very natural to write though.



--
Raphaël Pinson
Infrastructure Developer & Trainer
+33 479 26 57 93
+33 781 90 00 79

Camptocamp France
Savoie Technolac
BP 352
48, avenue du Lac du Bourget
73372 Le Bourget du Lac, Cedex
www.camptocamp.com

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]