diff options
| author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-01-13 18:26:14 +0000 |
|---|---|---|
| committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-01-13 18:26:14 +0000 |
| commit | bbf2c547dc550c4423c94ceb53395d1146a46918 (patch) | |
| tree | 37c5be69ee29153c1243323937c42e1f3e4b58cf | |
| parent | 0c1714945692330ca76a6c254303ff4fcd466efb (diff) | |
| download | puppet-bbf2c547dc550c4423c94ceb53395d1146a46918.tar.gz puppet-bbf2c547dc550c4423c94ceb53395d1146a46918.tar.xz puppet-bbf2c547dc550c4423c94ceb53395d1146a46918.zip | |
Adding /etc/services support
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@821 980ebf18-57e1-0310-9a29-db15c13687c0
| -rwxr-xr-x | lib/puppet/type/parsedtype.rb | 7 | ||||
| -rwxr-xr-x | lib/puppet/type/parsedtype/port.rb | 210 | ||||
| -rwxr-xr-x | test/types/host.rb | 31 | ||||
| -rwxr-xr-x | test/types/port.rb | 76 |
4 files changed, 293 insertions, 31 deletions
diff --git a/lib/puppet/type/parsedtype.rb b/lib/puppet/type/parsedtype.rb index c942c1217..c4c64c021 100755 --- a/lib/puppet/type/parsedtype.rb +++ b/lib/puppet/type/parsedtype.rb @@ -142,7 +142,9 @@ module Puppet # if the obj already exists with that name... if obj = self[hash[:name]] - # do nothing... + # We're assuming here that objects with the same name + # are the same object, which *should* be the case, assuming + # we've set up our naming stuff correctly everywhere. else # create a new obj, since no existing one seems to # match @@ -175,7 +177,7 @@ module Puppet @fileobj ||= @filetype.new(@path) if @instances.empty? - Puppet.notice "No host instances for %s" % user + Puppet.notice "No %s instances for %s" % [self.name, @path] else @fileobj.write(self.to_file()) end @@ -219,5 +221,6 @@ module Puppet end require 'puppet/type/parsedtype/host' +require 'puppet/type/parsedtype/port' # $Id$ diff --git a/lib/puppet/type/parsedtype/port.rb b/lib/puppet/type/parsedtype/port.rb new file mode 100755 index 000000000..2080e1086 --- /dev/null +++ b/lib/puppet/type/parsedtype/port.rb @@ -0,0 +1,210 @@ +require 'etc' +require 'facter' +require 'puppet/type/parsedtype' +require 'puppet/type/state' + +module Puppet + newtype(:port, Puppet::Type::ParsedType) do + newstate(:protocols) do + desc "The protocols the port uses. Valid values are *udp* and *tcp*. + Most services have both protocols, but not all." + + def is=(proto) + unless proto.is_a?(Array) + proto = [proto] + end + #self.info "setting to %s" % proto.inspect + @is = proto + end + + def is + #self.notice "returning is %s" % @is.inspect + @is + end + + # We actually want to return the whole array here, not just the first + # value. + def should + @should + end + end + + newstate(:number) do + desc "The port number." + end + + newstate(:description) do + desc "The port description." + end + + newstate(:aliases) do + desc "Any aliases the port might have. Values can be either an array + or a comma-separated list." + + # We have to override the feeding mechanism; it might be nil or + # white-space separated + def is=(value) + # If it's just whitespace, ignore it + if value =~ /^\s+$/ + @is = nil + else + # Else split based on whitespace and store as an array + @is = value.split(/\s+/) + end + end + + # We actually want to return the whole array here, not just the first + # value. + def should + @should + end + + munge do |values| + unless values.is_a?(Array) + values = [values] + end + # Split based on comma, then flatten the whole thing + values.collect { |values| + values.split(/,\s*/) + }.flatten + end + end + + newparam(:name) do + desc "The port name." + + isnamevar + end + + @doc = "Installs and manages port entries. For most systems, these + entries will just be in /etc/services, but some systems (notably OS X) + will have different solutions." + + @path = "/etc/services" + @fields = [:ip, :name, :aliases] + + @filetype = Puppet::FileType.filetype(:flat) +# case Facter["operatingsystem"].value +# when "Solaris": +# @filetype = Puppet::FileType::SunOS +# else +# @filetype = Puppet::CronType::Default +# end + + # Parse a services file + # + # This method also stores existing comments, and it stores all host + # jobs in order, mostly so that comments are retained in the order + # they were written and in proximity to the same jobs. + def self.parse(text) + count = 0 + hash = {} + text.chomp.split("\n").each { |line| + case line + when /^#/, /^\s*$/: + # add comments and blank lines to the list as they are + @instances << line + else + #if match = /^(\S+)\s+(\d+)\/(\w+)/.match(line) + # Puppet.warning "%s %s %s" % [$1, $2, $3] + # next + #if line.sub(/^(\S+)\s+(\d+)\/(\w+)\s*(\S*)$/.match(line) + if line.sub!(/^(\S+)\s+(\d+)\/(\w+)\s*/, '') + hash[:name] = $1 + hash[:number] = $2 + hash[:protocols] = $3 + + unless line == "" + line.sub!(/^([^#]+)\s*/) do |value| + aliases = $1 + unless aliases =~ /^\s*$/ + hash[:aliases] = aliases + end + + "" + end + + line.sub!(/^\s*#\s*(.+)$/) do |value| + desc = $1 + unless desc =~ /^\s*$/ + hash[:description] = desc.sub(/\s*$/, '') + end + + "" + end + end + else + raise Puppet::Error, "Could not match '%s'" % line + end + + # If there's already a service with this name, then check + # to see if the only difference is the proto; if so, just + # add our proto and walk away + if obj = self[hash[:name]] + if obj.portmerge(hash) + next + end + end + + hash2obj(hash) + + hash.clear + count += 1 + end + } + end + + def portmerge(hash) + unless @states.include?(:protocols) + return false + end + proto = self.state(:protocols).is + + if proto.nil? + # We are an unitialized object; we've got 'should' + # values but no 'is' values + return false + end + + if hash[:protocols] + # Check to see if it already includes our proto + if proto.include?(hash[:protocols]) + Puppet.warning( + "There is already a port with our name and protocols" + ) + else + # We are missing their proto + proto << hash[:protocols] + #Puppet.info "new proto is %s" % proto.inspect + @states[:protocols].is = proto + #Puppet.info "new value is %s" % @states[:protocols].is.inspect + end + end + + if hash.include?(:description) and ! @states.include?(:description) + Puppet.info "Adding description to %s" % hash[:name] + self.is = [:description, hash[:description]] + end + + return true + end + + # Convert the current object into a host-style string. + def to_str + str = "%s\t%s/%s" % [self[:name], self.state(:number).should, + self.state(:protocols).should] + + if state = self.state(:alias) + str += "\t%s" % state.should.join(" ") + end + + if state = self.state(:description) + str += "\t# %s" % state.should + end + + str + end + end +end + +# $Id$ diff --git a/test/types/host.rb b/test/types/host.rb index 84ff041a4..a1fedcd07 100755 --- a/test/types/host.rb +++ b/test/types/host.rb @@ -11,7 +11,7 @@ require 'puppet' require 'test/unit' require 'facter' -class TestCron < Test::Unit::TestCase +class TestHost < Test::Unit::TestCase include TestPuppet def setup super @@ -29,34 +29,7 @@ class TestCron < Test::Unit::TestCase # Here we just create a fake host type that answers to all of the methods # but does not modify our actual system. def mkfaketype - @fakehosttype = Class.new { - attr_accessor :synced, :loaded, :path - @tabs = Hash.new("") - def clear - @text = nil - end - - def initialize(path) - @path = path - @text = nil - end - - def read - @loaded = Time.now - @text - end - - def write(text) - @syned = Time.now - @text = text - end - - def remove - @text = "" - end - } - - @hosttype.filetype = @fakehosttype + @hosttype.filetype = Puppet::FileType.filetype(:ram) end def test_simplehost diff --git a/test/types/port.rb b/test/types/port.rb new file mode 100755 index 000000000..5225f27ce --- /dev/null +++ b/test/types/port.rb @@ -0,0 +1,76 @@ +# Test host job creation, modification, and destruction + +if __FILE__ == $0 + $:.unshift '..' + $:.unshift '../../lib' + $puppetbase = "../../../../language/trunk" +end + +require 'puppettest' +require 'puppet' +require 'puppet/type/parsedtype/port' +require 'test/unit' +require 'facter' + +class TestPort < Test::Unit::TestCase + include TestPuppet + def setup + super + @porttype = Puppet.type(:port) + @oldfiletype = @porttype.filetype + end + + def teardown + @porttype.filetype = @oldfiletype + Puppet.type(:file).clear + super + 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 + @porttype.filetype = Puppet::FileType.filetype(:ram) + end + + def test_simplehost + mkfaketype + host = nil + assert_nothing_raised { + assert_nil(Puppet.type(:port).retrieve) + } + + assert_nothing_raised { + host = Puppet.type(:port).create( + :name => "puppet", + :number => 8139, + :protocols => "tcp", + :description => "The port that Puppet runs on" + ) + } + + assert_nothing_raised { + Puppet.type(:port).store + } + + assert_nothing_raised { + assert_equal(Puppet.type(:port).fileobj.read, Puppet.type(:port).to_file) + } + end + + def test_hostsparse + assert_nothing_raised { + Puppet.type(:port).retrieve + } + + # Now just make we've got some ports we know will be there + dns = @porttype["domain"] + assert(dns, "Could not retrieve DNS port") + + assert_equal("53", dns.is(:number), "DNS number was wrong") + %w{udp tcp}.each { |v| + assert(dns.is(:protocols).include?(v), "DNS did not include proto %s" % v) + } + end +end + +# $Id$ |
