Avi Miller wrote:
> 
> 
> David Lutterkort wrote:
>> Somebody (not necesarily you, and I'd do it if I had time for it) needs
>> to take the parse_commands method in there and replace the one in the
>> current Augeas provider with it;
> 
> I suspect the someone should have some experience with Ruby, unlike 
> myself. :) I shall wait patiently for someone (else) to do it.
> 

I took David's patch (Thanks David!) and integrated it into the type. 
You can either build puppet from source by cloning off of my repo:

http://github.com/bkearney/puppet/tree/ticket/0.24.x/2441


Or you can apply this patch. You should be able to apply it from the 
site_ruby directory. There are a couple of subtle changes to the type 
based on this patch. I believe them to be for the better, but they may 
bite you:

1) There can be no ' or " characters around path elements.
2) The context is now only prepended to relative paths. So, if a
path is specified as /foo/bar the context will not be appended. It
will only be appended if it is foo/bar
3) The syntax for array matching in the onlyif is now eq or noteq.
It was == before.
4) The get and set commnands used to concatenate all items at the end
of a string so "set path to some value" would be interpreted as
"set" "path" "to some value". This is no longer supported. The caller
must put ' or " around the "to some value" for it to work"

Let me know if you have any issues.

-- bk

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Puppet Users" group.
To post to this group, send email to puppet-users@googlegroups.com
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en
-~----------~----~----~----~------~----~------~--~---

diff --git a/puppet/provider/augeas/augeas.rb b/lib/puppet/provider/augeas/augeas.rb
index 56e217a..618b672 100644
--- a/puppet/provider/augeas/augeas.rb
+++ b/puppet/provider/augeas/augeas.rb
@@ -18,6 +18,7 @@
 # Author: Bryan Kearney <bkear...@redhat.com>
 
 require 'augeas' if Puppet.features.augeas?
+require 'strscan'
 
 Puppet::Type.type(:augeas).provide(:augeas) do
     include Puppet::Util
@@ -29,6 +30,22 @@ Puppet::Type.type(:augeas).provide(:augeas) do
     SAVE_NOOP = "noop"
     SAVE_OVERWRITE = "overwrite"
 
+    COMMANDS = {
+      "set" => [ :path, :string ],
+      "rm" => [ :path ],
+      "clear" => [ :path ],
+      "insert" => [ :string, :string, :path ],
+      "get" => [ :path, :comparator, :string ],
+      "match" => [ :path, :glob ],
+      "size" => [:comparator, :int],
+      "include" => [:string],
+      "eq" => [:glob],
+      "noteq" => [:glob]
+    }
+
+    COMMANDS["ins"] = COMMANDS["insert"]
+    COMMANDS["remove"] = COMMANDS["rm"]    
+
     attr_accessor :aug
 
     # Extracts an 2 dimensional array of commands which are in the
@@ -38,42 +55,76 @@ Puppet::Type.type(:augeas).provide(:augeas) do
     # - A string with many commands per line
     # - An array of strings.
     def parse_commands(data)
-        commands = Array.new()
+        context = resource[:context]
+        # Add a trailing / if it is not there
+        if (context.length > 0)
+            context << "/" if context[-1, 1] != "/"
+        end
+
         if data.is_a?(String)
