diff --git a/lib/puppet/provider/host/parsed.rb b/lib/puppet/provider/host/parsed.rb index f3e76305d..d69dcbec4 100644 --- a/lib/puppet/provider/host/parsed.rb +++ b/lib/puppet/provider/host/parsed.rb @@ -1,72 +1,74 @@ require 'puppet/provider/parsedfile' hosts = nil case Facter.value(:operatingsystem) when "Solaris"; hosts = "/etc/inet/hosts" else hosts = "/etc/hosts" end Puppet::Type.type(:host).provide(:parsed, :parent => Puppet::Provider::ParsedFile, :default_target => hosts, :filetype => :flat ) do confine :exists => hosts text_line :comment, :match => /^#/ text_line :blank, :match => /^\s*$/ record_line :parsed, :fields => %w{ip name host_aliases}, :optional => %w{host_aliases}, :rts => true do |line| hash = {} if line.sub!(/^(\S+)\s+(\S+)\s*/, '') hash[:ip] = $1 hash[:name] = $2 - unless line == "" + if line.empty? + hash[:host_aliases] = [] + else line.sub!(/\s*/, '') line.sub!(/^([^#]+)\s*/) do |value| aliases = $1 unless aliases =~ /^\s*$/ hash[:host_aliases] = aliases.split(/\s+/) end "" end end else raise Puppet::Error, "Could not match '%s'" % line end if hash[:host_aliases] == "" - hash.delete(:host_aliases) + hash[:host_aliases] = [] end return hash end # Convert the current object into a host-style string. def self.to_line(hash) return super unless hash[:record_type] == :parsed [:ip, :name].each do |n| unless hash[n] and hash[n] != :absent raise ArgumentError, "%s is a required attribute for hosts" % n end end str = "%s\t%s" % [hash[:ip], hash[:name]] - if hash.include? :host_aliases + if hash.include? :host_aliases and !hash[:host_aliases].empty? if hash[:host_aliases].is_a? Array str += "\t%s" % hash[:host_aliases].join("\t") else raise ArgumentError, "Host aliases must be specified as an array" end end str end end diff --git a/test/ral/providers/host/parsed.rb b/test/ral/providers/host/parsed.rb index ce70f5c9f..839761286 100755 --- a/test/ral/providers/host/parsed.rb +++ b/test/ral/providers/host/parsed.rb @@ -1,225 +1,225 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../lib/puppettest' require 'etc' require 'puppettest' require 'puppettest/fileparsing' require 'test/unit' class TestParsedHostProvider < Test::Unit::TestCase include PuppetTest include PuppetTest::FileParsing def setup super @provider = Puppet::Type.type(:host).provider(:parsed) @oldfiletype = @provider.filetype end def teardown Puppet::Util::FileType.filetype(:ram).clear @provider.filetype = @oldfiletype @provider.clear super end def test_provider_existence assert(@provider, "Could not retrieve provider") end # Here we just create a fake host type that answers to all of the methods # but does not modify our actual system. def mkfaketype @provider.filetype = Puppet::Util::FileType.filetype(:ram) end def mkhosthash if defined? @hcount @hcount += 1 else @hcount = 1 end return { :name => "fakehost%s" % @hcount, :ip => "192.168.27.%s" % @hcount, :host_aliases => ["alias%s" % @hcount], :ensure => :present } end def mkhost hash = mkhosthash() fakeresource = fakeresource(:host, hash[:name]) host = @provider.new(fakeresource) assert(host, "Could not create provider host") hash.each do |name, val| host.send(name.to_s + "=", val) end return host end # Make sure we convert both directlys correctly using a simple host. def test_basic_isomorphism hash = {:record_type => :parsed, :name => "myhost", :ip => "192.168.43.56", :host_aliases => %w{another host}} str = nil assert_nothing_raised do str = @provider.to_line(hash) end assert_equal("192.168.43.56\tmyhost\tanother\thost", str) newhash = nil assert_nothing_raised do newhash = @provider.parse(str).shift end assert_equal(hash, newhash) end # Make sure parsing gets comments, blanks, and hosts def test_blanks_and_comments mkfaketype() text = %{# comment one 192.168.43.56\tmyhost\tanother\thost # another comment 192.168.43.57\tanotherhost } instances = nil assert_nothing_raised do instances = @provider.parse(text) end assert_equal([ {:record_type => :comment, :line => "# comment one"}, {:record_type => :blank, :line => ""}, {:record_type => :parsed, :name => "myhost", :ip => "192.168.43.56", :host_aliases => %w{another host}}, {:record_type => :blank, :line => " "}, {:record_type => :comment, :line => "# another comment"}, - {:record_type => :parsed, :name => "anotherhost", :ip => "192.168.43.57"} + {:record_type => :parsed, :name => "anotherhost", :ip => "192.168.43.57", :host_aliases => []} ], instances) newtext = nil assert_nothing_raised do newtext = @provider.to_file(instances).gsub(/^# HEADER.+\n/, '') end assert_equal(text, newtext) end def test_simplehost mkfaketype @provider.default_target = :yayness file = @provider.target_object(:yayness) # Start out with no content. assert_nothing_raised { assert_equal([], @provider.parse(file.read)) } # Now create a provider host = nil assert_nothing_raised { host = mkhost } # Make sure we're still empty assert_nothing_raised { assert_equal([], @provider.parse(file.read)) } # Try storing it assert_nothing_raised do host.flush end # Make sure we get the host back assert_nothing_raised { assert(file.read.include?(host.name), "Did not flush host to disk") } # Remove a single field and make sure it gets tossed name = host.host_aliases host.host_aliases = [:absent] assert_nothing_raised { host.flush assert(! file.read.include?(name[0]), "Did not remove host_aliases from disk") } # Make sure it throws up if we remove a required field host.ip = :absent assert_raise(ArgumentError) { host.flush } # Now remove the whole object host.ensure = :absent assert_nothing_raised { host.flush assert_equal([], @provider.parse(file.read)) } end # Parse our sample data and make sure we regenerate it correctly. def test_hostsparse fakedata("data/types/hosts").each do |file| fakedataparse(file) end end # Make sure we can modify the file elsewhere and those modifications will # get taken into account. def test_modifyingfile hostfile = tempfile() @provider.default_target = hostfile file = @provider.target_object(hostfile) hosts = [] 3.times { h = mkhost() hosts << h } hosts.each do |host| host.flush end newhost = mkhost() hosts << newhost # Now store our new host newhost.flush() # Verify we can retrieve that info assert_nothing_raised("Could not retrieve after second write") { @provider.prefetch } text = file.read instances = @provider.parse(text) # And verify that we have data for everything hosts.each { |host| name = host.resource[:name] assert(text.include?(name), "Host %s is not in file" % name) hash = host.property_hash assert(! hash.empty?, "Could not find host %s" % name) assert(hash[:ip], "Could not find ip for host %s" % name) } end end