diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-03-02 07:30:14 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-03-02 07:30:14 +0000 |
commit | 95856eaaf02361ff597ca2c85e51cf141fe81280 (patch) | |
tree | db31ba74ce65523fa9dcd4d1cae0cd75c55a4395 /lib/puppet | |
parent | ff1df8e1aef99dbdc222c5d5d808494fd08e7f83 (diff) | |
download | puppet-95856eaaf02361ff597ca2c85e51cf141fe81280.tar.gz puppet-95856eaaf02361ff597ca2c85e51cf141fe81280.tar.xz puppet-95856eaaf02361ff597ca2c85e51cf141fe81280.zip |
Okay, Puppet is now almost entirely capable of configuring itself. I have not yet added the extra tests to puppetmasterd to make sure it can start as a normal user, and the executables still fail some simple tests because they are producing output when they start (I will get rid of the output), but overall things look pretty good.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@965 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib/puppet')
-rw-r--r-- | lib/puppet/client/ca.rb | 6 | ||||
-rw-r--r-- | lib/puppet/client/master.rb | 16 | ||||
-rw-r--r-- | lib/puppet/config.rb | 147 | ||||
-rwxr-xr-x | lib/puppet/daemon.rb | 36 | ||||
-rw-r--r-- | lib/puppet/event.rb | 11 | ||||
-rw-r--r-- | lib/puppet/log.rb | 2 | ||||
-rw-r--r-- | lib/puppet/metric.rb | 20 | ||||
-rw-r--r-- | lib/puppet/server/ca.rb | 21 | ||||
-rwxr-xr-x | lib/puppet/sslcertificates.rb | 40 | ||||
-rw-r--r-- | lib/puppet/sslcertificates/ca.rb | 62 | ||||
-rw-r--r-- | lib/puppet/storage.rb | 22 | ||||
-rw-r--r-- | lib/puppet/transaction.rb | 2 | ||||
-rw-r--r-- | lib/puppet/type.rb | 122 | ||||
-rw-r--r-- | lib/puppet/type/component.rb | 33 | ||||
-rw-r--r-- | lib/puppet/type/pfile.rb | 17 | ||||
-rwxr-xr-x | lib/puppet/type/pfile/ensure.rb | 6 | ||||
-rwxr-xr-x | lib/puppet/type/pfile/group.rb | 84 | ||||
-rwxr-xr-x | lib/puppet/type/pfile/mode.rb | 3 |
18 files changed, 353 insertions, 297 deletions
diff --git a/lib/puppet/client/ca.rb b/lib/puppet/client/ca.rb index 11989230c..a7fa71e88 100644 --- a/lib/puppet/client/ca.rb +++ b/lib/puppet/client/ca.rb @@ -7,7 +7,11 @@ class Puppet::Client::CAClient < Puppet::Client::ProxyClient def initialize(hash = {}) if hash.include?(:CA) - hash[:CA] = Puppet::Server::CA.new() + if hash[:CA].is_a? Hash + hash[:CA] = Puppet::Server::CA.new(hash[:CA]) + else + hash[:CA] = Puppet::Server::CA.new() + end end super(hash) diff --git a/lib/puppet/client/master.rb b/lib/puppet/client/master.rb index f9694fb3d..02186b19d 100644 --- a/lib/puppet/client/master.rb +++ b/lib/puppet/client/master.rb @@ -66,11 +66,12 @@ class Puppet::Client::MasterClient < Puppet::Client # Cache the config def cache(text) + Puppet.config.use(:puppet, :sslcertificates, :puppetd) Puppet.info "Caching configuration at %s" % self.cachefile confdir = File.dirname(Puppet[:localconfig]) - unless FileTest.exists?(confdir) - Puppet.recmkdir(confdir, 0770) - end + #unless FileTest.exists?(confdir) + # Puppet.recmkdir(confdir, 0770) + #end File.open(self.cachefile + ".tmp", "w", 0660) { |f| f.print text } @@ -87,9 +88,10 @@ class Puppet::Client::MasterClient < Puppet::Client # Disable running the configuration. def disable Puppet.notice "Disabling puppetd" - unless FileTest.exists? File.dirname(Puppet[:puppetdlockfile]) - Puppet.recmkdir(File.dirname(Puppet[:puppetdlockfile])) - end + Puppet.config.use(:puppet) + #unless FileTest.exists? File.dirname(Puppet[:puppetdlockfile]) + # Puppet.recmkdir(File.dirname(Puppet[:puppetdlockfile])) + #end begin File.open(Puppet[:puppetdlockfile], "w") { |f| f.puts ""; f.flush } rescue => detail @@ -237,7 +239,7 @@ class Puppet::Client::MasterClient < Puppet::Client #@objects = objects # and perform any necessary final actions before we evaluate. - Puppet::Type.finalize + @objects.finalize return @objects end diff --git a/lib/puppet/config.rb b/lib/puppet/config.rb index b165192e5..06aebb893 100644 --- a/lib/puppet/config.rb +++ b/lib/puppet/config.rb @@ -1,4 +1,5 @@ require 'puppet' +require 'sync' require 'puppet/transportable' module Puppet @@ -6,6 +7,9 @@ module Puppet class Config include Enumerable + @@sync = Sync.new + + # Retrieve a config value def [](param) param = symbolize(param) @@ -88,6 +92,7 @@ class Config @config.each { |name, obj| obj.clear } + @used = [] end def symbolize(param) @@ -165,6 +170,8 @@ class Config def initialize @order = [] @config = {} + + @created = [] end # Return all of the parameters associated with a given section. @@ -296,43 +303,47 @@ class Config done ||= Hash.new { |hash, key| hash[key] = {} } objects = [] persection(section) { |obj| - [:owner, :group].each { |attr| - type = nil - if attr == :owner - type = :user - else - type = attr - end - if obj.respond_to? attr and name = obj.send(attr) - # Skip owners and groups we've already done, but tag them with - # our section if necessary - if done[type].include?(name) - tags = done[type][name].tags - unless tags.include?(section) - done[type][name].tags = tags << section - end - elsif newobj = Puppet::Type.type(type)[name] - newobj.tag(section) + if @config[:mkusers] and @config[:mkusers].value + [:owner, :group].each { |attr| + type = nil + if attr == :owner + type = :user else - newobj = TransObject.new(name, type.to_s) - newobj[:ensure] = "present" - done[type][name] = newobj - objects << newobj + type = attr end - end - } + if obj.respond_to? attr and name = obj.send(attr) + # Skip owners and groups we've already done, but tag them with + # our section if necessary + if done[type].include?(name) + tags = done[type][name].tags + unless tags.include?(section) + done[type][name].tags = tags << section + end + elsif newobj = Puppet::Type.type(type)[name] + unless newobj.state(:ensure) + newobj[:ensure] = "present" + end + newobj.tag(section) + else + newobj = TransObject.new(name, type.to_s) + newobj[:ensure] = "present" + done[type][name] = newobj + objects << newobj + end + end + } + end if obj.respond_to? :to_transportable transobjects = obj.to_transportable transobjects = [transobjects] unless transobjects.is_a? Array transobjects.each do |trans| + # transportable could return nil next unless trans unless done[:file].include? trans.name - # transportable could return nil - unless !includefiles and trans[:ensure] == :file - objects << trans - end - done[:file][obj.name] = obj + @created << trans.name + objects << trans + done[:file][trans.name] = trans end end end @@ -437,15 +448,54 @@ Generated on #{Time.now}. return manifest end - # Create the necessary objects to use a section - def use(section) - section = section.intern if section.is_a? String - bucket = section_to_transportable(section, nil, false) + def reuse + return unless defined? @used + @@sync.synchronize do # yay, thread-safe + @used.each do |section| + @used.delete(section) + self.use(section) + end + end + end - objects = bucket.to_type + # Create the necessary objects to use a section. This is idempotent; + # you can 'use' a section as many times as you want. + def use(*sections) + @@sync.synchronize do # yay, thread-safe + unless defined? @used + @used = [] + end + + runners = sections.collect { |s| + symbolize(s) + }.find_all { |s| + ! @used.include? s + } + return if runners.empty? - trans = objects.evaluate - trans.evaluate + bucket = Puppet::TransBucket.new + bucket.type = "puppetconfig" + bucket.top = true + runners.each do |section| + bucket.push section_to_transportable(section, nil, false) + end + + objects = bucket.to_type + + objects.finalize + trans = objects.evaluate + trans.evaluate + + # And then clean up. We're now a tree of objects, so we have to + # use delve, instead of each. + #objects.delve do |object| + objects.remove + #trans.objects.each do |object| + # object.remove(true) + #end + + sections.each { |s| @used << s } + end end def valid?(param) @@ -551,7 +601,7 @@ Generated on #{Time.now}. return nil end - if respond_to?(:convert) + if retval.is_a? String return convert(retval) else return retval @@ -573,7 +623,24 @@ Generated on #{Time.now}. # A file. class CFile < CElement - attr_accessor :owner, :group, :mode, :create + attr_writer :owner, :group + attr_accessor :mode, :create + + def group + if defined? @group + return convert(@group) + else + return nil + end + end + + def owner + if defined? @owner + return convert(@owner) + else + return nil + end + end # Set the type appropriately. Yep, a hack. This supports either naming # the variable 'dir', or adding a slash at the end. @@ -617,11 +684,15 @@ Generated on #{Time.now}. if type == :directory or self.create obj[:ensure] = type end - [:owner, :group, :mode].each { |var| + [:group, :mode].each { |var| if value = self.send(var) obj[var] = value end } + + if Process.uid == 0 and value = self.send(:owner) + obj[:owner] = value + end if self.section obj.tags = ["puppet", "configuration", self.section] end diff --git a/lib/puppet/daemon.rb b/lib/puppet/daemon.rb index 9f91e183f..c4aeefadb 100755 --- a/lib/puppet/daemon.rb +++ b/lib/puppet/daemon.rb @@ -54,17 +54,20 @@ module Puppet def httplog args = [] + # yuck; separate http logs file = nil - if self.is_a?(Puppet::Server) + Puppet.config.use(:puppet, :certificates, Puppet.name) + if Puppet.name == "puppetmasterd" file = Puppet[:masterhttplog] else file = Puppet[:httplog] end +# +# unless FileTest.exists?(File.dirname(file)) +# Puppet.recmkdir(File.dirname(file)) +# end - unless FileTest.exists?(File.dirname(file)) - Puppet.recmkdir(File.dirname(file)) - end args << file if Puppet[:debug] args << WEBrick::Log::DEBUG @@ -72,12 +75,14 @@ module Puppet log = WEBrick::Log.new(*args) + return log end # Read in an existing certificate. def readcert return unless @secureinit + Puppet.config.use(:puppet, :certificates) # verify we've got all of the certs set up and such if defined? @cert and defined? @key and @cert and @key @@ -116,13 +121,15 @@ module Puppet # storing the cert locally. def requestcert retrieved = false + Puppet.config.use(:puppet, :certificates) # create the directories involved - [Puppet[:certdir], Puppet[:privatekeydir], Puppet[:csrdir], - Puppet[:publickeydir]].each { |dir| - unless FileTest.exists?(dir) - Puppet.recmkdir(dir, 0770) - end - } + # FIXME it's a stupid hack that i have to do this +# [Puppet[:certdir], Puppet[:privatekeydir], Puppet[:csrdir], +# Puppet[:publickeydir]].each { |dir| +# unless FileTest.exists?(dir) +# Puppet.recmkdir(dir, 0770) +# end +# } if self.readcert Puppet.info "Certificate already exists; not requesting" @@ -188,6 +195,7 @@ module Puppet # Create the pid file. def setpidfile + Puppet.config.use(:puppet) @pidfile = self.pidfile if FileTest.exists?(@pidfile) Puppet.info "Deleting old pid file" @@ -199,10 +207,10 @@ module Puppet end end - unless FileTest.exists?(Puppet[:rundir]) - Puppet.recmkdir(Puppet[:rundir]) - File.chmod(01777, Puppet[:rundir]) - end + #unless FileTest.exists?(Puppet[:rundir]) + # Puppet.recmkdir(Puppet[:rundir]) + # File.chmod(01777, Puppet[:rundir]) + #end Puppet.info "Setting pidfile to %s" % @pidfile begin diff --git a/lib/puppet/event.rb b/lib/puppet/event.rb index 9576ea4be..7c0d0c573 100644 --- a/lib/puppet/event.rb +++ b/lib/puppet/event.rb @@ -123,9 +123,15 @@ module Puppet type, name = self.split(source) return @subscriptions[type][name].collect { |sub| sub.target + }.reject { |o| + o.nil? } end + def delete + self.class.delete(self) + end + # The hash here must include the target and source objects, the event, # and the callback to call. def initialize(hash) @@ -161,8 +167,9 @@ module Puppet if source = self.class.retrieve(@source) return source else - raise Puppet::Error, "Could not retreive dependency %s[%s]" % - @source + raise Puppet::Error, + "Could not retreive dependency %s[%s] for %s[%s]" % + [@source[0], @source[1], @target[0], @target[1]] end end diff --git a/lib/puppet/log.rb b/lib/puppet/log.rb index 672ff1d8b..ec7ec9e8b 100644 --- a/lib/puppet/log.rb +++ b/lib/puppet/log.rb @@ -123,6 +123,8 @@ module Puppet when /^\// # files Puppet.info "opening %s as a log" % dest # first make sure the directory exists + # We can't just use 'Config.use' here, because they've + # specified a "special" destination. unless FileTest.exist?(File.dirname(dest)) begin Puppet.recmkdir(File.dirname(dest)) diff --git a/lib/puppet/metric.rb b/lib/puppet/metric.rb index f67c06d36..fb72c305b 100644 --- a/lib/puppet/metric.rb +++ b/lib/puppet/metric.rb @@ -132,25 +132,7 @@ module Puppet def create - dir = Puppet[:rrddir] - unless dir - raise "Cannot store metrics unless RRDDir is set" - end - - unless FileTest.exist?(dir) - tmp = dir.sub(/^\//,'') - path = [File::SEPARATOR] - tmp.split(File::SEPARATOR).each { |d| - path.push d - unless FileTest.exist?(File.join(path)) - Dir.mkdir(File.join(path)) - end - } - end - - unless FileTest.directory?(dir) - raise Puppet::Error.new("%s must be a directory" % dir) - end + Puppet.config.use(:metrics) path = self.path args = [ diff --git a/lib/puppet/server/ca.rb b/lib/puppet/server/ca.rb index a008feb70..8b0a1a46f 100644 --- a/lib/puppet/server/ca.rb +++ b/lib/puppet/server/ca.rb @@ -48,8 +48,9 @@ class Server end def initialize(hash = {}) + Puppet.config.use(:puppet, :certificates, :ca) @autosign = hash[:autosign] || Puppet[:autosign] - @ca = Puppet::SSLCertificates::CA.new() + @ca = Puppet::SSLCertificates::CA.new(hash) end # our client sends us a csr, and we either store it for later signing, @@ -81,9 +82,9 @@ class Server # okay, we're now going to store the public key if we don't already # have it public_key = csr.public_key - unless FileTest.directory?(Puppet[:publickeydir]) - Puppet.recmkdir(Puppet[:publickeydir]) - end + #unless FileTest.directory?(Puppet[:publickeydir]) + # Puppet.recmkdir(Puppet[:publickeydir]) + #end pkeyfile = File.join(Puppet[:publickeydir], [hostname, "pem"].join('.')) if FileTest.exists?(pkeyfile) @@ -96,17 +97,17 @@ class Server f.print public_key.to_s } end - unless FileTest.directory?(Puppet[:certdir]) - Puppet.recmkdir(Puppet[:certdir], 0770) - end + #unless FileTest.directory?(Puppet[:certdir]) + # Puppet.recmkdir(Puppet[:certdir], 0770) + #end certfile = File.join(Puppet[:certdir], [hostname, "pem"].join(".")) #puts hostname #puts certfile - unless FileTest.directory?(Puppet[:csrdir]) - Puppet.recmkdir(Puppet[:csrdir], 0770) - end + #unless FileTest.directory?(Puppet[:csrdir]) + # Puppet.recmkdir(Puppet[:csrdir], 0770) + #end # first check to see if we already have a signed cert for the host cert, cacert = ca.getclientcert(hostname) if cert and cacert diff --git a/lib/puppet/sslcertificates.rb b/lib/puppet/sslcertificates.rb index fef661178..88a9193d1 100755 --- a/lib/puppet/sslcertificates.rb +++ b/lib/puppet/sslcertificates.rb @@ -9,36 +9,16 @@ rescue LoadError end module Puppet::SSLCertificates -# def self.mkdir(dir) -# # this is all a bunch of stupid hackery -# unless FileTest.exists?(dir) -# comp = Puppet.type(:component).create( -# :name => "certdir creation" -# ) -# path = [''] -# -# dir.split(File::SEPARATOR).each { |d| -# path << d -# if FileTest.exists?(File.join(path)) -# unless FileTest.directory?(File.join(path)) -# raise "%s exists but is not a directory" % File.join(path) -# end -# else -# obj = Puppet::Type.type(:file).create( -# :name => File.join(path), -# :mode => "750", -# :ensure => "directory" -# ) -# -# comp.push obj -# end -# } -# trans = comp.evaluate -# trans.evaluate -# end -# -# Puppet::Type.allclear -# end + Puppet.setdefaults("certificates", + :certdir => ["$ssldir/certs", "The certificate directory."], + :publickeydir => ["$ssldir/public_keys", "The public key directory."], + :privatekeydir => ["$ssldir/private_keys", "The private key directory."], + :privatedir => ["$ssldir/private", + "Where the client stores private certificate information."], + :passfile => ["$privatedir/password", + "Where puppetd stores the password for its private key. Generally + unused."] + ) #def self.mkcert(type, name, days, issuercert, issuername, serial, publickey) def self.mkcert(hash) diff --git a/lib/puppet/sslcertificates/ca.rb b/lib/puppet/sslcertificates/ca.rb index 9fec908d6..8d74cdf3e 100644 --- a/lib/puppet/sslcertificates/ca.rb +++ b/lib/puppet/sslcertificates/ca.rb @@ -2,35 +2,42 @@ class Puppet::SSLCertificates::CA Certificate = Puppet::SSLCertificates::Certificate attr_accessor :keyfile, :file, :config, :dir, :cert - Puppet.setdefaults("ca", - :certdir => ["$ssldir/certs", "The certificate directory."], - :publickeydir => ["$ssldir/public_keys", "The public key directory."], - :privatekeydir => ["$ssldir/private_keys", "The private key directory."], - :cadir => ["$ssldir/ca", - "The root directory for the certificate authority."], - :cacert => ["$cadir/ca_crt.pem", "The CA certificate."], - :cakey => ["$cadir/ca_key.pem", "The CA private key."], + Puppet.setdefaults(:ca, + :cadir => { :default => "$ssldir/ca", + :mode => 0770, + :desc => "The root directory for the certificate authority." + }, + :cacert => { :default => "$cadir/ca_crt.pem", + :mode => 0660, + :desc => "The CA certificate." + }, + :cakey => { :default => "$cadir/ca_key.pem", + :mode => 0660, + :desc => "The CA private key." + }, :capub => ["$cadir/ca_pub.pem", "The CA public key."], - :caprivatedir => ["$cadir/private", - "Where the CA stores private certificate information."], + :caprivatedir => { :default => "$cadir/private", + :mode => 0770, + :desc => "Where the CA stores private certificate information." + }, :csrdir => ["$cadir/requests", "Where the CA stores certificate requests"], - :signeddir => ["$cadir/signed", - "Where the CA stores signed certificates."], - :capass => ["$caprivatedir/ca.pass", - "Where the CA stores the password for the private key"], + :signeddir => { :default => "$cadir/signed", + :mode => 0770, + :desc => "Where the CA stores signed certificates." + }, + :capass => { :default => "$caprivatedir/ca.pass", + :mode => 0660, + :desc => "Where the CA stores the password for the private key" + }, :serial => ["$cadir/serial", "Where the serial number for certificates is stored."], - :privatedir => ["$ssldir/private", - "Where the client stores private certificate information."], - :passfile => ["$privatedir/password", - "Where puppetd stores the password for its private key. Generally - unused."], - :autosign => ["$confdir/autosign.conf", - "Whether to enable autosign. Valid values are true (which autosigns - any key request, and is a very bad idea), false (which never autosigns - any key request), and the path to a file, which uses that configuration - file to determine which keys to sign."], + :autosign => { :default => "$confdir/autosign.conf", + :mode => 0640, + :desc => "Whether to enable autosign. Valid values are true (which + autosigns any key request, and is a very bad idea), false (which + never autosigns any key request), and the path to a file, which + uses that configuration file to determine which keys to sign."}, :ca_days => [1825, "How long a certificate should be valid."], :ca_md => ["md5", "The type of hash used in certificates."], :req_bits => [2048, "The bit length of the certificates."], @@ -62,6 +69,7 @@ class Puppet::SSLCertificates::CA end def initialize(hash = {}) + Puppet.config.use(:puppet, :certificates, :ca) self.setconfig(hash) if Puppet[:capass] @@ -90,7 +98,11 @@ class Puppet::SSLCertificates::CA pass = "" 20.times { pass += (rand(74) + 48).chr } - Puppet.recmkdir(File.dirname(@config[:capass])) + # FIXME It's a hack that this still needs to be here :/ + unless FileTest.exists?(File.dirname(@config[:capass])) + Puppet::Util.recmkdir(File.dirname(@config[:capass]), 0770) + end + begin File.open(@config[:capass], "w", 0600) { |f| f.print pass } rescue Errno::EACCES => detail diff --git a/lib/puppet/storage.rb b/lib/puppet/storage.rb index 959d12c32..b9eb48d3a 100644 --- a/lib/puppet/storage.rb +++ b/lib/puppet/storage.rb @@ -29,7 +29,6 @@ module Puppet end def self.init - Puppet.debug "Initializing Storage" @@state = {} @@splitchar = "\t" end @@ -78,17 +77,18 @@ module Puppet end def self.store + Puppet.config.use(:puppet) Puppet.debug "Storing state" - unless FileTest.directory?(File.dirname(Puppet[:statefile])) - begin - Puppet.recmkdir(File.dirname(Puppet[:statefile])) - Puppet.info "Creating state directory %s" % - File.dirname(Puppet[:statefile]) - rescue => detail - Puppet.err "Could not create state file: %s" % detail - return - end - end +# unless FileTest.directory?(File.dirname(Puppet[:statefile])) +# begin +# Puppet.recmkdir(File.dirname(Puppet[:statefile])) +# Puppet.info "Creating state directory %s" % +# File.dirname(Puppet[:statefile]) +# rescue => detail +# Puppet.err "Could not create state file: %s" % detail +# return +# end +# end unless FileTest.exist?(Puppet[:statefile]) Puppet.info "Creating state file %s" % Puppet[:statefile] diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb index 588c0b71d..0b1e88553 100644 --- a/lib/puppet/transaction.rb +++ b/lib/puppet/transaction.rb @@ -11,7 +11,7 @@ require 'puppet/statechange' #--------------------------------------------------------------- module Puppet class Transaction - attr_accessor :toplevel, :component + attr_accessor :toplevel, :component, :objects #--------------------------------------------------------------- # a bit of a gross hack; a global list of objects that have failed to sync, diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index 2df667e0b..4dda52c06 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -289,7 +289,6 @@ class Type < Puppet::Element @types.each { |name, type| type.clear } - @finalized = false end # remove all of the instances of a single type @@ -321,32 +320,6 @@ class Type < Puppet::Element } end - # Perform any operations that need to be done between instance creation - # and instance evaluation. - def self.finalize - finished = {} - self.eachtype do |type| - type.each do |object| - unless finished.has_key?(object) - object.finish - finished[object] = true - end - end - end - self.mkdepends - - @finalized = true - end - - # Has the finalize method been called yet? - def self.finalized? - if defined? @finalized - return @finalized - else - return false - end - end - # does the type have an object with the given name? def self.has_key?(name) return @objects.has_key?(name) @@ -834,6 +807,16 @@ class Type < Puppet::Element end end + # Recurse deeply through the tree, but only yield types, not states. + def delve(&block) + self.each do |obj| + if obj.is_a? Puppet::Type + obj.delve(&block) + end + end + block.call(self) + end + # iterate across the existing states def eachstate # states() is a private method @@ -1023,8 +1006,16 @@ class Type < Puppet::Element if rmdeps Puppet::Event::Subscription.dependencies(self).each { |dep| + #begin + # self.unsubscribe(dep) + #rescue + # # ignore failed unsubscribes + #end + dep.delete + } + Puppet::Event::Subscription.subscribers(self).each { |dep| begin - self.unsubscribe(dep) + dep.unsubscribe(self) rescue # ignore failed unsubscribes end @@ -1198,10 +1189,13 @@ class Type < Puppet::Element unless hash.include?(:implicit) hash[:implicit] = true end - obj = self.create(hash) - obj.implicit = true + if obj = self.create(hash) + obj.implicit = true - return obj + return obj + else + return nil + end end # Is this type's name isomorphic with the object? That is, if the @@ -1223,6 +1217,7 @@ class Type < Puppet::Element def initvars @children = [] @evalcount = 0 + @tags = [] # callbacks are per object and event @callbacks = Hash.new { |chash, key| @@ -1387,7 +1382,6 @@ class Type < Puppet::Element next end end - # Skip autorequires that we already require next if self.requires?(obj) #self.info "Auto-requiring %s %s" % [obj.class.name, obj.name] @@ -1442,20 +1436,6 @@ class Type < Puppet::Element else self.fail "Could not find schedule %s" % self[:schedule] end -# if self[:schedule] -# elsif Puppet[:schedule] and ! Puppet[:ignoreschedules] -# # We handle schedule defaults here mostly because otherwise things -# # will behave very very erratically during testing. -# if sched = Puppet.type(:schedule)[Puppet[:schedule]] -# self[:schedule] = sched -# else -# self.fail "Could not find default schedule %s" % Puppet[:schedule] -# end -# else -# # While it's unlikely we won't have any schedule (since there's a -# # default), it's at least possible during testing -# return true -# end end # Check whether we are scheduled to run right now or not. @@ -1471,6 +1451,10 @@ class Type < Puppet::Element return schedule.match?(self.cached(:checked).to_i) end + def tag(tag) + @tags << tag + end + # Is the specified parameter set? def attrset?(type, attr) case type @@ -1789,28 +1773,6 @@ class Type < Puppet::Element # @callbacks[object][event] = method #end - # Build all of the dependencies for all of the different types. This is called - # after all of the objects are instantiated, so that we don't depend on - # file order. If we didn't use this (and instead just checked dependencies - # as we came across them), any required object would have to come before the - # requiring object in the file(s). - def self.mkdepends - @types.each { |name, type| - type.each { |obj| - obj.builddepends - } - } - end - - # The per-type version of dependency building. This actually goes through - # all of the objects themselves and builds deps. - def self.builddepends - return unless defined? @objects - @objects.each { |name, obj| - obj.builddepends - } - end - # Build the dependencies associated with an individual object. def builddepends # Handle the requires @@ -1832,11 +1794,11 @@ class Type < Puppet::Element end # return all objects subscribed to the current object - #def eachsubscriber - # Puppet::Event::Subscriptions.subscribers?(self).each { |sub| - # yield sub.targetobject - # } - #end + def eachsubscriber + Puppet::Event::Subscription.subscribers(self).each { |sub| + yield sub.target + } + end def handledepends(requires, event, method) # Requires are specified in the form of [type, name], so they're always @@ -1912,6 +1874,18 @@ class Type < Puppet::Element #@subscriptions.push sub end + def subscribesto?(object) + sub = false + self.eachsubscriber { |o| + if o == object + sub = true + break + end + } + + return sub + end + # Unsubscribe from a given object, possibly with a specific event. def unsubscribe(object, event = nil) Puppet::Event::Subscription.dependencies(self).find_all { |sub| @@ -1921,7 +1895,7 @@ class Type < Puppet::Element sub.source == object end }.each { |sub| - Puppet::Event::Subscription.delete(sub) + sub.delete } end diff --git a/lib/puppet/type/component.rb b/lib/puppet/type/component.rb index 5f7e7656a..1c0945f93 100644 --- a/lib/puppet/type/component.rb +++ b/lib/puppet/type/component.rb @@ -72,6 +72,32 @@ module Puppet def each @children.each { |child| yield child } end + + # Do all of the polishing off, mostly doing autorequires and making + # dependencies. This will get run once on the top-level component, + # and it will do everything necessary. + def finalize + finished = {} + + # First do all of the finish work, which mostly involves + self.delve do |object| + unless finished.has_key?(object) + object.finish + object.builddepends + finished[object] = true + end + end + + @finalized = true + end + + def finalized? + if defined? @finalized + return @finalized + else + return false + end + end # Return a flattened array containing all of the children # and all child components' children, sorted in order of dependencies. @@ -89,12 +115,7 @@ module Puppet # this is only called on one component over the whole system # this also won't work with scheduling, but eh def evaluate - # The normal client process will automatically finalize things, but - # this simplifies a lot of test code -- as long as we use a - # compontent, we get finalized. - unless Puppet::Type.finalized? - Puppet::Type.finalize - end + self.finalize unless self.finalized? transaction = Puppet::Transaction.new(self.flatten) transaction.component = self return transaction diff --git a/lib/puppet/type/pfile.rb b/lib/puppet/type/pfile.rb index ec0bb393f..9577acb19 100644 --- a/lib/puppet/type/pfile.rb +++ b/lib/puppet/type/pfile.rb @@ -96,12 +96,17 @@ module Puppet autorequire(:file) do cur = [] - # Skip the nil in the beginning and don't add ourselves as a prereq - # either. - self[:path].split(File::SEPARATOR)[1..-2].collect { |dir| - cur << dir - "/" + cur.join(File::SEPARATOR) - } + pary = self[:path].split(File::SEPARATOR) + pary.shift # remove the initial nil + pary.pop # remove us + + pary.inject([""]) do |ary, dir| + ary << dir + cur << ary.join(File::SEPARATOR) + ary + end + + cur end validate do diff --git a/lib/puppet/type/pfile/ensure.rb b/lib/puppet/type/pfile/ensure.rb index 8b5ad5aba..dfef404db 100755 --- a/lib/puppet/type/pfile/ensure.rb +++ b/lib/puppet/type/pfile/ensure.rb @@ -44,6 +44,12 @@ module Puppet newvalue(:directory) do mode = @parent.should(:mode) + parent = File.dirname(@parent[:path]) + unless FileTest.exists? parent + raise Puppet::Error, + "Cannot create %s; parent directory %s does not exist" % + [@parent[:path], parent] + end Puppet::Util.asuser(asuser()) { if mode Dir.mkdir(@parent[:path],mode) diff --git a/lib/puppet/type/pfile/group.rb b/lib/puppet/type/pfile/group.rb index 56aaa07f7..f01c69a1a 100755 --- a/lib/puppet/type/pfile/group.rb +++ b/lib/puppet/type/pfile/group.rb @@ -21,11 +21,20 @@ module Puppet # We want to print names, not numbers def is_to_s - id2name(@is) || @is + if @is.is_a? Integer + id2name(@is) || @is + else + return @is.to_s + end end def should_to_s - id2name(self.should) || self.should + should = self.should + if should.is_a? Integer + id2name(should) || should + else + return should.to_s + end end def retrieve @@ -38,60 +47,28 @@ module Puppet end end - munge do |value| - method = nil - gid = nil - gname = nil - - if value.is_a?(Integer) - method = :getgrgid - else - method = :getgrnam + # Determine if the group is valid, and if so, return the UID + def validgroup?(value) + if value =~ /^\d+$/ + value = value.to_i end - begin - group = Etc.send(method,value) - - # at one time, os x was putting the gid into the passwd - # field of the group struct, but that appears to not - # be the case any more - #os = Puppet::Fact["Operatingsystem"] - #case os - #when "Darwin": - # #gid = group.passwd - # gid = group.gid - #else - #end - - gid = group.gid - gname = group.name - - rescue ArgumentError => detail - raise Puppet::Error.new( - "Could not find group %s" % value) - rescue => detail - raise Puppet::Error.new( - "Could not find group %s: %s" % [self.should,detail]) - end - if gid.nil? - raise Puppet::Error.new( - "Could not retrieve gid for %s" % @parent.name) + if value = Puppet::Util.gid(value) + return value + else + return false end + end - #unless Process.uid == 0 - # groups = %x{groups}.chomp.split(/\s/) - # unless groups.include?(gname) - # self.notice "Cannot chgrp: not in group %s" % gname - # raise Puppet::Error.new( - # "Cannot chgrp: not in group %s" % gname) - # end - #end + munge do |value| + method = nil + gid = nil + gname = nil - if gid.nil? - raise Puppet::Error.new( - "Nil gid for %s" % @parent.name) + if val = validgroup?(value) + return val else - return gid + return value end end @@ -114,9 +91,14 @@ module Puppet end end + gid = nil + unless gid = Puppet::Util.gid(self.should) + raise Puppet::Error, "Could not find group %s" % self.should + end + begin # set owner to nil so it's ignored - File.chown(nil,self.should,@parent[:path]) + File.chown(nil,gid,@parent[:path]) rescue => detail error = Puppet::Error.new( "failed to chgrp %s to %s: %s" % [@parent[:path], self.should, detail.message]) diff --git a/lib/puppet/type/pfile/mode.rb b/lib/puppet/type/pfile/mode.rb index 3aeaca7be..26c1c2449 100755 --- a/lib/puppet/type/pfile/mode.rb +++ b/lib/puppet/type/pfile/mode.rb @@ -93,9 +93,8 @@ module Puppet if @is == :absent @parent.stat(true) self.retrieve - self.debug "%s: after refresh, is '%o'" % [self.class.name,@is] if @is == :absent - self.info "File does not exist; cannot set mode" % + self.debug "File does not exist; cannot set mode" % @parent[:path] return nil end |