-            data.each_line do |line|
-                cmd_array = Array.new()
-                single = line.index("'")
-                double = line.index('"')
-                tokens = nil
-                delim = " "
-                if ((single != nil) or (double != nil))
-                    single = 99999 if single == nil
-                    double = 99999 if double == nil
-                    delim = '"' if double < single
-                    delim = "'" if single < double
-                end
-                tokens = line.split(delim)
-                # If the length of tokens is 2, thn that means the pattern was
-                # command file "some text", therefore we need to re-split
-                # the first line
-                if tokens.length == 2
-                    tokens = (tokens[0].split(" ")) << tokens[1]
+            s = data
+            data = []
+            s.each_line { |line| data << line }
+        end
+        args = []
+        data.each do |line|
+            argline = []
+            sc = StringScanner.new(line)
+            cmd = sc.scan(/\w+/)
+            formals = COMMANDS[cmd]
+            fail("Unknown command #{cmd}") unless formals
+            argline << cmd
+            narg = 0
+            formals.each do |f|
+                sc.skip(/\s+/)
+                narg += 1
+                if f == :path
+                    start = sc.pos
+                    nbracket = 0
+                    begin
+                        sc.skip(/[^\]\[\s]+/)
+                        ch = sc.getch
+                        nbracket += 1 if ch == "["
+                        nbracket -= 1 if ch == "]"
+                        fail("unmatched [") if nbracket < 0
+                    end until nbracket == 0 && (sc.eos? || ch =~ /\s/)
+                        len = sc.pos - start
+                        len -= 1 unless sc.eos?
+                    unless p = sc.string[start, len]
+                        fail("missing path argument #{narg} for #{cmd}")
+                    end
+                    if p[0,1] != "$" && p[0,1] != "/"
+                        argline << context + p
+                    else
+                        argline << p
+                    end
+                elsif f == :string
+                    delim = sc.peek(1)
+                    if delim == "'" || delim == "\""
+                        sc.getch
+                        argline << sc.scan(/([^\\#{delim}]|(\\.))*/)
+                        sc.getch
+                    else
+                        argline << sc.scan(/[^\s]+/)
+                    end
+                    unless argline[-1]
+                        fail(raise Exception, "missing string argument #{narg} for #{cmd}")
+                    end
+                elsif f == :comparator
+                    argline << sc.scan(/(==|!=|=~|<|<=|>|>=)/)
+                    unless argline[-1]
+                        puts sc.rest() 
+                        fail(raise Exception, "invalid comparator for command #{cmd}")
+                    end
+                elsif f == :int
+                    argline << sc.scan(/\d+/).to_i
+                elsif f== :glob
+                    argline << sc.rest()
                 end
-                cmd = tokens.shift().strip()
-                delim = "" if delim == " "
-                file = tokens.shift().strip()
-                other = tokens.join(" ").strip()
-                cmd_array << cmd if !cmd.nil?
-                cmd_array << file if !file.nil?
-                cmd_array << other if other != ""
-                commands << cmd_array
-            end
-        elsif data.is_a?(Array)
-            data.each do |datum|
-                commands.concat(parse_commands(datum))
             end
+            args << argline
         end
-        return commands
+        return args
     end
 
 
@@ -137,10 +188,13 @@ Puppet::Type.type(:augeas).provide(:augeas) do
         return_value = false
 
         #validate and tear apart the command
-        fail("Invalid command: #{cmd_array.join(" ")}") if cmd_array.length < 4
+        fail("Invalid command: #{cmd_array.join(" ")}") if cmd_array.length < 3
         cmd = cmd_array.shift()
         path = cmd_array.shift()
-        verb = cmd_array.shift()
+
+        # Need to break apart the clause
+        clause_array = parse_commands(cmd_array.shift())[0]
+        verb = clause_array.shift()
 
         #Get the values from augeas
         result = @aug.match(path) || ''
@@ -148,21 +202,29 @@ Puppet::Type.type(:augeas).provide(:augeas) do
         unless (result.nil?)
             case verb
                 when "size":
-                    fail("Invalid command: #{cmd_array.join(" ")}") if cmd_array.length != 2
-                    comparator = cmd_array.shift()
-                    arg = cmd_array.shift().to_i
+                    fail("Invalid command: #{cmd_array.join(" ")}") if clause_array.length != 2
+                    comparator = clause_array.shift()
+                    arg = clause_array.shift()
                     return_value = true if (result.size.send(comparator, arg))
                 when "include":
-                    arg = cmd_array.join(" ")
+                    arg = clause_array.shift()
                     return_value = true if result.include?(arg)
-                when "==":
+                when "eq":
                     begin
-                        arg = cmd_array.join(" ")
+                        arg = clause_array.shift()
                         new_array = eval arg
                         return_value = true if result == new_array
                     rescue
                         fail("Invalid array in command: #{cmd_array.join(" ")}")
                     end
+                when "noteq":
+                    begin
+                        arg = clause_array.shift()
+                        new_array = eval arg
+                        return_value = true if result != new_array
+                    rescue
+                        fail("Invalid array in command: #{cmd_array.join(" ")}")
+                    end                    
             end
         end
         return_value
@@ -188,11 +250,9 @@ Puppet::Type.type(:augeas).provide(:augeas) do
         self.open_augeas()
         filter = resource[:onlyif]
         unless (filter == "")
-            cmd_array = filter.split
+            cmd_array = parse_commands(filter)[0]
             command = cmd_array[0];
-            cmd_array[1]= File.join(resource[:context], cmd_array[1])
             begin
-                data = nil
                 case command
                     when "get" then return_value = process_get(cmd_array)
                     when "match" then return_value = process_match(cmd_array)
@@ -244,35 +304,26 @@ Puppet::Type.type(:augeas).provide(:augeas) do
 
     # Actually execute the augeas changes.
     def do_execute_changes
-        commands = resource[:changes].clone()
-        context = resource[:context]
+        commands = parse_commands(resource[:changes])
         commands.each do |cmd_array|
-            cmd_array = cmd_array.clone()
             fail("invalid command #{cmd_array.join[" "]}") if cmd_array.length < 2
             command = cmd_array[0]
             cmd_array.shift()
             begin
                 case command
                     when "set":
-                        cmd_array[0]=File.join(context, cmd_array[0])
                         debug("sending command '#{command}' with params #{cmd_array.inspect}")
                         @aug.set(cmd_array[0], cmd_array[1])
                     when "rm", "remove":
-                        cmd_array[0]=File.join(context, cmd_array[0])
                         debug("sending command '#{command}' with params #{cmd_array.inspect}")
                         @aug.rm(cmd_array[0])
                     when "clear":
-                        cmd_array[0]=File.join(context, cmd_array[0])
                         debug("sending command '#{command}' with params #{cmd_array.inspect}")
                         @aug.clear(cmd_array[0])
                     when "insert", "ins"
-                        ext_array = cmd_array[1].split(" ") ;
-                        if cmd_array.size < 2 or ext_array.size < 2
-                            fail("ins requires 3 parameters")
-                        end
                         label = cmd_array[0]
-                        where = ext_array[0]
-                        path = File.join(context, ext_array[1])
+                        where = cmd_array[1]
+                        path = cmd_array[2]
                         case where
                             when "before": before = true
                             when "after": before = false
diff --git a/puppet/type/augeas.rb b/puppet/type/augeas.rb
index da9cff3..3022cbf 100644
--- a/puppet/type/augeas.rb
+++ b/puppet/type/augeas.rb
@@ -58,7 +58,9 @@ Puppet::Type.newtype(:augeas) do
     end
 
     newparam (:context) do
-        desc "Optional context path. This value is pre-pended to the paths of all changes"
+        desc "Optional context path. This value is pre-pended to the paths of all changes if the
+              path is relative. So a path specified as /files/foo will not be prepended with the
+              context whild files/foo will be prepended"
         defaultto ""
     end
 
@@ -69,7 +71,8 @@ Puppet::Type.newtype(:augeas) do
                get [AUGEAS_PATH] [COMPARATOR] [STRING]
                match [MATCH_PATH] size [COMPARATOR] [INT]
                match [MATCH_PATH] include [STRING]
-               match [MATCH_PATH] == [AN_ARRAY]
+               match [MATCH_PATH] eq [AN_ARRAY]
+               match [MATCH_PATH] noteq [AN_ARRAY]               
 
              where::
 
@@ -97,10 +100,6 @@ Puppet::Type.newtype(:augeas) do
           insert [LABEL] [WHERE] [PATH]
                                  Synonym for ins
         If the parameter 'context' is set that value is prepended to PATH"
-
-        munge do |value|
-            provider.parse_commands(value)
-        end
     end
 
 

Reply via email to