diff --git a/lib/puppet/type/file/checksum.rb b/lib/puppet/type/file/checksum.rb index 7915c3888..3b748631a 100755 --- a/lib/puppet/type/file/checksum.rb +++ b/lib/puppet/type/file/checksum.rb @@ -1,284 +1,284 @@ require 'puppet/util/checksums' # Keep a copy of the file checksums, and notify when they change. This # property never actually modifies the system, it only notices when the system # changes on its own. Puppet::Type.type(:file).newproperty(:checksum) do include Puppet::Util::Checksums desc "How to check whether a file has changed. This state is used internally for file copying, but it can also be used to monitor files somewhat like Tripwire without managing the file contents in any way. You can specify that a file's checksum should be monitored and then subscribe to the file from another object and receive events to signify checksum changes, for instance. There are a number of checksum types available including MD5 hashing (and an md5lite variation that only hashes the first 500 characters of the file." @event = :file_changed @unmanaged = true @validtypes = %w{md5 md5lite timestamp mtime time} def self.validtype?(type) @validtypes.include?(type) end @validtypes.each do |ctype| newvalue(ctype) do handlesum() end end str = @validtypes.join("|") # This is here because Puppet sets this internally, using # {md5}...... newvalue(/^\{#{str}\}/) do handlesum() end newvalue(:nosum) do # nothing :nochange end # If they pass us a sum type, behave normally, but if they pass # us a sum type + sum, stick the sum in the cache. munge do |value| if value =~ /^\{(\w+)\}(.+)$/ type = symbolize($1) sum = $2 cache(type, sum) return type else if FileTest.directory?(@resource[:path]) return :time elsif @resource[:source] and value.to_s != "md5" self.warning("Files with source set must use md5 as checksum. Forcing to md5 from %s for %s" % [ value, @resource[:path] ]) return :md5 else return symbolize(value) end end end # Store the checksum in the data cache, or retrieve it if only the # sum type is provided. def cache(type, sum = nil) - return unless resource.catalog.host_config? + return unless c = resource.catalog and c.host_config? unless type raise ArgumentError, "A type must be specified to cache a checksum" end type = symbolize(type) type = :mtime if type == :timestamp type = :ctime if type == :time unless state = @resource.cached(:checksums) self.debug "Initializing checksum hash" state = {} @resource.cache(:checksums, state) end if sum unless sum =~ /\{\w+\}/ sum = "{%s}%s" % [type, sum] end state[type] = sum else return state[type] end end # Because source and content and whomever else need to set the checksum # and do the updating, we provide a simple mechanism for doing so. def checksum=(value) munge(@should) self.updatesum(value) end def checktype self.should || :md5 end # Checksums need to invert how changes are printed. def change_to_s(currentvalue, newvalue) begin if currentvalue == :absent return "defined '%s' as '%s'" % [self.name, self.currentsum] elsif newvalue == :absent return "undefined %s from '%s'" % [self.name, self.is_to_s(currentvalue)] else if defined? @cached and @cached return "%s changed '%s' to '%s'" % [self.name, @cached, self.is_to_s(currentvalue)] else return "%s changed '%s' to '%s'" % [self.name, self.currentsum, self.is_to_s(currentvalue)] end end rescue Puppet::Error, Puppet::DevError raise rescue => detail raise Puppet::DevError, "Could not convert change %s to string: %s" % [self.name, detail] end end def currentsum cache(checktype()) end # Retrieve the cached sum def getcachedsum hash = nil unless hash = @resource.cached(:checksums) hash = {} @resource.cache(:checksums, hash) end sumtype = self.should if hash.include?(sumtype) #self.notice "Found checksum %s for %s" % # [hash[sumtype] ,@resource[:path]] sum = hash[sumtype] unless sum =~ /^\{\w+\}/ sum = "{%s}%s" % [sumtype, sum] end return sum elsif hash.empty? #self.notice "Could not find sum of type %s" % sumtype return :nosum else #self.notice "Found checksum for %s but not of type %s" % # [@resource[:path],sumtype] return :nosum end end # Calculate the sum from disk. def getsum(checktype, file = nil) sum = "" checktype = :mtime if checktype == :timestamp checktype = :ctime if checktype == :time self.should = checktype = :md5 if @resource.property(:source) file ||= @resource[:path] return nil unless FileTest.exist?(file) if ! FileTest.file?(file) checktype = :mtime end method = checktype.to_s + "_file" self.fail("Invalid checksum type %s" % checktype) unless respond_to?(method) return "{%s}%s" % [checktype, send(method, file)] end # At this point, we don't actually modify the system, we modify # the stored state to reflect the current state, and then kick # off an event to mark any changes. def handlesum currentvalue = self.retrieve if currentvalue.nil? raise Puppet::Error, "Checksum state for %s is somehow nil" % @resource.title end if self.insync?(currentvalue) self.debug "Checksum is already in sync" return nil end # If we still can't retrieve a checksum, it means that # the file still doesn't exist if currentvalue == :absent # if they're copying, then we won't worry about the file # not existing yet unless @resource.property(:source) self.warning("File %s does not exist -- cannot checksum" % @resource[:path]) end return nil end # If the sums are different, then return an event. if self.updatesum(currentvalue) return :file_changed else return nil end end def insync?(currentvalue) @should = [checktype()] if cache(checktype()) return currentvalue == currentsum() else # If there's no cached sum, then we don't want to generate # an event. return true end end # Even though they can specify multiple checksums, the insync? # mechanism can really only test against one, so we'll just retrieve # the first specified sum type. def retrieve(usecache = false) # When the 'source' is retrieving, it passes "true" here so # that we aren't reading the file twice in quick succession, yo. currentvalue = currentsum() return currentvalue if usecache and currentvalue stat = nil return :absent unless stat = @resource.stat if stat.ftype == "link" and @resource[:links] != :follow self.debug "Not checksumming symlink" # @resource.delete(:checksum) return currentvalue end # Just use the first allowed check type currentvalue = getsum(checktype()) # If there is no sum defined, then store the current value # into the cache, so that we're not marked as being # out of sync. We don't want to generate an event the first # time we get a sum. self.updatesum(currentvalue) unless cache(checktype()) # @resource.debug "checksum state is %s" % self.is return currentvalue end # Store the new sum to the state db. def updatesum(newvalue) - return unless resource.catalog.host_config? + return unless c = resource.catalog and c.host_config? result = false # if we're replacing, vs. updating if sum = cache(checktype()) return false if newvalue == sum self.debug "Replacing %s checksum %s with %s" % [@resource.title, sum, newvalue] result = true else @resource.debug "Creating checksum %s" % newvalue result = false end # Cache the sum so the log message can be right if possible. @cached = sum cache(checktype(), newvalue) return result end end diff --git a/test/executables/filebucket.rb b/test/executables/filebucket.rb deleted file mode 100755 index 491630707..000000000 --- a/test/executables/filebucket.rb +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../lib/puppettest' - -require 'puppet' -require 'puppet/network/client' -require 'puppettest' -require 'socket' -require 'facter' - -class TestFileBucketExe < Test::Unit::TestCase - include PuppetTest::ExeTest - - def test_local - bucket = tempfile - file = tempfile - text = "somet ext" - md5 = Digest::MD5.hexdigest(text) - File.open(file, "w") { |f| f.print text } - out = %x{filebucket --bucket #{bucket} backup #{file}} - - outfile, outmd5 = out.chomp.split(": ") - - assert_equal(0, $?, "filebucket did not run successfully") - - assert_equal(file, outfile, "did not output correct file name") - assert_equal(md5, outmd5, "did not output correct md5 sum") - - dipper = Puppet::Network::Client.dipper.new(:Path => bucket) - - newtext = nil - assert_nothing_raised("Could not get file from bucket") do - newtext = dipper.getfile(md5) - end - - assert_equal(text, newtext, "did not get correct file from md5 sum") - - out = %x{filebucket --bucket #{bucket} get #{md5}} - assert_equal(0, $?, "filebucket did not run successfully") - assert_equal(text, out, "did not get correct text back from filebucket") - - File.open(file, "w") { |f| f.puts "some other txt" } - out = %x{filebucket --bucket #{bucket} restore #{file} #{md5}} - assert_equal(0, $?, "filebucket did not run successfully") - assert_equal(text, File.read(file), "file was not restored") - end -end - diff --git a/test/executables/puppetbin.rb b/test/executables/puppetbin.rb deleted file mode 100755 index 08329efb6..000000000 --- a/test/executables/puppetbin.rb +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../lib/puppettest' - -require 'puppettest' - -class TestPuppetBin < Test::Unit::TestCase - include PuppetTest::ExeTest - def test_version - output = nil - assert_nothing_raised { - output = %x{puppet --version}.chomp - } - assert_equal(Puppet.version, output) - end - - def test_execution - file = mktestmanifest() - - output = nil - cmd = "puppet" - if Puppet[:debug] - cmd += " --debug" - end - cmd += " --confdir %s" % Puppet[:confdir] - cmd += " --vardir %s" % Puppet[:vardir] - unless Puppet[:debug] - cmd += " --logdest %s" % "/dev/null" - end - - assert_nothing_raised { - output = %x{#{cmd + " " + file} 2>&1} - } - assert($? == 0, "Puppet exited with code %s" % $?.to_i) - - assert(FileTest.exists?(@createdfile), "Failed to create config'ed file") - end - - def test_inlineexecution - path = tempfile() - code = "file { '#{path}': ensure => file }" - - output = nil - cmd = "puppet" - if Puppet[:debug] - cmd += " --debug" - end - #cmd += " --fqdn %s" % fqdn - cmd += " --confdir %s" % Puppet[:confdir] - cmd += " --vardir %s" % Puppet[:vardir] - unless Puppet[:debug] - cmd += " --logdest %s" % "/dev/null" - end - - cmd += " -e \"#{code}\"" - - assert_nothing_raised { - out = %x{#{cmd} 2>&1} - } - assert($? == 0, "Puppet exited with code %s" % $?.to_i) - - assert(FileTest.exists?(path), "Failed to create config'ed file") - end - - def test_stdin_execution - path = tempfile() - manifest = tempfile() - env = %x{which env}.chomp - if env == "" - Puppet.info "cannot find env; cannot test stdin_execution" - return - end - File.open(manifest, "w") do |f| - f.puts "#!#{env} puppet - file { '#{path}': ensure => file }" - end - File.chmod(0755, manifest) - - assert_nothing_raised { - out = %x{#{manifest} 2>&1} - } - assert($? == 0, "manifest exited with code %s" % $?.to_i) - - assert(FileTest.exists?(path), "Failed to create config'ed file") - end - - def test_parseonly - path = tempfile() - manifest = tempfile() - puppet = %x{which puppet}.chomp - if puppet == "" - Puppet.info "cannot find puppet; cannot test parseonly" - return - end - code = 'File <<| |>> - include nosuchclass' - - assert_nothing_raised { - IO.popen("#{puppet} --parseonly", 'w') { |p| p.puts code } - } - assert($? == 0, "parseonly test exited with code %s" % $?.to_i) - end -end - diff --git a/test/executables/puppetd.rb b/test/executables/puppetd.rb deleted file mode 100755 index d770ff91e..000000000 --- a/test/executables/puppetd.rb +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../lib/puppettest' - -require 'puppet' -require 'puppet/network/client' -require 'puppettest' -require 'socket' -require 'facter' - -class TestPuppetDExe < Test::Unit::TestCase - include PuppetTest::ExeTest - def setup - super - Puppet[:certdnsnames] = "localhost" - # start the master - @manifest = startmasterd - - - @cmd = "puppetd" - @cmd += " --verbose" - @cmd += " --test" - @cmd += " --masterport %s" % @@port - @cmd += " --confdir %s" % Puppet[:confdir] - @cmd += " --rundir %s" % File.join(Puppet[:vardir], "run") - @cmd += " --vardir %s" % Puppet[:vardir] - @cmd += " --server localhost" - end - - def test_normalstart - # and verify our daemon runs - output = nil - assert_nothing_raised { - output = %x{#{@cmd} 2>&1} - } - sleep 1 - assert($? == 0, "Puppetd exited with code %s" % $?) - - assert(FileTest.exists?(@createdfile), "Failed to create file %s" % @createdfile) - end - - # now verify that --noop works - def test_noop_start - @cmd += " --noop" - assert_nothing_raised { - output = %x{#{@cmd}}.chomp - } - sleep 1 - assert($? == 0, "Puppetd exited with code %s" % $?) - - assert(! FileTest.exists?(@createdfile), - "Noop created config'ed file") - end -end - diff --git a/test/network/client/resource.rb b/test/network/client/resource.rb index 86c6ccd2f..3ad9282bb 100755 --- a/test/network/client/resource.rb +++ b/test/network/client/resource.rb @@ -1,86 +1,64 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../lib/puppettest' require 'puppettest' require 'puppettest/support/utils' require 'puppettest/support/assertions' require 'puppet/network/client/resource' class TestResourceClient < Test::Unit::TestCase include PuppetTest::ServerTest include PuppetTest::Support::Utils + def setup + super + + Puppet::Type.type(:user).provider(:directoryservice).stubs(:get_macosx_version_major).returns "10.5" + end + def mkresourceserver Puppet::Network::Handler.resource.new end def mkclient client = Puppet::Network::Client.resource.new(:Resource => mkresourceserver) end def test_resources file = tempfile() text = "yayness\n" File.open(file, "w") { |f| f.print text } mkresourceserver() client = mkclient() # Test describing tresource = nil assert_nothing_raised { tresource = client.describe("file", file) } assert(tresource, "Did not get response") assert_instance_of(Puppet::TransObject, tresource) resource = nil assert_nothing_raised { resource = tresource.to_ral } assert_events([], resource) - p resource.instance_variable_get("@stat") File.unlink(file) assert_events([:file_created], resource) File.unlink(file) # Now test applying result = nil assert_nothing_raised { result = client.apply(tresource) } assert(FileTest.exists?(file), "File was not created on apply") - - # Lastly, test "list" - list = nil - assert_nothing_raised { - list = client.list("user") - } - - assert_instance_of(Puppet::TransBucket, list) - - count = 0 - list.each do |tresource| - break if count > 3 - assert_instance_of(Puppet::TransObject, tresource) - - tresource2 = nil - assert_nothing_raised { - tresource2 = client.describe(tresource.type, tresource.name) - } - - resource = nil - assert_nothing_raised { - resource = tresource2.to_ral - } - assert_events([], resource) - - count += 1 - end end end diff --git a/test/puppet/conffiles.rb b/test/puppet/conffiles.rb deleted file mode 100755 index 750570d23..000000000 --- a/test/puppet/conffiles.rb +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../lib/puppettest' - -require 'puppettest' - -class TestConfFiles < Test::Unit::TestCase - include PuppetTest - - @@gooddata = [ - { - "fun" => { - "a" => "b", - "c" => "d", - "e" => "f" - }, - "yay" => { - "aa" => "bk", - "ca" => "dk", - "ea" => "fk" - }, - "boo" => { - "eb" => "fb" - }, - }, - { - "puppet" => { - "yay" => "rah" - }, - "booh" => { - "okay" => "rah" - }, - "back" => { - "yayness" => "rah" - }, - } - ] - - def data2config(data) - str = "" - - if data.include?("puppet") - # because we're modifying it - data = data.dup - str += "[puppet]\n" - data["puppet"].each { |var, value| - str += "%s = %s\n" % [var, value] - } - data.delete("puppet") - end - - data.each { |type, settings| - str += "[%s]\n" % type - settings.each { |var, value| - str += "%s = %s\n" % [var, value] - } - } - - return str - end - - def sampledata - if block_given? - @@gooddata.each { |hash| yield hash } - else - return @@gooddata[0] - end - end - - def test_readconfig - path = tempfile() - - sampledata { |data| - config = Puppet::Util::Settings.new - data.each { |section, hash| - hash.each { |param, value| - config.setdefaults(section, param => [value, value]) - } - } - # Write it out as a config file - File.open(path, "w") { |f| f.print data2config(data) } - assert_nothing_raised { - config.parse(path) - } - - data.each { |section, hash| - hash.each { |var, value| - assert_equal( - data[section][var], - config[var], - "Got different values at %s/%s" % [section, var] - ) - } - } - } - end - - # Make sure that basic config generation works; this also ensures - # that the default config is free of simple typos etc. - def test_genconfig - assert_nothing_raised { - Puppet::settings::to_config - } - end - -end - diff --git a/test/ral/type/file.rb b/test/ral/type/file.rb index ec81c61a1..1a7813b74 100755 --- a/test/ral/type/file.rb +++ b/test/ral/type/file.rb @@ -1,1198 +1,1173 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../lib/puppettest' require 'puppettest' require 'puppettest/support/utils' require 'fileutils' class TestFile < Test::Unit::TestCase include PuppetTest::Support::Utils include PuppetTest::FileTesting def mkfile(hash) file = nil assert_nothing_raised { file = Puppet::Type.type(:file).new(hash) } return file end def mktestfile tmpfile = tempfile() File.open(tmpfile, "w") { |f| f.puts rand(100) } @@tmpfiles.push tmpfile mkfile(:name => tmpfile) end def setup super @file = Puppet::Type.type(:file) $method = @method_name Puppet[:filetimeout] = -1 Facter.stubs(:to_hash).returns({}) end def teardown system("rm -rf %s" % Puppet[:statefile]) super end def initstorage Puppet::Util::Storage.init Puppet::Util::Storage.load end def clearstorage Puppet::Util::Storage.store Puppet::Util::Storage.clear end def test_owner file = mktestfile() users = {} count = 0 # collect five users Etc.passwd { |passwd| if count > 5 break else count += 1 end users[passwd.uid] = passwd.name } fake = {} # find a fake user while true a = rand(1000) begin Etc.getpwuid(a) rescue fake[a] = "fakeuser" break end end uid, name = users.shift us = {} us[uid] = name users.each { |uid, name| assert_apply(file) assert_nothing_raised() { file[:owner] = name } assert_nothing_raised() { file.retrieve } assert_apply(file) } end def test_group file = mktestfile() [%x{groups}.chomp.split(/ /), Process.groups].flatten.each { |group| assert_nothing_raised() { file[:group] = group } assert(file.property(:group)) assert(file.property(:group).should) } end def test_groups_fails_when_invalid assert_raise(Puppet::Error, "did not fail when the group was empty") do Puppet::Type.type(:file).new :path => "/some/file", :group => "" end end if Puppet::Util::SUIDManager.uid == 0 def test_createasuser dir = tmpdir() user = nonrootuser() path = File.join(tmpdir, "createusertesting") @@tmpfiles << path file = nil assert_nothing_raised { file = Puppet::Type.type(:file).new( :path => path, :owner => user.name, :ensure => "file", :mode => "755" ) } comp = mk_catalog("createusertest", file) assert_events([:file_created], comp) end def test_nofollowlinks basedir = tempfile() Dir.mkdir(basedir) file = File.join(basedir, "file") link = File.join(basedir, "link") File.open(file, "w", 0644) { |f| f.puts "yayness"; f.flush } File.symlink(file, link) # First test 'user' user = nonrootuser() inituser = File.lstat(link).uid File.lchown(inituser, nil, link) obj = nil assert_nothing_raised { obj = Puppet::Type.type(:file).new( :title => link, :owner => user.name ) } obj.retrieve # Make sure it defaults to managing the link assert_events([:file_changed], obj) assert_equal(user.uid, File.lstat(link).uid) assert_equal(inituser, File.stat(file).uid) File.chown(inituser, nil, file) File.lchown(inituser, nil, link) # Try following obj[:links] = :follow assert_events([:file_changed], obj) assert_equal(user.uid, File.stat(file).uid) assert_equal(inituser, File.lstat(link).uid) # And then explicitly managing File.chown(inituser, nil, file) File.lchown(inituser, nil, link) obj[:links] = :manage assert_events([:file_changed], obj) assert_equal(user.uid, File.lstat(link).uid) assert_equal(inituser, File.stat(file).uid) obj.delete(:owner) obj[:links] = :follow # And then test 'group' group = nonrootgroup initgroup = File.stat(file).gid obj[:group] = group.name obj[:links] = :follow assert_events([:file_changed], obj) assert_equal(group.gid, File.stat(file).gid) File.chown(nil, initgroup, file) File.lchown(nil, initgroup, link) obj[:links] = :manage assert_events([:file_changed], obj) assert_equal(group.gid, File.lstat(link).gid) assert_equal(initgroup, File.stat(file).gid) end def test_ownerasroot file = mktestfile() users = {} count = 0 # collect five users Etc.passwd { |passwd| if count > 5 break else count += 1 end next if passwd.uid < 0 users[passwd.uid] = passwd.name } fake = {} # find a fake user while true a = rand(1000) begin Etc.getpwuid(a) rescue fake[a] = "fakeuser" break end end users.each { |uid, name| assert_nothing_raised() { file[:owner] = name } changes = [] assert_nothing_raised() { changes << file.evaluate } assert(changes.length > 0) assert_apply(file) currentvalue = file.retrieve assert(file.insync?(currentvalue)) assert_nothing_raised() { file[:owner] = uid } assert_apply(file) currentvalue = file.retrieve # make sure changing to number doesn't cause a sync assert(file.insync?(currentvalue)) } # We no longer raise an error here, because we check at run time #fake.each { |uid, name| # assert_raise(Puppet::Error) { # file[:owner] = name # } # assert_raise(Puppet::Error) { # file[:owner] = uid # } #} end def test_groupasroot file = mktestfile() [%x{groups}.chomp.split(/ /), Process.groups].flatten.each { |group| next unless Puppet::Util.gid(group) # grr. assert_nothing_raised() { file[:group] = group } assert(file.property(:group)) assert(file.property(:group).should) assert_apply(file) currentvalue = file.retrieve assert(file.insync?(currentvalue)) assert_nothing_raised() { file.delete(:group) } } end if Facter.value(:operatingsystem) == "Darwin" def test_sillyowner file = tempfile() File.open(file, "w") { |f| f.puts "" } File.chown(-2, nil, file) assert(File.stat(file).uid > 120000, "eh?") user = nonrootuser obj = Puppet::Type.newfile( :path => file, :owner => user.name ) assert_apply(obj) assert_equal(user.uid, File.stat(file).uid) end end else $stderr.puts "Run as root for complete owner and group testing" end def test_create %w{a b c d}.collect { |name| tempfile() + name.to_s }.each { |path| file =nil assert_nothing_raised() { file = Puppet::Type.type(:file).new( :name => path, :ensure => "file" ) } assert_events([:file_created], file) assert_events([], file) assert(FileTest.file?(path), "File does not exist") assert(file.insync?(file.retrieve)) @@tmpfiles.push path } end def test_create_dir basedir = tempfile() Dir.mkdir(basedir) %w{a b c d}.collect { |name| "#{basedir}/%s" % name }.each { |path| file = nil assert_nothing_raised() { file = Puppet::Type.type(:file).new( :name => path, :ensure => "directory" ) } assert(! FileTest.directory?(path), "Directory %s already exists" % [path]) assert_events([:directory_created], file) assert_events([], file) assert(file.insync?(file.retrieve)) assert(FileTest.directory?(path)) @@tmpfiles.push path } end def test_modes file = mktestfile # Set it to something else initially File.chmod(0775, file.title) [0644,0755,0777,0641].each { |mode| assert_nothing_raised() { file[:mode] = mode } assert_events([:file_changed], file) assert_events([], file) assert(file.insync?(file.retrieve)) assert_nothing_raised() { file.delete(:mode) } } end def cyclefile(path) # i had problems with using :name instead of :path [:name,:path].each { |param| file = nil changes = nil comp = nil trans = nil initstorage assert_nothing_raised { file = Puppet::Type.type(:file).new( param => path, :recurse => true, :checksum => "md5" ) } comp = Puppet::Type.type(:component).new( :name => "component" ) comp.push file assert_nothing_raised { trans = comp.evaluate } assert_nothing_raised { trans.evaluate } clearstorage Puppet::Type.allclear } end def test_recurse? file = Puppet::Type.type(:file).new :path => tempfile # Make sure we default to false assert(! file.recurse?, "Recurse defaulted to true") [true, "true", 10, "inf"].each do |value| file[:recurse] = value assert(file.recurse?, "%s did not cause recursion" % value) end [false, "false", 0].each do |value| file[:recurse] = value assert(! file.recurse?, "%s caused recursion" % value) end end def test_recursion basedir = tempfile() subdir = File.join(basedir, "subdir") tmpfile = File.join(basedir,"testing") FileUtils.mkdir_p(subdir) dir = nil [true, "true", "inf", 50].each do |value| assert_nothing_raised { dir = Puppet::Type.type(:file).new( :path => basedir, :recurse => value, :check => %w{owner mode group} ) } config = mk_catalog dir transaction = Puppet::Transaction.new(config) children = nil assert_nothing_raised { children = transaction.eval_generate(dir) } assert_equal([subdir], children.collect {|c| c.title }, "Incorrect generated children") # Remove our subdir resource, subdir_resource = config.resource(:file, subdir) config.remove_resource(subdir_resource) # Create the test file File.open(tmpfile, "w") { |f| f.puts "yayness" } assert_nothing_raised { children = transaction.eval_generate(dir) } # And make sure we get both resources back. assert_equal([subdir, tmpfile].sort, children.collect {|c| c.title }.sort, "Incorrect generated children when recurse == %s" % value.inspect) File.unlink(tmpfile) end end def test_filetype_retrieval file = nil # Verify it retrieves files of type directory assert_nothing_raised { file = Puppet::Type.type(:file).new( :name => tmpdir(), :check => :type ) } assert_nothing_raised { file.evaluate } assert_equal("directory", file.property(:type).retrieve) # And then check files assert_nothing_raised { file = Puppet::Type.type(:file).new( :name => tempfile(), :ensure => "file" ) } assert_apply(file) file[:check] = "type" assert_apply(file) assert_equal("file", file.property(:type).retrieve) file[:type] = "directory" currentvalues = {} assert_nothing_raised { currentvalues = file.retrieve } # The 'retrieve' method sets @should to @is, so they're never # out of sync. It's a read-only class. assert(file.insync?(currentvalues)) end def test_path dir = tempfile() path = File.join(dir, "subdir") assert_nothing_raised("Could not make file") { FileUtils.mkdir_p(File.dirname(path)) File.open(path, "w") { |f| f.puts "yayness" } } file = nil dirobj = nil assert_nothing_raised("Could not make file object") { dirobj = Puppet::Type.type(:file).new( :path => dir, :recurse => true, :check => %w{mode owner group} ) } catalog = mk_catalog dirobj transaction = Puppet::Transaction.new(catalog) transaction.eval_generate(dirobj) #assert_nothing_raised { # dirobj.eval_generate #} file = catalog.resource(:file, path) assert(file, "Could not retrieve file object") assert_equal("/%s" % file.ref, file.path) end def test_autorequire basedir = tempfile() subfile = File.join(basedir, "subfile") baseobj = Puppet::Type.type(:file).new( :name => basedir, :ensure => "directory" ) subobj = Puppet::Type.type(:file).new( :name => subfile, :ensure => "file" ) catalog = mk_catalog(baseobj, subobj) edge = nil assert_nothing_raised do edge = subobj.autorequire.shift end assert_equal(baseobj, edge.source, "file did not require its parent dir") assert_equal(subobj, edge.target, "file did not require its parent dir") end # Unfortunately, I know this fails def disabled_test_recursivemkdir path = tempfile() subpath = File.join(path, "this", "is", "a", "dir") file = nil assert_nothing_raised { file = Puppet::Type.type(:file).new( :name => subpath, :ensure => "directory", :recurse => true ) } comp = mk_catalog("yay", file) comp.finalize assert_apply(comp) #assert_events([:directory_created], comp) assert(FileTest.directory?(subpath), "Did not create directory") end # Make sure that content updates the checksum on the same run def test_checksumchange_for_content dest = tempfile() File.open(dest, "w") { |f| f.puts "yayness" } file = nil assert_nothing_raised { file = Puppet::Type.type(:file).new( :name => dest, :checksum => "md5", :content => "This is some content" ) } file.retrieve assert_events([:file_changed], file) file.retrieve assert_events([], file) end # Make sure that content updates the checksum on the same run def test_checksumchange_for_ensure dest = tempfile() file = nil assert_nothing_raised { file = Puppet::Type.type(:file).new( :name => dest, :checksum => "md5", :ensure => "file" ) } file.retrieve assert_events([:file_created], file) file.retrieve assert_events([], file) end def test_nameandpath path = tempfile() file = nil assert_nothing_raised { file = Puppet::Type.type(:file).new( :title => "fileness", :path => path, :content => "this is some content" ) } assert_apply(file) assert(FileTest.exists?(path)) end # Make sure that a missing group isn't fatal at object instantiation time. def test_missinggroup file = nil assert_nothing_raised { file = Puppet::Type.type(:file).new( :path => tempfile(), :group => "fakegroup" ) } assert(file.property(:group), "Group property failed") end def test_modecreation path = tempfile() file = Puppet::Type.type(:file).new( :path => path, :ensure => "file", :mode => "0777" ) assert_equal(0777, file.should(:mode), "Mode did not get set correctly") assert_apply(file) assert_equal(0777, File.stat(path).mode & 007777, "file mode is incorrect") File.unlink(path) file[:ensure] = "directory" assert_apply(file) assert_equal(0777, File.stat(path).mode & 007777, "directory mode is incorrect") end # If both 'ensure' and 'content' are used, make sure that all of the other # properties are handled correctly. def test_contentwithmode path = tempfile() file = nil assert_nothing_raised { file = Puppet::Type.type(:file).new( :path => path, :ensure => "file", :content => "some text\n", :mode => 0755 ) } assert_apply(file) assert_equal("%o" % 0755, "%o" % (File.stat(path).mode & 007777)) end def test_backupmodes File.umask(0022) file = tempfile() newfile = tempfile() File.open(file, "w", 0411) { |f| f.puts "yayness" } obj = Puppet::Type.type(:file).new( :path => file, :content => "rahness\n", :backup => ".puppet-bak" ) catalog = mk_catalog(obj) catalog.apply backupfile = file + obj[:backup] @@tmpfiles << backupfile assert(FileTest.exists?(backupfile), "Backup file %s does not exist" % backupfile) assert_equal(0411, filemode(backupfile), "File mode is wrong for backupfile") name = "bucket" bpath = tempfile() Dir.mkdir(bpath) bucket = Puppet::Type.type(:filebucket).new(:title => name, :path => bpath) catalog.add_resource(bucket) obj[:backup] = name obj[:content] = "New content" catalog.finalize catalog.apply md5 = "18cc17fa3047fcc691fdf49c0a7f539a" dir, file, pathfile = Puppet::Network::Handler.filebucket.paths(bpath, md5) assert_equal(0440, filemode(file)) end - def test_largefilechanges - source = tempfile() - dest = tempfile() - - # Now make a large file - File.open(source, "w") { |f| - 500.times { |i| f.puts "line %s" % i } - } - - resource = Puppet::Type.type(:file).new( - :title => dest, :source => source - ) - - assert_events([:file_created], resource) - - File.open(source, File::APPEND|File::WRONLY) { |f| f.puts "another line" } - - assert_events([:file_changed], resource) - - # Now modify the dest file - File.open(dest, File::APPEND|File::WRONLY) { |f| f.puts "one more line" } - - assert_events([:file_changed, :file_changed], resource) - end - def test_replacefilewithlink path = tempfile() link = tempfile() File.open(path, "w") { |f| f.puts "yay" } File.open(link, "w") { |f| f.puts "a file" } file = nil assert_nothing_raised { file = Puppet::Type.type(:file).new( :ensure => path, :path => link ) } assert_events([:link_created], file) assert(FileTest.symlink?(link), "Link was not created") assert_equal(path, File.readlink(link), "Link was created incorrectly") end def test_file_with_spaces dir = tempfile() Dir.mkdir(dir) source = File.join(dir, "file spaces") dest = File.join(dir, "another space") File.open(source, "w") { |f| f.puts :yay } obj = Puppet::Type.type(:file).new( :path => dest, :source => source ) assert(obj, "Did not create file") assert_apply(obj) assert(FileTest.exists?(dest), "File did not get created") end # Testing #274. Make sure target can be used without 'ensure'. def test_target_without_ensure source = tempfile() dest = tempfile() File.open(source, "w") { |f| f.puts "funtest" } obj = nil assert_nothing_raised { obj = Puppet::Type.newfile(:path => dest, :target => source) } assert_apply(obj) end def test_autorequire_owner_and_group file = tempfile() comp = nil user = nil group =nil home = nil ogroup = nil assert_nothing_raised { user = Puppet::Type.type(:user).new( :name => "pptestu", :home => file, :gid => "pptestg" ) home = Puppet::Type.type(:file).new( :path => file, :owner => "pptestu", :group => "pptestg", :ensure => "directory" ) group = Puppet::Type.type(:group).new( :name => "pptestg" ) comp = mk_catalog(user, group, home) } # Now make sure we get a relationship for each of these rels = nil assert_nothing_raised { rels = home.autorequire } assert(rels.detect { |e| e.source == user }, "owner was not autorequired") assert(rels.detect { |e| e.source == group }, "group was not autorequired") end # Testing #309 -- //my/file => /my/file def test_slash_deduplication ["/my/////file/for//testing", "//my/file/for/testing///", "/my/file/for/testing"].each do |path| file = nil assert_nothing_raised do file = Puppet::Type.newfile(:path => path) end assert_equal("/my/file/for/testing", file.title) end end # Testing #304 def test_links_to_directories link = tempfile() file = tempfile() dir = tempfile() Dir.mkdir(dir) bucket = Puppet::Type.type(:filebucket).new :name => "main" File.symlink(dir, link) File.open(file, "w") { |f| f.puts "" } assert_equal(dir, File.readlink(link)) obj = Puppet::Type.newfile :path => link, :ensure => :link, :target => file, :recurse => false, :backup => "main" catalog = mk_catalog(bucket, obj) catalog.apply assert_equal(file, File.readlink(link)) end # Testing #303 def test_nobackups_with_links link = tempfile() new = tempfile() File.open(link, "w") { |f| f.puts "old" } File.open(new, "w") { |f| f.puts "new" } obj = Puppet::Type.newfile :path => link, :ensure => :link, :target => new, :recurse => true, :backup => false assert_nothing_raised do obj.handlebackup end bfile = [link, "puppet-bak"].join(".") assert(! FileTest.exists?(bfile), "Backed up when told not to") assert_apply(obj) assert(! FileTest.exists?(bfile), "Backed up when told not to") end # Make sure we consistently handle backups for all cases. def test_ensure_with_backups # We've got three file types, so make sure we can replace any type # with the other type and that backups are done correctly. types = [:file, :directory, :link] dir = tempfile() path = File.join(dir, "test") linkdest = tempfile() creators = { :file => proc { File.open(path, "w") { |f| f.puts "initial" } }, :directory => proc { Dir.mkdir(path) }, :link => proc { File.symlink(linkdest, path) } } bucket = Puppet::Type.type(:filebucket).new :name => "main", :path => tempfile() obj = Puppet::Type.newfile :path => path, :force => true, :links => :manage catalog = mk_catalog(obj, bucket) Puppet[:trace] = true ["main", false].each do |backup| obj[:backup] = backup obj.finish types.each do |should| types.each do |is| # It makes no sense to replace a directory with a directory # next if should == :directory and is == :directory Dir.mkdir(dir) # Make the thing creators[is].call obj[:ensure] = should if should == :link obj[:target] = linkdest else if obj.property(:target) obj.delete(:target) end end # First try just removing the initial data assert_nothing_raised do obj.remove_existing(should) end unless is == should # Make sure the original is gone assert(! FileTest.exists?(obj[:path]), "remove_existing did not work: " + "did not remove %s with %s" % [is, should]) end FileUtils.rmtree(obj[:path]) # Now make it again creators[is].call property = obj.property(:ensure) currentvalue = property.retrieve unless property.insync?(currentvalue) assert_nothing_raised do property.sync end end FileUtils.rmtree(dir) end end end end if Process.uid == 0 # Testing #364. def test_writing_in_directories_with_no_write_access # Make a directory that our user does not have access to dir = tempfile() Dir.mkdir(dir) # Get a fake user user = nonrootuser # and group group = nonrootgroup # First try putting a file in there path = File.join(dir, "file") file = Puppet::Type.newfile :path => path, :owner => user.name, :group => group.name, :content => "testing" # Make sure we can create it assert_apply(file) assert(FileTest.exists?(path), "File did not get created") # And that it's owned correctly assert_equal(user.uid, File.stat(path).uid, "File has the wrong owner") assert_equal(group.gid, File.stat(path).gid, "File has the wrong group") assert_equal("testing", File.read(path), "file has the wrong content") # Now make a dir subpath = File.join(dir, "subdir") subdir = Puppet::Type.newfile :path => subpath, :owner => user.name, :group => group.name, :ensure => :directory # Make sure we can create it assert_apply(subdir) assert(FileTest.directory?(subpath), "File did not get created") # And that it's owned correctly assert_equal(user.uid, File.stat(subpath).uid, "File has the wrong owner") assert_equal(group.gid, File.stat(subpath).gid, "File has the wrong group") assert_equal("testing", File.read(path), "file has the wrong content") end end # #366 def test_replace_aliases file = Puppet::Type.newfile :path => tempfile() file[:replace] = :yes assert_equal(:true, file[:replace], ":replace did not alias :true to :yes") file[:replace] = :no assert_equal(:false, file[:replace], ":replace did not alias :false to :no") end def test_backup path = tempfile() file = Puppet::Type.newfile :path => path, :content => "yay" catalog = mk_catalog(file) catalog.finalize # adds the default resources. [false, :false, "false"].each do |val| assert_nothing_raised do file[:backup] = val end assert_equal(false, file[:backup], "%s did not translate" % val.inspect) end [true, :true, "true", ".puppet-bak"].each do |val| assert_nothing_raised do file[:backup] = val end assert_equal(".puppet-bak", file[:backup], "%s did not translate" % val.inspect) end # Now try a non-bucket string assert_nothing_raised do file[:backup] = ".bak" end assert_equal(".bak", file[:backup], ".bak did not translate") # Now try a non-existent bucket assert_nothing_raised do file[:backup] = "main" end assert_equal("main", file[:backup], "bucket name was not retained") assert_equal("main", file.bucket, "file's bucket was not set") # And then an existing bucket obj = Puppet::Type.type(:filebucket).new :name => "testing" catalog.add_resource(obj) bucket = obj.bucket assert_nothing_raised do file[:backup] = "testing" end assert_equal("testing", file[:backup], "backup value was reset") assert_equal(obj.bucket, file.bucket, "file's bucket was not set") end def test_pathbuilder dir = tempfile() Dir.mkdir(dir) file = File.join(dir, "file") File.open(file, "w") { |f| f.puts "" } obj = Puppet::Type.newfile :path => dir, :recurse => true, :mode => 0755 catalog = mk_catalog obj transaction = Puppet::Transaction.new(catalog) assert_equal("/%s" % obj.ref, obj.path) list = transaction.eval_generate(obj) fileobj = catalog.resource(:file, file) assert(fileobj, "did not generate file object") assert_equal("/%s" % fileobj.ref, fileobj.path, "did not generate correct subfile path") end # Testing #403 def test_removal_with_content_set path = tempfile() File.open(path, "w") { |f| f.puts "yay" } file = Puppet::Type.newfile(:name => path, :ensure => :absent, :content => "foo") assert_apply(file) assert(! FileTest.exists?(path), "File was not removed") end # Testing #438 def test_creating_properties_conflict file = tempfile() first = tempfile() second = tempfile() params = [:content, :source, :target] params.each do |param| assert_nothing_raised("%s conflicted with ensure" % [param]) do Puppet::Type.newfile(:path => file, param => first, :ensure => :file) end params.each do |other| next if other == param assert_raise(Puppet::Error, "%s and %s did not conflict" % [param, other]) do Puppet::Type.newfile(:path => file, other => first, param => second) end end end end # Testing #508 if Process.uid == 0 def test_files_replace_with_right_attrs source = tempfile() File.open(source, "w") { |f| f.puts "some text" } File.chmod(0755, source) user = nonrootuser group = nonrootgroup path = tempfile() good = {:uid => user.uid, :gid => group.gid, :mode => 0640} run = Proc.new do |obj, msg| assert_apply(obj) stat = File.stat(obj[:path]) good.each do |should, sval| if should == :mode current = filemode(obj[:path]) else current = stat.send(should) end assert_equal(sval, current, "Attr %s was not correct %s" % [should, msg]) end end file = Puppet::Type.newfile(:path => path, :owner => user.name, :group => group.name, :mode => 0640, :backup => false) {:source => source, :content => "some content"}.each do |attr, value| file[attr] = value # First create the file run.call(file, "upon creation with %s" % attr) # Now change something so that we replace the file case attr when :source: File.open(source, "w") { |f| f.puts "some different text" } when :content: file[:content] = "something completely different" else raise "invalid attr %s" % attr end # Run it again run.call(file, "after modification with %s" % attr) # Now remove the file and the attr file.delete(attr) File.unlink(path) end end end # Make sure we default to the "puppet" filebucket, rather than a string def test_backup_defaults_to_bucket path = tempfile file = Puppet::Type.newfile(:path => path, :content => 'some content') file.finish assert_instance_of(Puppet::Network::Client::Dipper, file.bucket, "did not default to a filebucket for backups") end # #567 def test_missing_files_are_in_sync file = tempfile obj = Puppet::Type.newfile(:path => file, :mode => 0755) changes = obj.evaluate assert(changes.empty?, "Missing file with no ensure resulted in changes") end def test_root_dir_is_named_correctly obj = Puppet::Type.newfile(:path => '/', :mode => 0755) assert_equal("/", obj.title, "/ directory was changed to empty string") end # #1010 and #1037 -- write should fail if the written checksum does not # match the file we thought we were writing. def test_write_validates_checksum file = tempfile inst = Puppet::Type.newfile(:path => file, :content => "something") tmpfile = file + ".puppettmp" wh = mock 'writehandle', :print => nil rh = mock 'readhandle' rh.expects(:read).with(512).times(2).returns("other").then.returns(nil) File.expects(:open).with { |*args| args[0] == tmpfile and args[1] != "r" }.yields(wh) File.expects(:open).with { |*args| args[0] == tmpfile and args[1] == "r" }.yields(rh) File.stubs(:rename) FileTest.stubs(:exist?).returns(true) FileTest.stubs(:file?).returns(true) inst.expects(:fail) inst.write("something", :whatever) end end diff --git a/test/util/settings.rb b/test/util/settings.rb index edd8e3e2c..f34cbbc46 100755 --- a/test/util/settings.rb +++ b/test/util/settings.rb @@ -1,939 +1,717 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../lib/puppettest' require 'mocha' require 'puppettest' require 'puppet/util/settings' require 'puppettest/parsertesting' class TestSettings < Test::Unit::TestCase include PuppetTest include PuppetTest::ParserTesting CElement = Puppet::Util::Settings::CElement CBoolean = Puppet::Util::Settings::CBoolean def setup super @config = mkconfig end def set_configs(config = nil) config ||= @config config.setdefaults("main", :one => ["a", "one"], :two => ["a", "two"], :yay => ["/default/path", "boo"], :mkusers => [true, "uh, yeah"], :name => ["testing", "a"] ) config.setdefaults("section1", :attr => ["a", "one"], :attrdir => ["/another/dir", "two"], :attr3 => ["$attrdir/maybe", "boo"] ) end def check_for_users count = Puppet::Type.type(:user).inject(0) { |c,o| c + 1 } assert(count > 0, "Found no users") end def test_to_config set_configs newc = mkconfig set_configs(newc) # Reset all of the values, so we know they're changing. newc.each do |name, obj| next if name == :name newc[name] = true end newfile = tempfile() File.open(newfile, "w") { |f| @config.to_config.split("\n").each do |line| # Uncomment the settings, so they actually take. if line =~ / = / f.puts line.sub(/^\s*#/, '') else f.puts line end end } + newc.setdefaults :section, :config => [newfile, "eh"] + assert_nothing_raised("Could not parse generated configuration") { - newc.parse(newfile) + newc.parse } @config.each do |name, object| assert_equal(@config[name], newc[name], "Parameter %s is not the same" % name) end end def mkconfig c = nil assert_nothing_raised { c = Puppet::Util::Settings.new } return c end def test_addbools assert_nothing_raised { @config.setdefaults(:testing, :booltest => [true, "testing"]) } assert(@config[:booltest]) @config = mkconfig assert_nothing_raised { @config.setdefaults(:testing, :booltest => ["true", "testing"]) } assert(@config[:booltest]) assert_nothing_raised { @config[:booltest] = false } assert(! @config[:booltest], "Booltest is not false") assert_nothing_raised { @config[:booltest] = "false" } assert(! @config[:booltest], "Booltest is not false") assert_raise(ArgumentError) { @config[:booltest] = "yayness" } assert_raise(ArgumentError) { @config[:booltest] = "/some/file" } end def test_strings val = "this is a string" assert_nothing_raised { @config.setdefaults(:testing, :strtest => [val, "testing"]) } assert_equal(val, @config[:strtest]) # Verify that variables are interpolated assert_nothing_raised { @config.setdefaults(:testing, :another => ["another $strtest", "testing"]) } assert_equal("another #{val}", @config[:another]) end def test_files c = mkconfig parent = "/puppet" assert_nothing_raised { @config.setdefaults(:testing, :parentdir => [parent, "booh"]) } assert_nothing_raised { @config.setdefaults(:testing, :child => ["$parent/child", "rah"]) } assert_equal(parent, @config[:parentdir]) assert_equal("/puppet/child", File.join(@config[:parentdir], "child")) end def test_getset initial = "an initial value" assert_raise(ArgumentError) { @config[:yayness] = initial } default = "this is a default" assert_nothing_raised { @config.setdefaults(:testing, :yayness => [default, "rah"]) } assert_equal(default, @config[:yayness]) assert_nothing_raised { @config[:yayness] = initial } assert_equal(initial, @config[:yayness]) assert_nothing_raised { @config.clear } assert_equal(default, @config[:yayness], "'clear' did not remove old values") assert_nothing_raised { @config[:yayness] = "not default" } assert_equal("not default", @config[:yayness]) end def test_parse_file text = %{ one = this is a test two = another test owner = root group = root yay = /a/path [main] four = five six = seven [section1] attr = value owner = puppet group = puppet attrdir = /some/dir attr3 = $attrdir/other } file = tempfile() File.open(file, "w") { |f| f.puts text } result = nil assert_nothing_raised { result = @config.send(:parse_file, file) } main = result[:main] assert(main, "Did not get section for main") { :one => "this is a test", :two => "another test", :owner => "root", :group => "root", :yay => "/a/path", :four => "five", :six => "seven" }.each do |param, value| assert_equal(value, main[param], "Param %s was not set correctly in main" % param) end section1 = result[:section1] assert(section1, "Did not get section1") { :attr => "value", :owner => "puppet", :group => "puppet", :attrdir => "/some/dir", :attr3 => "$attrdir/other" }.each do |param, value| assert_equal(value, section1[param], "Param %s was not set correctly in section1" % param) end end - def test_parse - result = { - :main => {:main => "main", :bad => "invalid", :cliparam => "reset"}, - :puppet => {:other => "puppet", :cliparam => "reset"}, - :puppetd => {:other => "puppetd", :cliparam => "reset"} - } - # Set our defaults, so they're valid. Don't define 'bad', since we want to test for failures. - @config.setdefaults(:main, - :main => ["whatever", "a"], - :cliparam => ["default", "y"], - :other => ["a", "b"], - :name => ["puppet", "b"] # our default name - ) - @config.setdefaults(:other, - :one => ["whatever", "a"], - :two => ["default", "y"], - :apple => ["a", "b"], - :shoe => ["puppet", "b"] # our default name - ) - @config.handlearg("--cliparam", "changed") - @config.stubs(:parse_file).returns(result) - - # First do it with our name being 'puppet' - assert_nothing_raised("Could not handle parse results") do - @config.parse(tempfile) - end - - assert_equal(:puppet, @config.name, "Did not get correct name") - assert_equal("main", @config[:main], "Did not get main value") - assert_equal("puppet", @config[:other], "Did not get name value") - assert_equal("changed", @config[:cliparam], "CLI values were overridden by config") - - # Now switch names and make sure the parsing switches, too. - @config.clear(true) - assert_nothing_raised("Could not handle parse results") do - @config.parse(tempfile) - end - @config[:name] = :puppetd - - assert_equal(:puppetd, @config.name, "Did not get correct name") - assert_equal("main", @config[:main], "Did not get main value") - assert_equal("puppetd", @config[:other], "Did not get name value") - assert_equal("changed", @config[:cliparam], "CLI values were overridden by config") - end - - # Make sure we can extract file options correctly. - def test_parsing_file_options - @config.setdefaults(:whev, - :file => { - :desc => "whev", - :default => "/default", - :owner => "me", - :group => "me", - :mode => "755" - } - ) - - file = tempfile - count = 0 - - { - :pass => { - " {owner = you}" => {:owner => "you"}, - " {owner = you, group = you}" => {:owner => "you", :group => "you"}, - " {owner = you, group = you, mode = 755}" => {:owner => "you", :group => "you", :mode => "755"}, - " { owner = you, group = you } " => {:owner => "you", :group => "you"}, - "{owner=you,group=you} " => {:owner => "you", :group => "you"}, - "{owner=you,} " => {:owner => "you"} - }, - :fail => [ - %{{owner = you group = you}}, - %{{owner => you, group => you}}, - %{{user => you}}, - %{{random => you}}, - %{{mode => you}}, # make sure modes are numbers - %{{owner => you}} - ] - }.each do |type, list| - count += 1 - list.each do |value| - if type == :pass - value, should = value[0], value[1] - end - path = "/other%s" % count - # Write our file out - File.open(file, "w") do |f| - f.puts %{[main]\nfile = #{path}#{value}} - end - - if type == :fail - assert_raise(ArgumentError, "Did not fail on %s" % value.inspect) do - @config.send(:parse_file, file) - end - else - result = nil - assert_nothing_raised("Failed to parse %s" % value.inspect) do - result = @config.send(:parse_file, file) - end - assert_equal(should, result[:main][:_meta][:file], "Got incorrect return for %s" % value.inspect) - assert_equal(path, result[:main][:file], "Got incorrect value for %s" % value.inspect) - end - end - end - end - - # Make sure file options returned from parse_file are handled correctly. - def test_parsed_file_options - @config.setdefaults(:whev, - :file => { - :desc => "whev", - :default => "/default", - :owner => "me", - :group => "me", - :mode => "755" - } - ) - - result = { - :main => { - :file => "/other", - :_meta => { - :file => { - :owner => "you", - :group => "you", - :mode => "644" - } - } - } - } - - @config.expects(:parse_file).returns(result) - - assert_nothing_raised("Could not handle file options") do - @config.parse("/whatever") - end - - # Get the actual object, so we can verify metadata - file = @config.element(:file) - - assert_equal("/other", @config[:file], "Did not get correct value") - assert_equal("you", file.owner, "Did not pass on user") - assert_equal("you", file.group, "Did not pass on group") - assert_equal("644", file.mode, "Did not pass on mode") - end - def test_arghandling c = mkconfig assert_nothing_raised { @config.setdefaults("testing", :onboolean => [true, "An on bool"], :offboolean => [false, "An off bool"], :string => ["a string", "A string arg"], :file => ["/path/to/file", "A file arg"] ) } data = { :onboolean => [true, false], :offboolean => [true, false], :string => ["one string", "another string"], :file => %w{/a/file /another/file} } data.each { |param, values| values.each { |val| opt = nil arg = nil if @config.boolean?(param) if val opt = "--%s" % param else opt = "--no-%s" % param end else opt = "--%s" % param arg = val end assert_nothing_raised("Could not handle arg %s with value %s" % [opt, val]) { @config.handlearg(opt, arg) } } } end def test_addargs @config.setdefaults("testing", :onboolean => [true, "An on bool"], :offboolean => [false, "An off bool"], :string => ["a string", "A string arg"], :file => ["/path/to/file", "A file arg"] ) should = [] @config.each { |name, element| element.expects(:getopt_args).returns([name]) should << name } result = [] assert_nothing_raised("Add args failed") do @config.addargs(result) end assert_equal(should, result, "Did not call addargs correctly.") end def test_addargs_functional @config.setdefaults("testing", :onboolean => [true, "An on bool"], :string => ["a string", "A string arg"] ) result = [] should = [] assert_nothing_raised("Add args failed") do @config.addargs(result) end @config.each do |name, element| if name == :onboolean should << ["--onboolean", GetoptLong::NO_ARGUMENT] should << ["--no-onboolean", GetoptLong::NO_ARGUMENT] elsif name == :string should << ["--string", GetoptLong::REQUIRED_ARGUMENT] end end assert_equal(should, result, "Add args functional test failed") end def test_groupsetting cfile = tempfile() group = "yayness" File.open(cfile, "w") do |f| f.puts "[main] group = #{group} " end config = mkconfig - config.setdefaults(Puppet[:name], :group => ["puppet", "a group"]) + config.setdefaults(Puppet[:name], :group => ["puppet", "a group"], :config => [cfile, "eh"]) assert_nothing_raised { - config.parse(cfile) + config.parse } assert_equal(group, config[:group], "Group did not take") end # provide a method to modify and create files w/out specifying the info # already stored in a config def test_writingfiles File.umask(0022) path = tempfile() mode = 0644 config = mkconfig args = { :default => path, :mode => mode, :desc => "yay" } user = nonrootuser() group = nonrootgroup() if Puppet::Util::SUIDManager.uid == 0 args[:owner] = user.name args[:group] = group.name end config.setdefaults(:testing, :myfile => args) assert_nothing_raised { config.write(:myfile) do |file| file.puts "yay" end } assert_equal(mode, filemode(path), "Modes are not equal") # OS X is broken in how it chgrps files if Puppet::Util::SUIDManager.uid == 0 assert_equal(user.uid, File.stat(path).uid, "UIDS are not equal") case Facter["operatingsystem"].value when /BSD/, "Darwin": # nothing else assert_equal(group.gid, File.stat(path).gid, "GIDS are not equal") end end end def test_mkdir File.umask(0022) path = tempfile() mode = 0755 config = mkconfig args = { :default => path, :mode => mode, :desc => "a file" } user = nonrootuser() group = nonrootgroup() if Puppet::Util::SUIDManager.uid == 0 args[:owner] = user.name args[:group] = group.name end config.setdefaults(:testing, :mydir => args) assert_nothing_raised { config.mkdir(:mydir) } assert_equal(mode, filemode(path), "Modes are not equal") # OS X and *BSD is broken in how it chgrps files if Puppet::Util::SUIDManager.uid == 0 assert_equal(user.uid, File.stat(path).uid, "UIDS are not equal") case Facter["operatingsystem"].value when /BSD/, "Darwin": # nothing else assert_equal(group.gid, File.stat(path).gid, "GIDS are not equal") end end end # Make sure that tags are ignored when configuring def test_configs_ignore_tags config = mkconfig file = tempfile() config.setdefaults(:mysection, :mydir => [file, "a file"] ) Puppet[:tags] = "yayness" assert_nothing_raised { config.use(:mysection) } assert(FileTest.directory?(file), "Directory did not get created") assert_equal("yayness", Puppet[:tags], "Tags got changed during config") end def test_configs_replace_in_url config = mkconfig config.setdefaults(:mysection, :name => ["yayness", "yay"]) config.setdefaults(:mysection, :url => ["http://$name/rahness", "yay"]) val = nil assert_nothing_raised { val = config[:url] } assert_equal("http://yayness/rahness", val, "Settings got messed up") end def test_correct_type_assumptions file = Puppet::Util::Settings::CFile element = Puppet::Util::Settings::CElement bool = Puppet::Util::Settings::CBoolean # We have to keep these ordered, unfortunately. [ ["/this/is/a/file", file], ["true", bool], [true, bool], ["false", bool], ["server", element], ["http://$server/yay", element], ["$server/yayness", file], ["$server/yayness.conf", file] ].each do |ary| config = mkconfig value, type = ary name = value.to_s + "_setting" assert_nothing_raised { config.setdefaults(:yayness, name => { :default => value, :desc => name.to_s}) } elem = config.element(name) assert_instance_of(type, elem, "%s got created as wrong type" % value.inspect) end end - # Make sure we correctly reparse our config files but don't lose CLI values. - def test_reparse - Puppet[:filetimeout] = 0 - - config = mkconfig() - config.setdefaults(:mysection, :default => ["default", "yay"]) - config.setdefaults(:mysection, :clichange => ["clichange", "yay"]) - config.setdefaults(:mysection, :filechange => ["filechange", "yay"]) - - config.stubs(:read_file).returns(%{[main]\nfilechange = filevalue\n}) - file = mock 'file' - file.stubs(:changed?).returns(true) - - assert_nothing_raised { - config.parse(file) - } - - # Set another "from the cli" - assert_nothing_raised { - config.handlearg("clichange", "clivalue") - } - - # And leave the other unset - assert_equal("default", config[:default]) - assert_equal("filevalue", config[:filechange], "Did not get value from file") - assert_equal("clivalue", config[:clichange]) - - # Now reparse - config.stubs(:read_file).returns(%{[main]\nfilechange = newvalue\n}) - file = mock 'file' - file.stubs(:changed?).returns(true) - config.parse(file) - - # And check all of the values - assert_equal("default", config[:default]) - assert_equal("clivalue", config[:clichange]) - assert_equal("newvalue", config[:filechange]) - end - def test_parse_removes_quotes config = mkconfig() config.setdefaults(:mysection, :singleq => ["single", "yay"]) config.setdefaults(:mysection, :doubleq => ["double", "yay"]) config.setdefaults(:mysection, :none => ["noquote", "yay"]) config.setdefaults(:mysection, :middle => ["midquote", "yay"]) file = tempfile() # Set one parameter in the file File.open(file, "w") { |f| f.puts %{[main]\n singleq = 'one' doubleq = "one" none = one middle = mid"quote } } + config.setdefaults(:mysection, :config => [file, "eh"]) + assert_nothing_raised { - config.parse(file) + config.parse } %w{singleq doubleq none}.each do |p| assert_equal("one", config[p], "%s did not match" % p) end assert_equal('mid"quote', config["middle"], "middle did not match") end - def test_timer - Puppet[:filetimeout] = 0.1 - origpath = tempfile() - config = mkconfig() - config.setdefaults(:mysection, :paramdir => [tempfile(), "yay"]) - - file = tempfile() - # Set one parameter in the file - File.open(file, "w") { |f| - f.puts %{[main]\n - paramdir = #{origpath} -} - } - - assert_nothing_raised { - config.parse(file) - config.use(:mysection) - } - - assert(FileTest.directory?(origpath), "dir did not get created") - - # Now start the timer - assert_nothing_raised { - EventLoop.current.monitor_timer config.timer - } - - newpath = tempfile() - - File.open(file, "w") { |f| - f.puts %{[main]\n - paramdir = #{newpath} -} - } - config.file.send("tstamp=".intern, Time.now - 50) - sleep 1 - - assert_equal(newpath, config["paramdir"], - "File did not get reparsed from timer") - assert(FileTest.directory?(newpath), "new dir did not get created") - - - end - # Test that config parameters correctly call passed-in blocks when the value # is set. def test_paramblocks config = mkconfig() testing = nil assert_nothing_raised do config.setdefaults :test, :blocktest => {:default => "yay", :desc => "boo", :hook => proc { |value| testing = value }} end elem = config.element(:blocktest) assert_nothing_raised do assert_equal("yay", elem.value) end assert_nothing_raised do config[:blocktest] = "yaytest" end assert_nothing_raised do assert_equal("yaytest", elem.value) end assert_equal("yaytest", testing) assert_nothing_raised do config[:blocktest] = "another" end assert_nothing_raised do assert_equal("another", elem.value) end assert_equal("another", testing) # Now verify it works from setdefault assert_nothing_raised do config.setdefaults :test, :blocktest2 => { :default => "yay", :desc => "yay", :hook => proc { |v| testing = v } } end assert_equal("yay", config[:blocktest2]) assert_nothing_raised do config[:blocktest2] = "footest" end assert_equal("footest", config[:blocktest2]) assert_equal("footest", testing) end def test_no_modify_root config = mkconfig config.setdefaults(:yay, :mydir => {:default => tempfile(), :mode => 0644, :owner => "root", :group => "root", :desc => "yay" }, :mkusers => [false, "yay"] ) assert_nothing_raised do config.use(:yay) end # Now enable it so they'll be added config[:mkusers] = true comp = config.to_catalog comp.vertices.find_all { |r| r.class.name == :user }.each do |u| assert(u.name != "root", "Tried to manage root user") end comp.vertices.find_all { |r| r.class.name == :group }.each do |u| assert(u.name != "root", "Tried to manage root group") assert(u.name != "wheel", "Tried to manage wheel group") end # assert(yay, "Did not find yay component") # yay.each do |c| # puts @config.ref # end # assert(! yay.find { |o| o.class.name == :user and o.name == "root" }, # "Found root user") # assert(! yay.find { |o| o.class.name == :group and o.name == "root" }, # "Found root group") end # #415 def test_remove_trailing_spaces config = mkconfig() - config.setdefaults(:yay, :rah => ["testing", "a desc"]) - file = tempfile() File.open(file, "w") { |f| f.puts "rah = something " } - assert_nothing_raised { config.parse(file) } + config.setdefaults(:yay, :config => [file, "eh"], :rah => ["testing", "a desc"]) + + assert_nothing_raised { config.parse } assert_equal("something", config[:rah], "did not remove trailing whitespace in parsing") end # #484 def test_parsing_unknown_variables logstore() config = mkconfig() - config.setdefaults(:mysection, :one => ["yay", "yay"]) file = tempfile() File.open(file, "w") { |f| f.puts %{[main]\n one = one two = yay } } + config.setdefaults(:mysection, :config => [file, "eh"], :one => ["yay", "yay"]) + assert_nothing_raised("Unknown parameter threw an exception") do - config.parse(file) + config.parse end end def test_multiple_interpolations @config.setdefaults(:section, :one => ["oneval", "yay"], :two => ["twoval", "yay"], :three => ["$one/$two", "yay"] ) assert_equal("oneval/twoval", @config[:three], "Did not interpolate multiple variables") end # Make sure we can replace ${style} var names def test_curly_replacements @config.setdefaults(:section, :one => ["oneval", "yay"], :two => ["twoval", "yay"], :three => ["$one/${two}/${one}/$two", "yay"] ) assert_equal("oneval/twoval/oneval/twoval", @config[:three], "Did not interpolate curlied variables") end # Test to make sure that we can set and get a short name def test_celement_short_name element = nil assert_nothing_raised("Could not create celement") do element = CElement.new :short => "n", :desc => "anything", :settings => Puppet::Util::Settings.new end assert_equal("n", element.short, "Short value is not retained") assert_raise(ArgumentError,"Allowed multicharactered short names.") do element = CElement.new :short => "no", :desc => "anything", :settings => Puppet::Util::Settings.new end end # Test to make sure that no two celements have the same short name def test_celement_short_name_not_duplicated config = mkconfig assert_nothing_raised("Could not create celement with short name.") do config.setdefaults(:main, :one => { :default => "blah", :desc => "anything", :short => "o" }) end assert_nothing_raised("Could not create second celement with short name.") do config.setdefaults(:main, :two => { :default => "blah", :desc => "anything", :short => "i" }) end assert_raise(ArgumentError, "Could create second celement with duplicate short name.") do config.setdefaults(:main, :three => { :default => "blah", :desc => "anything", :short => "i" }) end # make sure that when the above raises an expection that the config is not included assert(!config.include?(:three), "Invalid configuration item was retained") end # Tell getopt which arguments are valid def test_get_getopt_args element = CElement.new :name => "foo", :desc => "anything", :settings => Puppet::Util::Settings.new assert_equal([["--foo", GetoptLong::REQUIRED_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args") element.short = "n" assert_equal([["--foo", "-n", GetoptLong::REQUIRED_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args") element = CBoolean.new :name => "foo", :desc => "anything", :settings => Puppet::Util::Settings.new assert_equal([["--foo", GetoptLong::NO_ARGUMENT], ["--no-foo", GetoptLong::NO_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args") element.short = "n" assert_equal([["--foo", "-n", GetoptLong::NO_ARGUMENT],["--no-foo", GetoptLong::NO_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args") end end