diff --git a/lib/puppet/provider/augeas/augeas.rb b/lib/puppet/provider/augeas/augeas.rb index e9471b1be..56e217a54 100644 --- a/lib/puppet/provider/augeas/augeas.rb +++ b/lib/puppet/provider/augeas/augeas.rb @@ -1,277 +1,291 @@ #-- # Copyright (C) 2008 Red Hat Inc. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Author: Bryan Kearney require 'augeas' if Puppet.features.augeas? Puppet::Type.type(:augeas).provide(:augeas) do include Puppet::Util - - confine :true => Puppet.features.augeas? - + + confine :true => Puppet.features.augeas? + has_features :parse_commands, :need_to_run?,:execute_changes SAVE_NOOP = "noop" SAVE_OVERWRITE = "overwrite" attr_accessor :aug # Extracts an 2 dimensional array of commands which are in the # form of command path value. # The input can be # - A string with one command # - A string with many commands per line # - An array of strings. def parse_commands(data) commands = Array.new() 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] 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 end return commands end def open_augeas if (@aug.nil?) flags = 0 (flags = 1 << 2 ) if self.resource[:type_check] == :true root = self.resource[:root] load_path = self.resource[:load_path] debug("Opening augeas with root #{root}, lens path #{load_path}, flags #{flags}") @aug = Augeas.open(root, load_path,flags) - + if (self.get_augeas_version() >= "0.3.6") debug("Augeas version #{self.get_augeas_version()} is installed") end end @aug end - + + def close_augeas + if (!@aug.nil?) + @aug.close() + debug("Closed the augeas connection") + @aug = nil; + end + end + # Used by the need_to_run? method to process get filters. Returns # true if there is a match, false if otherwise # Assumes a syntax of get /files/path [COMPARATOR] value def process_get(cmd_array) return_value = false #validate and tear apart the command fail ("Invalid command: #{cmd_array.join(" ")}") if cmd_array.length < 4 cmd = cmd_array.shift() path = cmd_array.shift() comparator = cmd_array.shift() arg = cmd_array.join(" ") #check the value in augeas result = @aug.get(path) || '' unless result.nil? case comparator when "!=": return_value = true if !(result == arg) when "=~": regex = Regexp.new(arg) loc = result=~ regex return_value = true if ! loc.nil? else return_value = true if (result.send(comparator, arg)) end end return_value - end - + end + # Used by the need_to_run? method to process match filters. Returns # true if there is a match, false if otherwise def process_match(cmd_array) return_value = false #validate and tear apart the command fail("Invalid command: #{cmd_array.join(" ")}") if cmd_array.length < 4 cmd = cmd_array.shift() path = cmd_array.shift() verb = cmd_array.shift() #Get the values from augeas result = @aug.match(path) || '' # Now do the work - if (!result.nil?) + 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 return_value = true if (result.size.send(comparator, arg)) when "include": arg = cmd_array.join(" ") return_value = true if result.include?(arg) when "==": begin arg = cmd_array.join(" ") 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 end def get_augeas_version return @aug.get("/augeas/version") || "" end def set_augeas_save_mode(mode) return @aug.set("/augeas/save", mode) end def files_changed? saved_files = @aug.match("/augeas/events/saved") - return saved_files.size() > 0 + return saved_files.size() > 0 end - + # Determines if augeas acutally needs to run. def need_to_run? - self.open_augeas() + force = resource[:force] return_value = true + self.open_augeas() filter = resource[:onlyif] unless (filter == "") cmd_array = filter.split 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) end rescue Exception => e fail("Error sending command '#{command}' with params #{cmd_array[1..-1].inspect}/#{e.message}") end end - # If we have a verison of augeas which is at least 0.3.6 then we - # can make the changes now, see if changes were made, and - # actually do the save. - if ((return_value) and (self.get_augeas_version() >= "0.3.6")) - debug("Will attempt to save and only run if files changed") - self.set_augeas_save_mode(SAVE_NOOP) - self.do_execute_changes() - save_result = @aug.save() - saved_files = @aug.match("/augeas/events/saved") - if ((save_result) and (not files_changed?)) - debug("Skipping becuase no files were changed") - return_value = false - else - debug("Files changed, should execute") + unless (force) + # If we have a verison of augeas which is at least 0.3.6 then we + # can make the changes now, see if changes were made, and + # actually do the save. + if ((return_value) and (self.get_augeas_version() >= "0.3.6")) + debug("Will attempt to save and only run if files changed") + self.set_augeas_save_mode(SAVE_NOOP) + self.do_execute_changes() + save_result = @aug.save() + saved_files = @aug.match("/augeas/events/saved") + if ((save_result) and (not files_changed?)) + debug("Skipping becuase no files were changed") + return_value = false + else + debug("Files changed, should execute") + end end end - + self.close_augeas() return return_value - end + end def execute_changes - # if we have version 0.3.6 or greater we have already executed - # the changes. We just need to save them. If not, do the changes + # Re-connect to augeas, and re-execute the changes + self.open_augeas() if (self.get_augeas_version() >= "0.3.6") self.set_augeas_save_mode(SAVE_OVERWRITE) - else - self.do_execute_changes() end - + + self.do_execute_changes() + success = @aug.save() if (success != true) fail("Save failed with return code #{success}") end + self.close_augeas() - return :executed + return :executed end - + # Actually execute the augeas changes. def do_execute_changes - commands = resource[:changes] + commands = resource[:changes].clone() context = resource[:context] 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}") + 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}") + debug("sending command '#{command}' with params #{cmd_array.inspect}") @aug.clear(cmd_array[0]) when "insert", "ins" - if cmd_array.size < 3 + 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 = cmd_array[1] - path = File.join(context, cmd_array[2]) + where = ext_array[0] + path = File.join(context, ext_array[1]) case where when "before": before = true when "after": before = false else fail("Invalid value '#{where}' for where param") end - debug("sending command '#{command}' with params #{[label, where, path].inspect()}") - @aug.insert(path, label, before) + debug("sending command '#{command}' with params #{[label, where, path].inspect()}") + aug.insert(path, label, before) else fail("Command '#{command}' is not supported") end rescue Exception => e fail("Error sending command '#{command}' with params #{cmd_array.inspect}/#{e.message}") end end - end - + end + end diff --git a/lib/puppet/type/augeas.rb b/lib/puppet/type/augeas.rb index c89400b5e..e0d5e10b7 100644 --- a/lib/puppet/type/augeas.rb +++ b/lib/puppet/type/augeas.rb @@ -1,157 +1,164 @@ #-- # Copyright (C) 2008 Red Hat Inc. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Author: Bryan Kearney Puppet::Type.newtype(:augeas) do include Puppet::Util - + feature :parse_commands, "Parse the command string" feature :need_to_run?, "If the command should run" - feature :execute_changes, "Actually make the changes" + feature :execute_changes, "Actually make the changes" @doc = "Apply the changes (single or array of changes) to the filesystem via the augeas tool. Requires: - augeas to be installed (http://www.augeas.net) - ruby-augeas bindings Sample usage with a string:: augeas{\"test1\" : context => \"/files/etc/sysconfig/firstboot\", changes => \"set RUN_FIRSTBOOT YES\", onlyif => \"match other_value size > 0\", } Sample usage with an array and custom lenses:: augeas{\"jboss_conf\": context => \"/files\", changes => [ \"set /etc/jbossas/jbossas.conf/JBOSS_IP $ipaddress\", \"set /etc/jbossas/jbossas.conf/JAVA_HOME /usr\" ], load_path => \"$/usr/share/jbossas/lenses\", } " newparam (:name) do desc "The name of this task. Used for uniqueness" isnamevar end newparam (:context) do desc "Optional context path. This value is pre-pended to the paths of all changes" - defaultto "" + defaultto "" end newparam (:onlyif) do desc "Optional augeas command and comparisons to control the execution of this type. Supported onlyif syntax:: get [AUGEAS_PATH] [COMPARATOR] [STRING] match [MATCH_PATH] size [COMPARATOR] [INT] match [MATCH_PATH] include [STRING] match [MATCH_PATH] == [AN_ARRAY] where:: AUGEAS_PATH is a valid path scoped by the context MATCH_PATH is a valid match synatx scoped by the context COMPARATOR is in the set [> >= != == <= <] STRING is a string INT is a number AN_ARRAY is in the form ['a string', 'another']" defaultto "" end - + newparam(:changes) do desc "The changes which should be applied to the filesystem. This can be either a string which contains a command or an array of commands. Commands supported are:: set [PATH] [VALUE] Sets the value VALUE at loction PATH rm [PATH] Removes the node at location PATH remove [PATH] Synonym for rm clear [PATH] Keeps the node at PATH, but removes the value. ins [LABEL] [WHERE] [PATH] Inserts an empty node LABEL either [WHERE={before|after}] PATH. insert [LABEL] [WHERE] [PATH] Synonym for ins If the parameter 'context' is set that value is prepended to PATH" - munge do |value| + munge do |value| provider.parse_commands(value) end end newparam(:root) do desc "A file system path; all files loaded by Augeas are loaded underneath ROOT" defaultto "/" end newparam(:load_path) do desc "Optional colon separated list of directories; these directories are searched for schema definitions" defaultto "" end + newparam(:force) do + desc "Optional command to force the augeas type to execute even if it thinks changes + will not be made. This does not overide the only setting. If onlyif is set, then the + foce setting will not override that result" + + defaultto false + end newparam(:type_check) do desc "Set to true if augeas should perform typechecking. Optional, defaults to false" newvalues(:true, :false) defaultto :false end - + # This is the acutal meat of the code. It forces # augeas to be run and fails or not based on the augeas return # code. newproperty(:returns) do |property| include Puppet::Util desc "The expected return code from the augeas command. Should not be set" defaultto 0 - + # Make output a bit prettier def change_to_s(currentvalue, newvalue) return "executed successfully" - end - + end + # if the onlyif resource is provided, then the value is parsed. # a return value of 0 will stop exection becuase it matches the # default value. def retrieve if @resource.provider.need_to_run?() :need_to_run else 0 end - end + end # Actually execute the command. def sync @resource.provider.execute_changes() end - end + end end diff --git a/spec/unit/provider/augeas/augeas.rb b/spec/unit/provider/augeas/augeas.rb index e05812d78..284145657 100644 --- a/spec/unit/provider/augeas/augeas.rb +++ b/spec/unit/provider/augeas/augeas.rb @@ -1,335 +1,365 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' provider_class = Puppet::Type.type(:augeas).provider(:augeas) describe provider_class do describe "command parsing" do it "should break apart a single line into three tokens" do provider = provider_class.new() tokens = provider.parse_commands("set /Jar/Jar Binks") tokens.size.should == 1 - tokens[0].size.should == 3 + tokens[0].size.should == 3 tokens[0][0].should == "set" tokens[0][1].should == "/Jar/Jar" - tokens[0][2].should == "Binks" + tokens[0][2].should == "Binks" end - + it "should break apart a multiple line into six tokens" do provider = provider_class.new() tokens = provider.parse_commands("set /Jar/Jar Binks\nrm anakin skywalker") tokens.size.should == 2 - tokens[0].size.should == 3 - tokens[1].size.should == 3 + tokens[0].size.should == 3 + tokens[1].size.should == 3 tokens[0][0].should == "set" tokens[0][1].should == "/Jar/Jar" - tokens[0][2].should == "Binks" + tokens[0][2].should == "Binks" tokens[1][0].should == "rm" tokens[1][1].should == "anakin" - tokens[1][2].should == "skywalker" - end - + tokens[1][2].should == "skywalker" + end + it "should handle arrays" do provider = provider_class.new() commands = ["set /Jar/Jar Binks", "rm anakin skywalker"] tokens = provider.parse_commands(commands) tokens.size.should == 2 - tokens[0].size.should == 3 - tokens[1].size.should == 3 + tokens[0].size.should == 3 + tokens[1].size.should == 3 tokens[0][0].should == "set" tokens[0][1].should == "/Jar/Jar" - tokens[0][2].should == "Binks" + tokens[0][2].should == "Binks" tokens[1][0].should == "rm" tokens[1][1].should == "anakin" - tokens[1][2].should == "skywalker" - end - + tokens[1][2].should == "skywalker" + end + it "should concat the last values" do provider = provider_class.new() tokens = provider.parse_commands("set /Jar/Jar Binks is my copilot") tokens.size.should == 1 - tokens[0].size.should == 3 + tokens[0].size.should == 3 tokens[0][0].should == "set" tokens[0][1].should == "/Jar/Jar" - tokens[0][2].should == "Binks is my copilot" + tokens[0][2].should == "Binks is my copilot" end it "should accept spaces and and single ticks" do provider = provider_class.new() tokens = provider.parse_commands("set 'Jar Jar' Binks") tokens.size.should == 1 tokens[0].size.should == 3 tokens[0][0].should == "set" tokens[0][1].should == "Jar Jar" tokens[0][2].should == "Binks" end - + it "should accept spaces in the value and and single ticks" do provider = provider_class.new() tokens = provider.parse_commands("set 'Jar Jar' 'Binks is my copilot'") tokens.size.should == 1 tokens[0].size.should == 3 tokens[0][0].should == "set" tokens[0][1].should == "Jar Jar" tokens[0][2].should == "Binks is my copilot" end - + it "should accept spaces and and double ticks" do provider = provider_class.new() tokens = provider.parse_commands('set "Jar Jar" Binks') tokens.size.should == 1 tokens[0].size.should == 3 tokens[0][0].should == "set" tokens[0][1].should == 'Jar Jar' tokens[0][2].should == 'Binks' end - + it "should accept spaces in the value and and double ticks" do provider = provider_class.new() tokens = provider.parse_commands('set "Jar Jar" "Binks is my copilot"') tokens.size.should == 1 tokens[0].size.should == 3 tokens[0][0].should == "set" tokens[0][1].should == 'Jar Jar' tokens[0][2].should == 'Binks is my copilot' end - + it "should accept mixed ticks" do provider = provider_class.new() tokens = provider.parse_commands('set "Jar Jar" "Some \'Test\'"') tokens.size.should == 1 tokens[0].size.should == 3 tokens[0][0].should == "set" tokens[0][1].should == 'Jar Jar' tokens[0][2].should == "Some \'Test\'" end - + it "should accept only the last value using ticks" do provider = provider_class.new() tokens = provider.parse_commands('set /Jar/Jar "Binks is my copilot"') tokens.size.should == 1 tokens[0].size.should == 3 tokens[0][0].should == "set" tokens[0][1].should == '/Jar/Jar' tokens[0][2].should == "Binks is my copilot" end - + it "should accept only the first value using ticks" do provider = provider_class.new() tokens = provider.parse_commands('set "Jar Jar" copilot') tokens.size.should == 1 tokens[0].size.should == 3 tokens[0][0].should == "set" tokens[0][1].should == 'Jar Jar' tokens[0][2].should == "copilot" end - + it "should accept only the first value using ticks and the last values being concatenated" do provider = provider_class.new() tokens = provider.parse_commands('set "Jar Jar" Binks is my copilot') tokens.size.should == 1 tokens[0].size.should == 3 tokens[0][0].should == "set" tokens[0][1].should == 'Jar Jar' tokens[0][2].should == "Binks is my copilot" - end + end end - + describe "get filters" do before do augeas_stub = stub("augeas", :get => "value") - @provider = provider_class.new() - @provider.aug= augeas_stub + @provider = provider_class.new() + @provider.aug= augeas_stub end - + it "should return false for a = nonmatch" do command = ["get", "fake value", "==", "value"] @provider.process_get(command).should == true end - + it "should return true for a != match" do command = ["get", "fake value", "!=", "value"] @provider.process_get(command).should == false - end - + end + it "should return true for a =~ match" do command = ["get", "fake value", "=~", "val*"] @provider.process_get(command).should == true - end - + end + it "should return false for a == nonmatch" do command = ["get", "fake value", "=~", "num*"] @provider.process_get(command).should == false - end + end end - + describe "match filters" do before do augeas_stub = stub("augeas", :match => ["set", "of", "values"]) - @provider = provider_class.new() - @provider.aug= augeas_stub + @provider = provider_class.new() + @provider.aug= augeas_stub end - + it "should return true for size match" do command = ["match", "fake value", "size", "==", "3"] @provider.process_match(command).should == true end - + it "should return false for a size non match" do command = ["match", "fake value", "size", "<", "3"] @provider.process_match(command).should == false - end - + end + it "should return true for includes match" do command = ["get", "fake value", "include", "values"] @provider.process_match(command).should == true - end - + end + it "should return false for includes non match" do command = ["get", "fake value", "include", "JarJar"] @provider.process_match(command).should == false - end - + end + it "should return true for an array match" do command = ["get", "fake value", "==", "['set', 'of', 'values']"] @provider.process_match(command).should == true - end - + end + it "should return false for an array non match" do command = ["get", "fake value", "==", "['this', 'should', 'not', 'match']"] @provider.process_match(command).should == false - end - end - - describe "legacy need to run" do + end + end + + describe "need to run" do it "should handle no filters" do - resource = stub("resource", :[] => "") - augeas_stub = stub("augeas", :match => ["set", "of", "values"]) + resource = stub("resource") + resource.stubs(:[]).returns(false).then.returns("") + augeas_stub = stub("augeas", :match => ["set", "of", "values"]) + augeas_stub.stubs("close") provider = provider_class.new(resource) provider.stubs(:get_augeas_version).returns("0.3.5") - provider.need_to_run?.should == true + provider.need_to_run?.should == true end - + it "should return true when a get filter matches" do - resource = stub("resource", :[] => "get path == value") + resource = stub("resource") + resource.stubs(:[]).returns(false).then.returns("get path == value") provider = provider_class.new(resource) augeas_stub = stub("augeas", :get => "value") + augeas_stub.stubs("close") provider.aug= augeas_stub - provider.stubs(:get_augeas_version).returns("0.3.5") - provider.need_to_run?.should == true - end - + provider.stubs(:get_augeas_version).returns("0.3.5") + provider.need_to_run?.should == true + end + it "should return false when a get filter does not match" do - resource = stub("resource", :[] => "get path == another value") + resource = stub("resource") + resource.stubs(:[]).returns(false).then.returns("get path == another value") provider = provider_class.new(resource) augeas_stub = stub("augeas", :get => "value") + augeas_stub.stubs("close") provider.aug= augeas_stub - provider.stubs(:get_augeas_version).returns("0.3.5") - provider.need_to_run?.should == false - end - + provider.stubs(:get_augeas_version).returns("0.3.5") + provider.need_to_run?.should == false + end + it "should return true when a match filter matches" do - resource = stub("resource", :[] => "match path size == 3") + resource = stub("resource") + resource.stubs(:[]).returns(false).then.returns("match path size == 3") provider = provider_class.new(resource) augeas_stub = stub("augeas", :match => ["set", "of", "values"]) + augeas_stub.stubs("close") provider.aug= augeas_stub - provider.stubs(:get_augeas_version).returns("0.3.5") - provider.need_to_run?.should == true - end - + provider.stubs(:get_augeas_version).returns("0.3.5") + provider.need_to_run?.should == true + end + it "should return false when a match filter does not match" do - resource = stub("resource", :[] => "match path size == 2") + resource = stub("resource") + resource.stubs(:[]).returns(false).then.returns("match path size == 2") + provider = provider_class.new(resource) + augeas_stub = stub("augeas", :match => ["set", "of", "values"]) + augeas_stub.stubs("close") + provider.aug= augeas_stub + provider.stubs(:get_augeas_version).returns("0.3.5") + provider.need_to_run?.should == false + end + + #This is a copy of the last one, with setting the force to true + it "setting force should not change the above logic" do + resource = stub("resource") + resource.stubs(:[]).returns(true).then.returns("match path size == 2") provider = provider_class.new(resource) augeas_stub = stub("augeas", :match => ["set", "of", "values"]) + augeas_stub.stubs("close") provider.aug= augeas_stub - provider.stubs(:get_augeas_version).returns("0.3.5") - provider.need_to_run?.should == false - end + provider.stubs(:get_augeas_version).returns("0.3.5") + provider.need_to_run?.should == false + end end - - describe "legacy augeas integration" do - + + describe "augeas execution integration" do + before do @resource = stub("resource") @provider = provider_class.new(@resource) @augeas = stub("augeas") @provider.aug= @augeas - @provider.stubs(:get_augeas_version).returns("0.3.5") + @provider.stubs(:get_augeas_version).returns("0.3.5") end - + it "should handle set commands" do command = [["set", "/Jar/Jar", "Binks"]] context = "/some/path" @resource.expects(:[]).times(2).returns(command).then.returns(context) @augeas.expects(:set).with("/some/path/Jar/Jar", "Binks") @augeas.expects(:save).returns(true) + @augeas.expects(:close) @provider.execute_changes.should == :executed end - + it "should handle rm commands" do command = [["rm", "/Jar/Jar"]] context = "" @resource.expects(:[]).times(2).returns(command).then.returns(context) @augeas.expects(:rm).with("/Jar/Jar") @augeas.expects(:save).returns(true) + @augeas.expects(:close) @provider.execute_changes.should == :executed - end - + end + it "should handle remove commands" do command = [["remove", "Jar/Jar"]] context = "" @resource.expects(:[]).times(2).returns(command).then.returns(context) @augeas.expects(:rm).with("/Jar/Jar") @augeas.expects(:save).returns(true) + @augeas.expects(:close) @provider.execute_changes.should == :executed - end - + end + it "should handle clear commands" do command = [["clear", "/Jar/Jar"]] context = "/foo" @resource.expects(:[]).times(2).returns(command).then.returns(context) @augeas.expects(:clear).with("/foo/Jar/Jar") @augeas.expects(:save).returns(true) + @augeas.expects(:close) @provider.execute_changes.should == :executed - end - + end + it "should handle ins commands with before" do command = [["ins", "Binks", "before /Jar/Jar"]] context = "/foo" @resource.expects(:[]).times(2).returns(command).then.returns(context) @augeas.expects(:insert).with("/foo/Jar/Jar", "Binks", true) @augeas.expects(:save).returns(true) + @augeas.expects(:close) @provider.execute_changes.should == :executed end it "should handle ins commands with before" do command = [["ins", "Binks", "after /Jar/Jar"]] context = "/foo" @resource.expects(:[]).times(2).returns(command).then.returns(context) @augeas.expects(:insert).with("/foo/Jar/Jar", "Binks", false) @augeas.expects(:save).returns(true) + @augeas.expects(:close) @provider.execute_changes.should == :executed end it "should handle ins with no context" do command = [["ins", "Binks", "after /Jar/Jar"]] context = "" # this is the default @resource.expects(:[]).times(2).returns(command).then.returns(context) @augeas.expects(:insert).with("/Jar/Jar", "Binks", false) @augeas.expects(:save).returns(true) + @augeas.expects(:close) @provider.execute_changes.should == :executed - end - + end + it "should handle multiple commands" do command = [["ins", "Binks", "after /Jar/Jar"], ["clear", "/Jar/Jar"]] context = "/foo" @resource.expects(:[]).times(2).returns(command).then.returns(context) @augeas.expects(:insert).with("/foo/Jar/Jar", "Binks", false) - @augeas.expects(:clear).with("/foo/Jar/Jar") + @augeas.expects(:clear).with("/foo/Jar/Jar") @augeas.expects(:save).returns(true) + @augeas.expects(:close) @provider.execute_changes.should == :executed - end + end end end