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