Please review pull request #546: (#11988) Don't overwrite symlinks in augeas provider opened by (nicklewis)
Description:
Previously, if not running with force set, we would try to write the
file in SAVE_NEWFILE mode to create a .augnew file with the
changes. We determined whether there were changes to be made based on
that file (and used it to show a diff). When it came time to actually
make the changes, we would simply move the .augnew file over the file
being managed. Unfortunately, if the file being managed were a symlink,
this would clobber it.
There was a fallback path in the case of force (or older versions of
augeas not supporting SAVE_NEWFILE) in which we would make the
changes in SAVE_OVERWRITE mode as normal. Now, the behavior is a
combination of the two; we still use SAVE_NEWFILE to determine whether
changes need to be made and to show a diff, but then remove the .augnew
file and always run again in SAVE_OVERWRITE mode to save the changes.
This effectively delegates the behavior of preserving the file, etc.
to augeas, so we don't duplicate effort or bugs.
- Opened: Wed Feb 29 23:08:19 UTC 2012
- Based on: puppetlabs:2.7.x (675b245647f5452796216eeb35763579c0c8973b)
- Requested merge: nicklewis:ticket/2.7.x/11988 (dfefc23b744b68589068f1c0e92e2b7baee0cf83)
Diff follows:
diff --git a/lib/puppet/provider/augeas/augeas.rb b/lib/puppet/provider/augeas/augeas.rb
index 703a01b..303c59d 100644
--- a/lib/puppet/provider/augeas/augeas.rb
+++ b/lib/puppet/provider/augeas/augeas.rb
@@ -285,10 +285,10 @@ def need_to_run?
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.
+ # can make the changes now and see if changes were made.
if return_value and versioncmp(get_augeas_version, "0.3.6") >= 0
debug("Will attempt to save and only run if files changed")
+ # Execute in NEWFILE mode so we can show a diff
set_augeas_save_mode(SAVE_NEWFILE)
do_execute_changes
save_result = @aug.save
@@ -302,9 +302,7 @@ def need_to_run?
if Puppet[:show_diff]
notice "\n" + diff(saved_file, saved_file + ".augnew")
end
- if resource.noop?
- File.delete(saved_file + ".augnew")
- end
+ File.delete(saved_file + ".augnew")
end
debug("Files changed, should execute")
return_value = true
@@ -323,32 +321,16 @@ def need_to_run?
end
def execute_changes
- # Re-connect to augeas, and re-execute the changes
- begin
- open_augeas
- saved_files = @aug.match("/augeas/events/saved")
- unless saved_files.empty?
- saved_files.each do |key|
- root = resource[:root].sub(/^\/$/, "")
- saved_file = @aug.get(key).to_s.sub(/^\/files/, root)
- if File.exists?(saved_file + ".augnew")
- success = File.rename(saved_file + ".augnew", saved_file)
- debug(saved_file + ".augnew moved to " + saved_file)
- fail("Rename failed with return code #{success}") if success != 0
- end
- end
- else
- debug("No saved files, re-executing augeas")
- set_augeas_save_mode(SAVE_OVERWRITE) if versioncmp(get_augeas_version, "0.3.6") >= 0
- do_execute_changes
- success = @aug.save
- fail("Save failed with return code #{success}") if success != true
- end
- ensure
- close_augeas
- end
+ # Reload augeas, and execute the changes for real
+ aug.load
+ set_augeas_save_mode(SAVE_OVERWRITE) if versioncmp(get_augeas_version, "0.3.6") >= 0
+ do_execute_changes
+ success = @aug.save
+ fail("Save failed with return code #{success}") if success != true
:executed
+ ensure
+ close_augeas
end
# Actually execute the augeas changes.
diff --git a/spec/unit/provider/augeas/augeas_spec.rb b/spec/unit/provider/augeas/augeas_spec.rb
index 52ebb34..e985398 100755
--- a/spec/unit/provider/augeas/augeas_spec.rb
+++ b/spec/unit/provider/augeas/augeas_spec.rb
@@ -4,14 +4,22 @@
provider_class = Puppet::Type.type(:augeas).provider(:augeas)
describe provider_class do
- describe "command parsing" do
- before do
- @resource = stub("resource")
- @provider = provider_class.new(@resource)
- end
+ before(:each) do
+ @resource = Puppet::Type.type(:augeas).new(
+ :name => "test",
+ :root => my_fixture_dir,
+ :provider => :augeas
+ )
+ @provider = provider_class.new(@resource)
+ end
+
+ after(:each) do
+ @provider.close_augeas
+ end
+ describe "command parsing" do
it "should break apart a single line into three tokens and clean up the context" do
- @resource.stubs(:[]).returns("/context")
+ @resource[:context] = "/context"
tokens = @provider.parse_commands("set Jar/Jar Binks")
tokens.size.should == 1
tokens[0].size.should == 3
@@ -21,7 +29,6 @@
end
it "should break apart a multiple line into six tokens" do
- @resource.stubs(:[]).returns("")
tokens = @provider.parse_commands("set /Jar/Jar Binks\nrm anakin")
tokens.size.should == 2
tokens[0].size.should == 3
@@ -34,7 +41,6 @@
end
it "should strip whitespace and ignore blank lines" do
- @resource.stubs(:[]).returns("")
tokens = @provider.parse_commands(" set /Jar/Jar Binks \t\n \n\n rm anakin ")
tokens.size.should == 2
tokens[0].size.should == 3
@@ -47,7 +53,7 @@
end
it "should handle arrays" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
commands = ["set /Jar/Jar Binks", "rm anakin"]
tokens = @provider.parse_commands(commands)
tokens.size.should == 2
@@ -72,7 +78,7 @@
#end
it "should accept spaces in the value and single ticks" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
tokens = @provider.parse_commands("set JarJar 'Binks is my copilot'")
tokens.size.should == 1
tokens[0].size.should == 3
@@ -82,7 +88,7 @@
end
it "should accept spaces in the value and double ticks" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
tokens = @provider.parse_commands('set /JarJar "Binks is my copilot"')
tokens.size.should == 1
tokens[0].size.should == 3
@@ -92,7 +98,7 @@
end
it "should accept mixed ticks" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
tokens = @provider.parse_commands('set JarJar "Some \'Test\'"')
tokens.size.should == 1
tokens[0].size.should == 3
@@ -102,59 +108,59 @@
end
it "should handle predicates with literals" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
tokens = @provider.parse_commands("rm */*[module='pam_console.so']")
tokens.should == [["rm", "/foo/*/*[module='pam_console.so']"]]
end
it "should handle whitespace in predicates" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
tokens = @provider.parse_commands("ins 42 before /files/etc/hosts/*/ipaddr[ . = '127.0.0.1' ]")
tokens.should == [["ins", "42", "before","/files/etc/hosts/*/ipaddr[ . = '127.0.0.1' ]"]]
end
it "should handle multiple predicates" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
tokens = @provider.parse_commands("clear pam.d/*/*[module = 'system-auth'][type = 'account']")
tokens.should == [["clear", "/foo/pam.d/*/*[module = 'system-auth'][type = 'account']"]]
end
it "should handle nested predicates" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
args = ["clear", "/foo/pam.d/*/*[module[ ../type = 'type] = 'system-auth'][type[last()] = 'account']"]
tokens = @provider.parse_commands(args.join(" "))
tokens.should == [ args ]
end
it "should handle escaped doublequotes in doublequoted string" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
tokens = @provider.parse_commands("set /foo \"''\\\"''\"")
tokens.should == [[ "set", "/foo", "''\\\"''" ]]
end
it "should allow escaped spaces and brackets in paths" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
args = [ "set", "/white\\ space/\\[section", "value" ]
tokens = @provider.parse_commands(args.join(" \t "))
tokens.should == [ args ]
end
it "should allow single quoted escaped spaces in paths" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
args = [ "set", "'/white\\ space/key'", "value" ]
tokens = @provider.parse_commands(args.join(" \t "))
tokens.should == [[ "set", "/white\\ space/key", "value" ]]
end
it "should allow double quoted escaped spaces in paths" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
args = [ "set", '"/white\\ space/key"', "value" ]
tokens = @provider.parse_commands(args.join(" \t "))
tokens.should == [[ "set", "/white\\ space/key", "value" ]]
end
it "should remove trailing slashes" do
- @resource.stubs(:[]).returns("/foo/")
+ @resource[:context] = "/foo/"
tokens = @provider.parse_commands("set foo/ bar")
tokens.should == [[ "set", "/foo/foo", "bar" ]]
end
@@ -162,9 +168,9 @@
describe "get filters" do
before do
- augeas_stub = stub("augeas", :get => "value")
- @provider = provider_class.new
- @provider.aug= augeas_stub
+ augeas = stub("augeas", :get => "value")
+ augeas.stubs("close")
+ @provider.aug = augeas
end
it "should return false for a = nonmatch" do
@@ -190,10 +196,10 @@
describe "match filters" do
before do
- resource = stub("resource", :[] => "")
- augeas_stub = stub("augeas", :match => ["set", "of", "values"])
- @provider = provider_class.new(resource)
- @provider.aug= augeas_stub
+ augeas = stub("augeas", :match => ["set", "of", "values"])
+ augeas.stubs("close")
+ @provider = provider_class.new(@resource)
+ @provider.aug = augeas
end
it "should return true for size match" do
@@ -248,126 +254,89 @@
end
describe "need to run" do
+ before(:each) do
+ @augeas = stub("augeas")
+ @augeas.stubs("close")
+ @provider.aug = @augeas
+
+ # These tests pretend to be an earlier version so the provider doesn't
+ # attempt to make the change in the need_to_run? method
+ @provider.stubs(:get_augeas_version).returns("0.3.5")
+ end
+
it "should handle no filters" do
- resource = stub("resource")
- resource.stubs(:[]).returns(false).then.returns("").then.returns("")
- resource.stubs(:noop?).returns(false)
- augeas_stub = stub("augeas", :match => ["set", "of", "values"])
- augeas_stub.stubs("close")
- provider = provider_class.new(resource)
- provider.aug= augeas_stub
- provider.stubs(:get_augeas_version).returns("0.3.5")
- provider.need_to_run?.should == true
+ @augeas.stubs("match").returns(["set", "of", "values"])
+ @provider.need_to_run?.should == true
end
it "should return true when a get filter matches" do
- resource = stub("resource")
- resource.stubs(:[]).returns(false).then.returns("get path == value").then.returns("")
- resource.stubs(:noop?).returns(false)
- 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
+ @resource[:onlyif] = "get path == value"
+ @augeas.stubs("get").returns("value")
+ @provider.need_to_run?.should == true
end
it "should return false when a get filter does not match" do
- resource = stub("resource")
- resource.stubs(:[]).returns(false).then.returns("get path == another value").then.returns("")
- 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
+ @resource[:onlyif] = "get path == another value"
+ @augeas.stubs("get").returns("value")
+ @provider.need_to_run?.should == false
end
it "should return true when a match filter matches" do
- resource = stub("resource")
- resource.stubs(:[]).returns(false).then.returns("match path size == 3").then.returns("")
- resource.stubs(:noop?).returns(false)
- 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
+ @resource[:onlyif] = "match path size == 3"
+ @augeas.stubs("match").returns(["set", "of", "values"])
+ @provider.need_to_run?.should == true
end
it "should return false when a match filter does not match" do
- resource = stub("resource")
- resource.stubs(:[]).returns(false).then.returns("match path size == 2").then.returns("")
- 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
+ @resource[:onlyif] = "match path size == 2"
+ @augeas.stubs("match").returns(["set", "of", "values"])
+ @provider.need_to_run?.should == false
end
- #This is a copy of the last one, with setting the force to true
+ # Now setting 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").then.returns("")
- 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
+ @resource[:force] = true
+ @resource[:onlyif] = "match path size == 2"
+ @augeas.stubs("match").returns(["set", "of", "values"])
+ @provider.need_to_run?.should == false
end
#Ticket 5211 testing
it "should return true when a size != the provided value" do
- resource = stub("resource")
- resource.stubs(:[]).returns(false).then.returns("match path size != 17").then.returns("")
- resource.stubs(:noop?).returns(false)
- 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
+ @resource[:onlyif] = "match path size != 17"
+ @augeas.stubs("match").returns(["set", "of", "values"])
+ @provider.need_to_run?.should == true
end
#Ticket 5211 testing
it "should return false when a size doeas equal the provided value" do
- resource = stub("resource")
- resource.stubs(:[]).returns(false).then.returns("match path size != 3").then.returns("")
- 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
+ @resource[:onlyif] = "match path size != 3"
+ @augeas.stubs("match").returns(["set", "of", "values"])
+ @provider.need_to_run?.should == false
end
# Ticket 2728 (diff files)
- describe "and Puppet[:show_diff] is set", :if => Puppet.features.augeas? do
- before do
+ describe "and Puppet[:show_diff] is set" do
+ before(:each) do
Puppet[:show_diff] = true
- @resource = Puppet::Type.type(:augeas).new(:name => "test")
- @provider = provider_class.new(@resource)
- @augeas_stub = stub("augeas")
- @provider.aug = @augeas_stub
-
- @augeas_stub.stubs("get").with("/augeas/version").returns("0.10.0")
- @augeas_stub.stubs(:set).returns(true)
- @augeas_stub.stubs(:save).returns(true)
+ @resource[:root] = ""
+ @provider.stubs(:get_augeas_version).returns("0.10.0")
+ @augeas.stubs(:set).returns(true)
+ @augeas.stubs(:save).returns(true)
end
it "should call diff when a file is shown to have been changed" do
file = "/etc/hosts"
+ File.stubs(:delete)
@resource[:context] = "/files"
@resource[:changes] = ["set #{file}/foo bar"]
- @augeas_stub.stubs(:match).with("/augeas/events/saved").returns(["/augeas/events/saved"])
- @augeas_stub.stubs(:get).with("/augeas/events/saved").returns(["/files#{file}"])
- @augeas_stub.expects(:set).with("/augeas/save", "newfile")
- @augeas_stub.expects(:close).never()
+ @augeas.stubs(:match).with("/augeas/events/saved").returns(["/augeas/events/saved"])
+ @augeas.stubs(:get).with("/augeas/events/saved").returns(["/files#{file}"])
+ @augeas.expects(:set).with("/augeas/save", "newfile")
+ @augeas.expects(:close).never()
@provider.expects("diff").with("#{file}", "#{file}.augnew").returns("")
@provider.should be_need_to_run
@@ -376,15 +345,16 @@
it "should call diff for each file thats changed" do
file1 = "/etc/hosts"
file2 = "/etc/resolv.conf"
+ File.stubs(:delete)
@resource[:context] = "/files"
@resource[:changes] = ["set #{file1}/foo bar", "set #{file2}/baz biz"]
- @augeas_stub.stubs(:match).with("/augeas/events/saved").returns(["/augeas/events/saved[1]", "/augeas/events/saved[2]"])
- @augeas_stub.stubs(:get).with("/augeas/events/saved[1]").returns(["/files#{file1}"])
- @augeas_stub.stubs(:get).with("/augeas/events/saved[2]").returns(["/files#{file2}"])
- @augeas_stub.expects(:set).with("/augeas/save", "newfile")
- @augeas_stub.expects(:close).never()
+ @augeas.stubs(:match).with("/augeas/events/saved").returns(["/augeas/events/saved[1]", "/augeas/events/saved[2]"])
+ @augeas.stubs(:get).with("/augeas/events/saved[1]").returns(["/files#{file1}"])
+ @augeas.stubs(:get).with("/augeas/events/saved[2]").returns(["/files#{file2}"])
+ @augeas.expects(:set).with("/augeas/save", "newfile")
+ @augeas.expects(:close).never()
@provider.expects(:diff).with("#{file1}", "#{file1}.augnew").returns("")
@provider.expects(:diff).with("#{file2}", "#{file2}.augnew").returns("")
@@ -395,15 +365,16 @@
it "should call diff when a file is shown to have been changed" do
root = "/tmp/foo"
file = "/etc/hosts"
+ File.stubs(:delete)
@resource[:context] = "/files"
@resource[:changes] = ["set #{file}/foo bar"]
@resource[:root] = root
- @augeas_stub.stubs(:match).with("/augeas/events/saved").returns(["/augeas/events/saved"])
- @augeas_stub.stubs(:get).with("/augeas/events/saved").returns(["/files#{file}"])
- @augeas_stub.expects(:set).with("/augeas/save", "newfile")
- @augeas_stub.expects(:close).never()
+ @augeas.stubs(:match).with("/augeas/events/saved").returns(["/augeas/events/saved"])
+ @augeas.stubs(:get).with("/augeas/events/saved").returns(["/files#{file}"])
+ @augeas.expects(:set).with("/augeas/save", "newfile")
+ @augeas.expects(:close).never()
@provider.expects(:diff).with("#{root}#{file}", "#{root}#{file}.augnew").returns("")
@provider.should be_need_to_run
@@ -416,26 +387,25 @@
@resource[:context] = "/files"
@resource[:changes] = ["set #{file}/foo bar"]
- @augeas_stub.stubs(:match).with("/augeas/events/saved").returns([])
- @augeas_stub.expects(:set).with("/augeas/save", "newfile")
- @augeas_stub.expects(:get).with("/augeas/events/saved").never()
- @augeas_stub.expects(:close)
+ @augeas.stubs(:match).with("/augeas/events/saved").returns([])
+ @augeas.expects(:set).with("/augeas/save", "newfile")
+ @augeas.expects(:get).with("/augeas/events/saved").never()
+ @augeas.expects(:close)
@provider.expects(:diff).never()
@provider.should_not be_need_to_run
end
- it "should cleanup when in noop mode" do
+ it "should cleanup the .augnew file" do
file = "/etc/hosts"
- @resource[:noop] = true
@resource[:context] = "/files"
@resource[:changes] = ["set #{file}/foo bar"]
- @augeas_stub.stubs(:match).with("/augeas/events/saved").returns(["/augeas/events/saved"])
- @augeas_stub.stubs(:get).with("/augeas/events/saved").returns(["/files#{file}"])
- @augeas_stub.expects(:set).with("/augeas/save", "newfile")
- @augeas_stub.expects(:close)
+ @augeas.stubs(:match).with("/augeas/events/saved").returns(["/augeas/events/saved"])
+ @augeas.stubs(:get).with("/augeas/events/saved").returns(["/files#{file}"])
+ @augeas.expects(:set).with("/augeas/save", "newfile")
+ @augeas.expects(:close)
File.expects(:delete).with(file + ".augnew")
@@ -449,9 +419,9 @@
@resource[:context] = "/files"
@resource[:changes] = ["set #{file}/foo bar"]
- @augeas_stub.stubs(:save).returns(false)
- @augeas_stub.stubs(:match).with("/augeas/events/saved").returns([])
- @augeas_stub.expects(:close)
+ @augeas.stubs(:save).returns(false)
+ @augeas.stubs(:match).with("/augeas/events/saved").returns([])
+ @augeas.expects(:close)
@provider.expects(:diff).never()
lambda { @provider.need_to_run? }.should raise_error
@@ -460,20 +430,18 @@
end
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")
+ @augeas = stub("augeas", :load)
+ @augeas.stubs("close")
@augeas.stubs(:match).with("/augeas/events/saved").returns([])
+
+ @provider.aug = @augeas
+ @provider.stubs(:get_augeas_version).returns("0.3.5")
end
it "should handle set commands" do
- command = "set JarJar Binks"
- context = "/some/path/"
- @resource.expects(:[]).times(2).returns(command).then.returns(context)
+ @resource[:changes] = "set JarJar Binks"
+ @resource[:context] = "/some/path/"
@augeas.expects(:set).with("/some/path/JarJar", "Binks").returns(true)
@augeas.expects(:save).returns(true)
@augeas.expects(:close)
@@ -481,9 +449,7 @@
end
it "should handle rm commands" do
- command = "rm /Jar/Jar"
- context = ""
- @resource.expects(:[]).times(2).returns(command).then.returns(context)
+ @resource[:changes] = "rm /Jar/Jar"
@augeas.expects(:rm).with("/Jar/Jar")
@augeas.expects(:save).returns(true)
@augeas.expects(:close)
@@ -491,9 +457,7 @@
end
it "should handle remove commands" do
- command = "remove /Jar/Jar"
- context = ""
- @resource.expects(:[]).times(2).returns(command).then.returns(context)
+ @resource[:changes] = "remove /Jar/Jar"
@augeas.expects(:rm).with("/Jar/Jar")
@augeas.expects(:save).returns(true)
@augeas.expects(:close)
@@ -501,20 +465,17 @@
end
it "should handle clear commands" do
- command = "clear Jar/Jar"
- context = "/foo/"
- @resource.expects(:[]).times(2).returns(command).then.returns(context)
+ @resource[:changes] = "clear Jar/Jar"
+ @resource[:context] = "/foo/"
@augeas.expects(:clear).with("/foo/Jar/Jar").returns(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 before Jar/Jar"
- context = "/foo"
- @resource.expects(:[]).times(2).returns(command).then.returns(context)
+ @resource[:changes] = "ins Binks before Jar/Jar"
+ @resource[:context] = "/foo"
@augeas.expects(:insert).with("/foo/Jar/Jar", "Binks", true)
@augeas.expects(:save).returns(true)
@augeas.expects(:close)
@@ -522,9 +483,8 @@
end
it "should handle ins commands with after" do
- command = "ins Binks after /Jar/Jar"
- context = "/foo"
- @resource.expects(:[]).times(2).returns(command).then.returns(context)
+ @resource[:changes] = "ins Binks after /Jar/Jar"
+ @resource[:context] = "/foo"
@augeas.expects(:insert).with("/Jar/Jar", "Binks", false)
@augeas.expects(:save).returns(true)
@augeas.expects(:close)
@@ -532,9 +492,7 @@
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)
+ @resource[:changes] = "ins Binks after /Jar/Jar"
@augeas.expects(:insert).with("/Jar/Jar", "Binks", false)
@augeas.expects(:save).returns(true)
@augeas.expects(:close)
@@ -542,9 +500,8 @@
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)
+ @resource[:changes] = ["ins Binks after /Jar/Jar", "clear Jar/Jar"]
+ @resource[:context] = "/foo/"
@augeas.expects(:insert).with("/Jar/Jar", "Binks", false)
@augeas.expects(:clear).with("/foo/Jar/Jar").returns(true)
@augeas.expects(:save).returns(true)
@@ -553,9 +510,8 @@
end
it "should handle defvar commands" do
- command = "defvar myjar Jar/Jar"
- context = "/foo/"
- @resource.expects(:[]).times(2).returns(command).then.returns(context)
+ @resource[:changes] = "defvar myjar Jar/Jar"
+ @resource[:context] = "/foo/"
@augeas.expects(:defvar).with("myjar", "/foo/Jar/Jar").returns(true)
@augeas.expects(:save).returns(true)
@augeas.expects(:close)
@@ -563,9 +519,8 @@
end
it "should pass through augeas variables without context" do
- command = ["defvar myjar Jar/Jar","set $myjar/Binks 1"]
- context = "/foo/"
- @resource.expects(:[]).times(2).returns(command).then.returns(context)
+ @resource[:changes] = ["defvar myjar Jar/Jar","set $myjar/Binks 1"]
+ @resource[:context] = "/foo/"
@augeas.expects(:defvar).with("myjar", "/foo/Jar/Jar").returns(true)
# this is the important bit, shouldn't be /foo/$myjar/Binks
@augeas.expects(:set).with("$myjar/Binks", "1").returns(true)
@@ -575,9 +530,8 @@
end
it "should handle defnode commands" do
- command = "defnode newjar Jar/Jar[last()+1] Binks"
- context = "/foo/"
- @resource.expects(:[]).times(2).returns(command).then.returns(context)
+ @resource[:changes] = "defnode newjar Jar/Jar[last()+1] Binks"
+ @resource[:context] = "/foo/"
@augeas.expects(:defnode).with("newjar", "/foo/Jar/Jar[last()+1]", "Binks").returns(true)
@augeas.expects(:save).returns(true)
@augeas.expects(:close)
@@ -585,9 +539,8 @@
end
it "should handle mv commands" do
- command = "mv Jar/Jar Binks"
- context = "/foo/"
- @resource.expects(:[]).times(2).returns(command).then.returns(context)
+ @resource[:changes] = "mv Jar/Jar Binks"
+ @resource[:context] = "/foo/"
@augeas.expects(:mv).with("/foo/Jar/Jar", "/foo/Binks").returns(true)
@augeas.expects(:save).returns(true)
@augeas.expects(:close)
@@ -595,9 +548,8 @@
end
it "should handle setm commands" do
- command = ["set test[1]/Jar/Jar Foo","set test[2]/Jar/Jar Bar","setm test Jar/Jar Binks"]
- context = "/foo/"
- @resource.expects(:[]).times(2).returns(command).then.returns(context)
+ @resource[:changes] = ["set test[1]/Jar/Jar Foo","set test[2]/Jar/Jar Bar","setm test Jar/Jar Binks"]
+ @resource[:context] = "/foo/"
@augeas.expects(:set).with("/foo/test[1]/Jar/Jar", "Foo").returns(true)
@augeas.expects(:set).with("/foo/test[2]/Jar/Jar", "Bar").returns(true)
@augeas.expects(:setm).with("/foo/test", "Jar/Jar", "Binks").returns(true)
@@ -606,4 +558,33 @@
@provider.execute_changes.should == :executed
end
end
+
+ describe "when making changes", :if => Puppet.features.augeas? do
+ include PuppetSpec::Files
+
+ it "should not clobber the file if it's a symlink" do
+ Puppet::Util::Storage.stubs(:store)
+
+ link = tmpfile('link')
+ target = tmpfile('target')
+ FileUtils.touch(target)
+ FileUtils.symlink(target, link)
+
+ resource = Puppet::Type.type(:augeas).new(
+ :name => 'test',
+ :incl => link,
+ :lens => 'Sshd.lns',
+ :changes => "set PermitRootLogin no"
+ )
+
+ catalog = Puppet::Resource::Catalog.new
+ catalog.add_resource resource
+
+ catalog.apply
+
+ File.ftype(link).should == 'link'
+ File.readlink(link).should == target
+ File.read(target).should =~ /PermitRootLogin no/
+ end
+ end
end
-- You received this message because you are subscribed to the Google Groups "Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to [email protected].
For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en.
