diff --git a/spec/integration/type/file_spec.rb b/spec/integration/type/file_spec.rb index 9814c4539..03d3c8a10 100755 --- a/spec/integration/type/file_spec.rb +++ b/spec/integration/type/file_spec.rb @@ -1,511 +1,485 @@ #!/usr/bin/env rspec require 'spec_helper' require 'puppet_spec/files' describe Puppet::Type.type(:file) do include PuppetSpec::Files + let(:catalog) { Puppet::Resource::Catalog.new } + let(:path) { tmpfile('file_testing') } + before do # stub this to not try to create state.yaml Puppet::Util::Storage.stubs(:store) end it "should not attempt to manage files that do not exist if no means of creating the file is specified" do - file = Puppet::Type.type(:file).new :path => make_absolute("/my/file"), :mode => "755" - catalog = Puppet::Resource::Catalog.new + file = described_class.new :path => path, :mode => 0755 catalog.add_resource file file.parameter(:mode).expects(:retrieve).never - transaction = Puppet::Transaction.new(catalog) - transaction.resource_harness.evaluate(file).should_not be_failed + report = catalog.apply.report + report.resource_statuses["File[#{path}]"].should_not be_failed + File.should_not be_exist(path) end describe "when writing files" do it "should backup files to a filebucket when one is configured", :fails_on_windows => true do - bucket = Puppet::Type.type(:filebucket).new :path => tmpfile("filebucket"), :name => "mybucket" - file = Puppet::Type.type(:file).new :path => tmpfile("bucket_backs"), :backup => "mybucket", :content => "foo" - catalog = Puppet::Resource::Catalog.new + filebucket = Puppet::Type.type(:filebucket).new :path => tmpfile("filebucket"), :name => "mybucket" + file = described_class.new :path => path, :backup => "mybucket", :content => "foo" catalog.add_resource file - catalog.add_resource bucket + catalog.add_resource filebucket File.open(file[:path], "w") { |f| f.puts "bar" } md5 = Digest::MD5.hexdigest(File.read(file[:path])) catalog.apply - bucket.bucket.getfile(md5).should == "bar\n" + filebucket.bucket.getfile(md5).should == "bar\n" end it "should backup files in the local directory when a backup string is provided" do - file = Puppet::Type.type(:file).new :path => tmpfile("bucket_backs"), :backup => ".bak", :content => "foo" - catalog = Puppet::Resource::Catalog.new + file = described_class.new :path => path, :backup => ".bak", :content => "foo" catalog.add_resource file File.open(file[:path], "w") { |f| f.puts "bar" } catalog.apply backup = file[:path] + ".bak" FileTest.should be_exist(backup) File.read(backup).should == "bar\n" end it "should fail if no backup can be performed" do - dir = tmpfile("backups") - Dir.mkdir(dir) - path = File.join(dir, "testfile") - file = Puppet::Type.type(:file).new :path => path, :backup => ".bak", :content => "foo" - catalog = Puppet::Resource::Catalog.new + file = described_class.new :path => path, :backup => ".bak", :content => "foo" catalog.add_resource file - File.open(file[:path], "w") { |f| f.puts "bar" } + File.open(path, 'w') { |f| f.puts "bar" } # Create a directory where the backup should be so that writing to it fails - Dir.mkdir(File.join(dir, "testfile.bak")) - - Puppet::Util::Log.stubs(:newmessage) + Dir.mkdir("#{path}.bak") catalog.apply - File.read(file[:path]).should == "bar\n" + File.read(path).should == "bar\n" end it "should not backup symlinks", :unless => Puppet.features.microsoft_windows? do link = tmpfile("link") dest1 = tmpfile("dest1") dest2 = tmpfile("dest2") bucket = Puppet::Type.type(:filebucket).new :path => tmpfile("filebucket"), :name => "mybucket" - file = Puppet::Type.type(:file).new :path => link, :target => dest2, :ensure => :link, :backup => "mybucket" - catalog = Puppet::Resource::Catalog.new + file = described_class.new :path => link, :target => dest2, :ensure => :link, :backup => "mybucket" catalog.add_resource file catalog.add_resource bucket File.open(dest1, "w") { |f| f.puts "whatever" } File.symlink(dest1, link) md5 = Digest::MD5.hexdigest(File.read(file[:path])) catalog.apply File.readlink(link).should == dest2 Find.find(bucket[:path]) { |f| File.file?(f) }.should be_nil end it "should backup directories to the local filesystem by copying the whole directory" do - file = Puppet::Type.type(:file).new :path => tmpfile("bucket_backs"), :backup => ".bak", :content => "foo", :force => true - catalog = Puppet::Resource::Catalog.new + file = described_class.new :path => path, :backup => ".bak", :content => "foo", :force => true catalog.add_resource file - Dir.mkdir(file[:path]) - otherfile = File.join(file[:path], "foo") + Dir.mkdir(path) + + otherfile = File.join(path, "foo") File.open(otherfile, "w") { |f| f.print "yay" } catalog.apply - backup = file[:path] + ".bak" + backup = "#{path}.bak" FileTest.should be_directory(backup) + File.read(File.join(backup, "foo")).should == "yay" end it "should backup directories to filebuckets by backing up each file separately", :fails_on_windows => true do bucket = Puppet::Type.type(:filebucket).new :path => tmpfile("filebucket"), :name => "mybucket" - file = Puppet::Type.type(:file).new :path => tmpfile("bucket_backs"), :backup => "mybucket", :content => "foo", :force => true - catalog = Puppet::Resource::Catalog.new + file = described_class.new :path => tmpfile("bucket_backs"), :backup => "mybucket", :content => "foo", :force => true catalog.add_resource file catalog.add_resource bucket Dir.mkdir(file[:path]) foofile = File.join(file[:path], "foo") barfile = File.join(file[:path], "bar") File.open(foofile, "w") { |f| f.print "fooyay" } File.open(barfile, "w") { |f| f.print "baryay" } foomd5 = Digest::MD5.hexdigest(File.read(foofile)) barmd5 = Digest::MD5.hexdigest(File.read(barfile)) catalog.apply bucket.bucket.getfile(foomd5).should == "fooyay" bucket.bucket.getfile(barmd5).should == "baryay" end it "should propagate failures encountered when renaming the temporary file" do - file = Puppet::Type.type(:file).new :path => tmpfile("fail_rename"), :content => "foo" - file.stubs(:remove_existing) # because it tries to make a backup + file = described_class.new :path => path, :content => "foo" + file.stubs(:perform_backup).returns(true) - catalog = Puppet::Resource::Catalog.new catalog.add_resource file - File.open(file[:path], "w") { |f| f.print "bar" } + File.open(path, "w") { |f| f.print "bar" } File.expects(:rename).raises ArgumentError - lambda { file.write(:content) }.should raise_error(Puppet::Error) - File.read(file[:path]).should == "bar" + expect { file.write(:content) }.to raise_error(Puppet::Error, /Could not rename temporary file/) + File.read(path).should == "bar" end end describe "when recursing" do def build_path(dir) Dir.mkdir(dir) File.chmod(0750, dir) @dirs = [dir] @files = [] %w{one two}.each do |subdir| fdir = File.join(dir, subdir) Dir.mkdir(fdir) File.chmod(0750, fdir) @dirs << fdir %w{three}.each do |file| ffile = File.join(fdir, file) @files << ffile File.open(ffile, "w") { |f| f.puts "test #{file}" } File.chmod(0640, ffile) end end end it "should be able to recurse over a nonexistent file", :fails_on_windows => true do - @path = tmpfile("file_integration_tests") - - @file = Puppet::Type::File.new( - :name => @path, + @file = described_class.new( + :name => path, :mode => 0644, :recurse => true, :backup => false ) - @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource @file + catalog.add_resource @file lambda { @file.eval_generate }.should_not raise_error end it "should be able to recursively set properties on existing files" do - @path = tmpfile("file_integration_tests") + path = tmpfile("file_integration_tests") - build_path(@path) + build_path(path) - @file = Puppet::Type::File.new( - :name => @path, + file = described_class.new( + :name => path, :mode => 0644, :recurse => true, :backup => false ) - @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource @file + catalog.add_resource file - @catalog.apply + catalog.apply + @dirs.should_not be_empty @dirs.each do |path| (File.stat(path).mode & 007777).should == 0755 end + @files.should_not be_empty @files.each do |path| (File.stat(path).mode & 007777).should == 0644 end end it "should be able to recursively make links to other files", :unless => Puppet.features.microsoft_windows? do source = tmpfile("file_link_integration_source") build_path(source) dest = tmpfile("file_link_integration_dest") - @file = Puppet::Type::File.new(:name => dest, :target => source, :recurse => true, :ensure => :link, :backup => false) + @file = described_class.new(:name => dest, :target => source, :recurse => true, :ensure => :link, :backup => false) - @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource @file + catalog.add_resource @file - @catalog.apply + catalog.apply @dirs.each do |path| link_path = path.sub(source, dest) File.lstat(link_path).should be_directory end @files.each do |path| link_path = path.sub(source, dest) File.lstat(link_path).ftype.should == "link" end end it "should be able to recursively copy files", :fails_on_windows => true do source = tmpfile("file_source_integration_source") build_path(source) dest = tmpfile("file_source_integration_dest") - @file = Puppet::Type::File.new(:name => dest, :source => source, :recurse => true, :backup => false) + @file = described_class.new(:name => dest, :source => source, :recurse => true, :backup => false) - @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource @file + catalog.add_resource @file - @catalog.apply + catalog.apply @dirs.each do |path| newpath = path.sub(source, dest) File.lstat(newpath).should be_directory end @files.each do |path| newpath = path.sub(source, dest) File.lstat(newpath).ftype.should == "file" end end it "should not recursively manage files managed by a more specific explicit file" do dir = tmpfile("recursion_vs_explicit_1") subdir = File.join(dir, "subdir") file = File.join(subdir, "file") FileUtils.mkdir_p(subdir) File.open(file, "w") { |f| f.puts "" } - base = Puppet::Type::File.new(:name => dir, :recurse => true, :backup => false, :mode => "755") - sub = Puppet::Type::File.new(:name => subdir, :recurse => true, :backup => false, :mode => "644") + base = described_class.new(:name => dir, :recurse => true, :backup => false, :mode => "755") + sub = described_class.new(:name => subdir, :recurse => true, :backup => false, :mode => "644") - @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource base - @catalog.add_resource sub + catalog.add_resource base + catalog.add_resource sub - @catalog.apply + catalog.apply (File.stat(file).mode & 007777).should == 0644 end it "should recursively manage files even if there is an explicit file whose name is a prefix of the managed file" do - dir = tmpfile("recursion_vs_explicit_2") - - managed = File.join(dir, "file") - generated = File.join(dir, "file_with_a_name_starting_with_the_word_file") + managed = File.join(path, "file") + generated = File.join(path, "file_with_a_name_starting_with_the_word_file") managed_mode = Puppet.features.microsoft_windows? ? 0444 : 0700 - FileUtils.mkdir_p(dir) - File.open(managed, "w") { |f| f.puts "" } - File.open(generated, "w") { |f| f.puts "" } + FileUtils.mkdir_p(path) + FileUtils.touch(managed) + FileUtils.touch(generated) - @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource Puppet::Type::File.new(:name => dir, :recurse => true, :backup => false, :mode => managed_mode) - @catalog.add_resource Puppet::Type::File.new(:name => managed, :recurse => true, :backup => false, :mode => "644") + catalog.add_resource described_class.new(:name => path, :recurse => true, :backup => false, :mode => managed_mode) + catalog.add_resource described_class.new(:name => managed, :recurse => true, :backup => false, :mode => "644") - @catalog.apply + catalog.apply (File.stat(generated).mode & 007777).should == managed_mode end end describe "when generating resources", :fails_on_windows => true do before do - @source = tmpfile("generating_in_catalog_source") + source = tmpfile("generating_in_catalog_source") - @dest = tmpfile("generating_in_catalog_dest") + Dir.mkdir(source) - Dir.mkdir(@source) - - s1 = File.join(@source, "one") - s2 = File.join(@source, "two") + s1 = File.join(source, "one") + s2 = File.join(source, "two") File.open(s1, "w") { |f| f.puts "uno" } File.open(s2, "w") { |f| f.puts "dos" } - @file = Puppet::Type::File.new(:name => @dest, :source => @source, :recurse => true, :backup => false) + @file = described_class.new( + :name => path, + :source => source, + :recurse => true, + :backup => false + ) - @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource @file + catalog.add_resource @file end it "should add each generated resource to the catalog" do - @catalog.apply do |trans| - @catalog.resource(:file, File.join(@dest, "one")).should be_instance_of(@file.class) - @catalog.resource(:file, File.join(@dest, "two")).should be_instance_of(@file.class) + catalog.apply do |trans| + catalog.resource(:file, File.join(path, "one")).should be_a(described_class) + catalog.resource(:file, File.join(path, "two")).should be_a(described_class) end end it "should have an edge to each resource in the relationship graph" do - @catalog.apply do |trans| - one = @catalog.resource(:file, File.join(@dest, "one")) - @catalog.relationship_graph.edge?(@file, one).should be + catalog.apply do |trans| + one = catalog.resource(:file, File.join(path, "one")) + catalog.relationship_graph.should be_edge(@file, one) - two = @catalog.resource(:file, File.join(@dest, "two")) - @catalog.relationship_graph.edge?(@file, two).should be + two = catalog.resource(:file, File.join(path, "two")) + catalog.relationship_graph.should be_edge(@file, two) end end end describe "when copying files" do # Ticket #285. it "should be able to copy files with pound signs in their names" do source = tmpfile("filewith#signs") dest = tmpfile("destwith#signs") File.open(source, "w") { |f| f.print "foo" } - file = Puppet::Type::File.new(:name => dest, :source => source) + file = described_class.new(:name => dest, :source => source) - catalog = Puppet::Resource::Catalog.new catalog.add_resource file catalog.apply File.read(dest).should == "foo" end it "should be able to copy files with spaces in their names" do source = tmpfile("filewith spaces") dest = tmpfile("destwith spaces") File.open(source, "w") { |f| f.print "foo" } File.chmod(0755, source) - file = Puppet::Type::File.new(:path => dest, :source => source) + file = described_class.new(:path => dest, :source => source) - catalog = Puppet::Resource::Catalog.new catalog.add_resource file catalog.apply expected_mode = Puppet.features.microsoft_windows? ? 0644 : 0755 File.read(dest).should == "foo" (File.stat(dest).mode & 007777).should == expected_mode end it "should be able to copy individual files even if recurse has been specified" do source = tmpfile("source") dest = tmpfile("dest") File.open(source, "w") { |f| f.print "foo" } - file = Puppet::Type::File.new(:name => dest, :source => source, :recurse => true) + file = described_class.new(:name => dest, :source => source, :recurse => true) - catalog = Puppet::Resource::Catalog.new catalog.add_resource file catalog.apply File.read(dest).should == "foo" end end - it "should be able to create files when 'content' is specified but 'ensure' is not" do - dest = tmpfile("files_with_content") - - - file = Puppet::Type.type(:file).new( - :name => dest, + it "should create a file with content if ensure is omitted" do + file = described_class.new( + :path => path, :content => "this is some content, yo" ) - catalog = Puppet::Resource::Catalog.new catalog.add_resource file catalog.apply - File.read(dest).should == "this is some content, yo" + File.read(path).should == "this is some content, yo" end - it "should create files with content if both 'content' and 'ensure' are set" do - dest = tmpfile("files_with_content") - - - file = Puppet::Type.type(:file).new( - :name => dest, + it "should create files with content if both content and ensure are set" do + file = described_class.new( + :path => path, :ensure => "file", :content => "this is some content, yo" ) - catalog = Puppet::Resource::Catalog.new catalog.add_resource file catalog.apply - File.read(dest).should == "this is some content, yo" + File.read(path).should == "this is some content, yo" end it "should delete files with sources but that are set for deletion" do - dest = tmpfile("dest_source_with_ensure") source = tmpfile("source_source_with_ensure") + File.open(source, "w") { |f| f.puts "yay" } - File.open(dest, "w") { |f| f.puts "boo" } + File.open(path, "w") { |f| f.puts "boo" } - file = Puppet::Type.type(:file).new( - :name => make_absolute(dest), + file = described_class.new( + :path => path, :ensure => :absent, :source => source, :backup => false ) - catalog = Puppet::Resource::Catalog.new catalog.add_resource file catalog.apply - File.should_not be_exist(dest) + File.should_not be_exist(path) end describe "when purging files" do before do - @sourcedir = tmpfile("purge_source") - @destdir = tmpfile("purge_dest") - Dir.mkdir(@sourcedir) - Dir.mkdir(@destdir) - @sourcefile = File.join(@sourcedir, "sourcefile") - @copiedfile = File.join(@destdir, "sourcefile") - @localfile = File.join(@destdir, "localfile") - @purgee = File.join(@destdir, "to_be_purged") - File.open(@localfile, "w") { |f| f.puts "rahtest" } - File.open(@sourcefile, "w") { |f| f.puts "funtest" } + sourcedir = tmpfile("purge_source") + destdir = tmpfile("purge_dest") + Dir.mkdir(sourcedir) + Dir.mkdir(destdir) + sourcefile = File.join(sourcedir, "sourcefile") + + @copiedfile = File.join(destdir, "sourcefile") + @localfile = File.join(destdir, "localfile") + @purgee = File.join(destdir, "to_be_purged") + + File.open(@localfile, "w") { |f| f.print "oldtest" } + File.open(sourcefile, "w") { |f| f.print "funtest" } # this file should get removed - File.open(@purgee, "w") { |f| f.puts "footest" } + File.open(@purgee, "w") { |f| f.print "footest" } - @lfobj = Puppet::Type.newfile( + lfobj = Puppet::Type.newfile( :title => "localfile", :path => @localfile, - :content => "rahtest\n", + :content => "rahtest", :ensure => :file, :backup => false ) - @destobj = Puppet::Type.newfile( + destobj = Puppet::Type.newfile( :title => "destdir", - :path => @destdir, - :source => @sourcedir, + :path => destdir, + :source => sourcedir, :backup => false, :purge => true, :recurse => true ) - @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource @lfobj, @destobj + catalog.add_resource lfobj, destobj + catalog.apply end it "should still copy remote files" do - @catalog.apply - FileTest.should be_exist(@copiedfile) + File.read(@copiedfile).should == 'funtest' end it "should not purge managed, local files" do - @catalog.apply - FileTest.should be_exist(@localfile) + File.read(@localfile).should == 'rahtest' end it "should purge files that are neither remote nor otherwise managed" do - @catalog.apply FileTest.should_not be_exist(@purgee) end end end