diff options
author | David Lutterkort <lutter@redhat.com> | 2009-05-30 22:43:55 -0700 |
---|---|---|
committer | James Turnbull <james@lovedthanlost.net> | 2009-06-03 23:34:51 +1000 |
commit | 7c5125bb6dec630d2509905e3c202e0dfe59d959 (patch) | |
tree | f297ee552f018e3514b53def3e2e2ba66cc5a9c6 /lib/puppet/provider/augeas | |
parent | 6ce81546ccfab2aefbec7fced5c38226bdd83297 (diff) | |
download | puppet-7c5125bb6dec630d2509905e3c202e0dfe59d959.tar.gz puppet-7c5125bb6dec630d2509905e3c202e0dfe59d959.tar.xz puppet-7c5125bb6dec630d2509905e3c202e0dfe59d959.zip |
Brought in lutters parse_commands patch and integrated it into the type.
This includes reworking the get and match commands as well. This change
introduces a few small changes. These are:
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"
Cherry-pick of 9a2642 from 0.24.x
Conflicts:
lib/puppet/provider/augeas/augeas.rb
Diffstat (limited to 'lib/puppet/provider/augeas')
-rw-r--r-- | lib/puppet/provider/augeas/augeas.rb | 165 |
1 files changed, 108 insertions, 57 deletions
diff --git a/lib/puppet/provider/augeas/augeas.rb b/lib/puppet/provider/augeas/augeas.rb index 841bdc6c1..35ab50652 100644 --- a/lib/puppet/provider/augeas/augeas.rb +++ b/lib/puppet/provider/augeas/augeas.rb @@ -18,6 +18,7 @@ # Author: Bryan Kearney <bkearney@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,32 +188,43 @@ 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) || '' # Now do the work 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 + when "size": + 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(" ") + when "include": + 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"; return_value = process_get(cmd_array) when "match"; 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 |