diff options
author | Luke Kanies <luke@madstop.com> | 2008-04-11 13:01:42 -0500 |
---|---|---|
committer | Luke Kanies <luke@madstop.com> | 2008-04-11 13:01:42 -0500 |
commit | fb05ef3c96038d67a46eb142202af186ad6cb0b3 (patch) | |
tree | 148e8b882e5c8104c4f3fa8ecc4288e8608f812d /lib/puppet | |
parent | b49fb68f768e8b98c555ef0ae08a7bd22f5d36bd (diff) | |
parent | b49fd495622b15f96faf944db1e70cbe9e7fe7c4 (diff) | |
download | puppet-fb05ef3c96038d67a46eb142202af186ad6cb0b3.tar.gz puppet-fb05ef3c96038d67a46eb142202af186ad6cb0b3.tar.xz puppet-fb05ef3c96038d67a46eb142202af186ad6cb0b3.zip |
Merge branch '0.24.x'
Diffstat (limited to 'lib/puppet')
45 files changed, 410 insertions, 556 deletions
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index 0f01c2ee2..eed1a00f3 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -128,7 +128,7 @@ module Puppet This is more useful as a server-side setting than client, but any environment chosen must be in this list. Values should be separated by a comma."], - :environment => {:default => "development", :desc => "The environment Puppet is running in. For clients + :environment => {:default => "production", :desc => "The environment Puppet is running in. For clients (e.g., ``puppetd``) this determines the environment itself, which is used to find modules and much more. For servers (i.e., ``puppetmasterd``) this provides the default environment for nodes diff --git a/lib/puppet/dsl.rb b/lib/puppet/dsl.rb index 966feaf9b..714b350f8 100644 --- a/lib/puppet/dsl.rb +++ b/lib/puppet/dsl.rb @@ -1,7 +1,7 @@ # Just quick mess-around to see what a DSL would look like. # # This is what the executable could look like: -##!/usr/bin/ruby +##!/usr/bin/env ruby # #require 'puppet' #require 'puppet/dsl' @@ -23,7 +23,7 @@ # And here's what an example config could look like: # -##!/usr/bin/ruby +##!/usr/bin/env ruby # # # require 'puppet' diff --git a/lib/puppet/external/nagios.rb b/lib/puppet/external/nagios.rb index 78459fcb6..0dcae4c6d 100755 --- a/lib/puppet/external/nagios.rb +++ b/lib/puppet/external/nagios.rb @@ -1,4 +1,4 @@ -#!/usr/local/bin/ruby -w +#!/usr/bin/env ruby -w #-------------------- # A script to retrieve hosts from ldap and create an importable diff --git a/lib/puppet/external/nagios/base.rb b/lib/puppet/external/nagios/base.rb index efc3982b4..25c689559 100755 --- a/lib/puppet/external/nagios/base.rb +++ b/lib/puppet/external/nagios/base.rb @@ -228,7 +228,9 @@ class Nagios::Base # This is probably a bad idea. def name=(value) - send(self.class.namevar.to_s + "=", value) + unless self.class.namevar.to_s == "name" + send(self.class.namevar.to_s + "=", value) + end end def namevar @@ -318,59 +320,64 @@ class Nagios::Base self.class.name end - # object types - newtype :command do - setparameters :command_name, :command_line - end + # object types + newtype :command do + setparameters :command_name, :command_line + end - newtype :contact do + newtype :contact do setparameters :contact_name, :alias, :host_notification_period, - :host_notification_commands, :service_notification_period, - :service_notification_commands, - :email, :pager, :service_notification_options, :host_notification_options + :host_notification_commands, :service_notification_period, + :service_notification_commands, :register, :email, :pager, + :service_notification_options, :host_notification_options setsuperior "person" - end + end - newtype :contactgroup do - setparameters :contactgroup_name, :alias, :members - end + newtype :contactgroup do + setparameters :contactgroup_name, :alias, :members + end - newtype :host do + newtype :host do setparameters :host_name, :notifications_enabled, :event_handler_enabled, - :flap_detection_enabled, :process_perf_data, :retain_status_information, - :retain_nonstatus_information, :register, :use, :alias, - :address, :check_command, :max_check_attempts, :notification_interval, - :notification_period, :notification_options, :checks_enabled, - :failure_prediction_enabled, :parents + :flap_detection_enabled, :process_perf_data, :retain_status_information, + :retain_nonstatus_information, :register, :use, :alias, + :address, :check_command, :max_check_attempts, :notification_interval, + :notification_period, :notification_options, :checks_enabled, + :failure_prediction_enabled, :parents, :contact_groups setsuperior "person" - map :address => "ipHostNumber" - end - - newtype :hostextinfo do - auxiliary = true + end + newtype :hostextinfo do + auxiliary = true setparameters :host_name, :notes_url, :icon_image, :icon_image_alt, :vrml_image, - "2d_coords".intern, "3d_coords".intern + "2d_coords".intern, "3d_coords".intern setnamevar :host_name - end + end - newtype :hostgroup do + newtype :hostgroup do setparameters :hostgroup_name, :alias, :contact_groups, :members - end + end + + newtype :hostescalation do + setparameters :name, :first_notification, :last_notification, + :notification_interval, :contact_groups, + :escalation_options, :register, :hostgroup_name + setnamevar :name + end - newtype :hostgroupescalation do - auxiliary = true + newtype :hostgroupescalation do + auxiliary = true setparameters :hostgroup_name, :first_notification, :last_notification, - :contact_groups, :notification_interval + :contact_groups, :notification_interval setnamevar :hostgroup_name - end + end - newtype :service do + newtype :service do attach :host => :host_name setparameters :name, :active_checks_enabled, :passive_checks_enabled, :parallelize_check, :obsess_over_service, :check_freshness, @@ -381,41 +388,48 @@ class Nagios::Base :normal_check_interval, :retry_check_interval, :contact_groups, :notification_interval, :notification_period, :notification_options, :service_description, :host_name, :freshness_threshold, - :check_command + :check_command, :hostgroup_name, :event_handler, :servicegroups, :host suppress :host_name setnamevar :service_description - end + end - newtype :servicedependency do + newtype :servicedependency do auxiliary = true setparameters :host_name, :service_description, :dependent_host_name, - :dependent_service_description, :execution_failure_criteria, - :notification_failure_criteria + :dependent_service_description, :execution_failure_criteria, + :notification_failure_criteria, :hostgroup_name, + :dependent_hostgroup_name setnamevar :host_name - end + end newtype :serviceescalation do setparameters :host_name, :service_description, :first_notification, - :last_notification, :contact_groups, :notification_interval + :last_notification, :contact_groups, :notification_interval, :hostgroup_name setnamevar :host_name end - newtype :serviceextinfo do + newtype :servicegroup do + setparameters :servicegroup_name, :alias + + setnamevar :servicegroup_name + end + + newtype :serviceextinfo do auxiliary = true setparameters :host_name, :service_description, :icon_image, :icon_image_alt setnamevar :host_name - end + end - newtype :timeperiod do - setparameters :timeperiod_name, :alias, :sunday, :monday, :tuesday, :wednesday, - :thursday, :friday, :saturday - end + newtype :timeperiod do + setparameters :timeperiod_name, :alias, :sunday, :monday, :tuesday, + :wednesday, :thursday, :friday, :saturday + end end # $Id$ diff --git a/lib/puppet/file_serving/indirection_hooks.rb b/lib/puppet/file_serving/indirection_hooks.rb index 141642efe..66ed169dc 100644 --- a/lib/puppet/file_serving/indirection_hooks.rb +++ b/lib/puppet/file_serving/indirection_hooks.rb @@ -12,7 +12,8 @@ module Puppet::FileServing::IndirectionHooks PROTOCOL_MAP = {"puppet" => :rest, "file" => :file, "puppetmounts" => :file_server} # Pick an appropriate terminus based on the protocol. - def select_terminus(full_uri, options = {}) + def select_terminus(request) + full_uri = request.key # Short-circuit to :file if it's a fully-qualified path. return PROTOCOL_MAP["file"] if full_uri =~ /^#{::File::SEPARATOR}/ begin @@ -29,11 +30,12 @@ module Puppet::FileServing::IndirectionHooks terminus = :file_server end + # This is the backward-compatible module terminus. if terminus == :file_server and uri.path =~ %r{^/([^/]+)\b} modname = $1 if modname == "modules" terminus = :modules - elsif terminus(:modules).find_module(modname, options[:node]) + elsif terminus(:modules).find_module(modname, request.options[:node]) Puppet.warning "DEPRECATION NOTICE: Found file '%s' in module without using the 'modules' mount; please prefix path with '/modules'" % uri.path terminus = :modules end diff --git a/lib/puppet/file_serving/metadata.rb b/lib/puppet/file_serving/metadata.rb index 56712122c..beecaef48 100644 --- a/lib/puppet/file_serving/metadata.rb +++ b/lib/puppet/file_serving/metadata.rb @@ -11,15 +11,6 @@ require 'puppet/file_serving/indirection_hooks' # A class that handles retrieving file metadata. class Puppet::FileServing::Metadata < Puppet::FileServing::FileBase - module MetadataHelper - include Puppet::FileServing::IndirectionHooks - - def post_find(instance) - end - - def post_search(key, options = {}) - end - end include Puppet::Util::Checksums diff --git a/lib/puppet/indirector.rb b/lib/puppet/indirector.rb index c30c097b2..2402b9cbe 100644 --- a/lib/puppet/indirector.rb +++ b/lib/puppet/indirector.rb @@ -9,6 +9,7 @@ module Puppet::Indirector require 'puppet/indirector/indirection' require 'puppet/indirector/terminus' + require 'puppet/indirector/envelope' # Declare that the including class indirects its methods to # this terminus. The terminus name must be the name of a Puppet @@ -20,6 +21,7 @@ module Puppet::Indirector # populate this class with the various new methods extend ClassMethods include InstanceMethods + include Puppet::Indirector::Envelope # instantiate the actual Terminus for that type and this name (:ldap, w/ args :node) # & hook the instantiated Terminus into this class (Node: @indirection = terminus) @@ -28,41 +30,37 @@ module Puppet::Indirector end module ClassMethods - attr_reader :indirection + attr_reader :indirection - def cache_class=(klass) - indirection.cache_class = klass - end + def cache_class=(klass) + indirection.cache_class = klass + end - def terminus_class=(klass) - indirection.terminus_class = klass - end + def terminus_class=(klass) + indirection.terminus_class = klass + end - def find(*args) - indirection.find(*args) - end - - def destroy(*args) - indirection.destroy(*args) - end + # Expire any cached instance. + def expire(*args) + indirection.expire *args + end + + def find(*args) + indirection.find *args + end - def search(*args) - indirection.search(*args) - end + def destroy(*args) + indirection.destroy *args + end - def version(*args) - indirection.version(*args) - end + def search(*args) + indirection.search *args + end end module InstanceMethods - # Make it easy for the model to set versions, - # which are used for caching and such. - attr_accessor :version - - # these become instance methods - def save(*args) - self.class.indirection.save(self, *args) - end + def save(*args) + self.class.indirection.save self, *args + end end end diff --git a/lib/puppet/indirector/catalog/compiler.rb b/lib/puppet/indirector/catalog/compiler.rb index 6d769b97d..2b5e8d912 100644 --- a/lib/puppet/indirector/catalog/compiler.rb +++ b/lib/puppet/indirector/catalog/compiler.rb @@ -13,15 +13,13 @@ class Puppet::Node::Catalog::Compiler < Puppet::Indirector::Code attr_accessor :code # Compile a node's catalog. - def find(key, client = nil, clientip = nil) - if key.is_a?(Puppet::Node) - node = key - else - node = find_node(key) + def find(request) + unless node = request.options[:node] || find_node(request.key) + raise ArgumentError, "Could not find node '%s'; cannot compile" % request.key end if catalog = compile(node) - return catalog.to_transportable + return catalog else # This shouldn't actually happen; we should either return # a config or raise an exception. @@ -46,22 +44,6 @@ class Puppet::Node::Catalog::Compiler < Puppet::Indirector::Code $0 =~ /puppetmasterd/ end - # Return the catalog version. Here we're returning the - # latest of the node, fact, or parse date. These are the - # three things that go into compiling a client catalog, - # so changes in any of them result in changes. - # LAK:FIXME Note that this only works when all three sources - # use timestamps; once one of them moves to using real versions, - # the comparison stops working. - def version(key) - if node = Puppet::Node.find_by_any_name(key) - return [Puppet::Node.version(key).to_f, Puppet::Node::Facts.version(key).to_f, interpreter.catalog_version(node).to_f].sort[-1] - else - # This is the standard for "got nothing for ya". - 0 - end - end - private # Add any extra data necessary to the node. @@ -102,16 +84,12 @@ class Puppet::Node::Catalog::Compiler < Puppet::Indirector::Code def find_node(key) # If we want to use the cert name as our key # LAK:FIXME This needs to be figured out somehow, but it requires the routing. + # This should be able to use the request, yay. #if Puppet[:node_name] == 'cert' and client # key = client #end - # Note that this is reasonable, because either their node source should actually - # know about the node, or they should be using the ``null`` node source, which - # will always return data. - unless node = Puppet::Node.find_by_any_name(key) - raise Puppet::Error, "Could not find node '%s'" % key - end + return nil unless node = Puppet::Node.find_by_any_name(key) # Add any external data to the node. add_node_data(node) diff --git a/lib/puppet/indirector/checksum/file.rb b/lib/puppet/indirector/checksum/file.rb index 3b196a1f8..5489b40e8 100644 --- a/lib/puppet/indirector/checksum/file.rb +++ b/lib/puppet/indirector/checksum/file.rb @@ -18,8 +18,8 @@ class Puppet::Checksum::File < Puppet::Indirector::File path.join(File::SEPARATOR) end - def save(file) - path = File.dirname(path(file.name)) + def save(request) + path = File.dirname(path(request.key)) # Make the directories if necessary. unless FileTest.directory?(path) diff --git a/lib/puppet/indirector/direct_file_server.rb b/lib/puppet/indirector/direct_file_server.rb index 31cc9aa16..1711356f9 100644 --- a/lib/puppet/indirector/direct_file_server.rb +++ b/lib/puppet/indirector/direct_file_server.rb @@ -11,17 +11,17 @@ class Puppet::Indirector::DirectFileServer < Puppet::Indirector::Terminus include Puppet::Util::URIHelper include Puppet::FileServing::TerminusHelper - def find(key, options = {}) - uri = key2uri(key) + def find(request) + uri = key2uri(request.key) return nil unless FileTest.exists?(uri.path) - instance = model.new(key, :path => uri.path) - instance.links = options[:links] if options[:links] + instance = model.new(request.key, :path => uri.path) + instance.links = request.options[:links] if request.options[:links] return instance end - def search(key, options = {}) - uri = key2uri(key) + def search(request) + uri = key2uri(request.key) return nil unless FileTest.exists?(uri.path) - path2instances(key, uri.path, options) + path2instances(request.key, uri.path, request.options) end end diff --git a/lib/puppet/indirector/envelope.rb b/lib/puppet/indirector/envelope.rb new file mode 100644 index 000000000..ef7952ef6 --- /dev/null +++ b/lib/puppet/indirector/envelope.rb @@ -0,0 +1,13 @@ +require 'puppet/indirector' + +# Provide any attributes or functionality needed for indirected +# instances. +module Puppet::Indirector::Envelope + attr_accessor :expiration + + def expired? + return false unless expiration + return false if expiration >= Time.now + return true + end +end diff --git a/lib/puppet/indirector/exec.rb b/lib/puppet/indirector/exec.rb index 7e4ac8d18..2462e31da 100644 --- a/lib/puppet/indirector/exec.rb +++ b/lib/puppet/indirector/exec.rb @@ -3,9 +3,9 @@ require 'puppet/util' class Puppet::Indirector::Exec < Puppet::Indirector::Terminus # Look for external node definitions. - def find(name) + def find(request) # Run the command. - unless output = query(name) + unless output = query(request.key) return nil end diff --git a/lib/puppet/indirector/facts/facter.rb b/lib/puppet/indirector/facts/facter.rb index a8c47e3bf..465d90c13 100644 --- a/lib/puppet/indirector/facts/facter.rb +++ b/lib/puppet/indirector/facts/facter.rb @@ -56,8 +56,8 @@ class Puppet::Node::Facts::Facter < Puppet::Indirector::Code end # Look a host's facts up in Facter. - def find(key) - Puppet::Node::Facts.new(key, Facter.to_hash) + def find(request) + Puppet::Node::Facts.new(request.key, Facter.to_hash) end def save(facts) diff --git a/lib/puppet/indirector/file.rb b/lib/puppet/indirector/file.rb index c2d36c46b..e5382155f 100644 --- a/lib/puppet/indirector/file.rb +++ b/lib/puppet/indirector/file.rb @@ -2,26 +2,28 @@ require 'puppet/indirector/terminus' # An empty terminus type, meant to just return empty objects. class Puppet::Indirector::File < Puppet::Indirector::Terminus - def destroy(file) + # Remove files on disk. + def destroy(request) if respond_to?(:path) - path = path(file.name) + path = path(request.key) else - path = file.path + path = request.key end - raise Puppet::Error.new("File %s does not exist; cannot destroy" % [file]) unless File.exist?(path) + raise Puppet::Error.new("File %s does not exist; cannot destroy" % [request.key]) unless File.exist?(path) begin File.unlink(path) rescue => detail - raise Puppet::Error, "Could not remove %s: %s" % [file, detail] + raise Puppet::Error, "Could not remove %s: %s" % [request.key, detail] end end - def find(name) + # Return a model instance for a given file on disk. + def find(request) if respond_to?(:path) - path = path(name) + path = path(request.key) else - path = name + path = request.key end return nil unless File.exist?(path) @@ -35,20 +37,21 @@ class Puppet::Indirector::File < Puppet::Indirector::Terminus return model.new(content) end - def save(file) + # Save a new file to disk. + def save(request) if respond_to?(:path) - path = path(file.name) + path = path(request.key) else - path = file.path + path = request.key end dir = File.dirname(path) - raise Puppet::Error.new("Cannot save %s; parent directory %s does not exist" % [file, dir]) unless File.directory?(dir) + raise Puppet::Error.new("Cannot save %s; parent directory %s does not exist" % [request.key, dir]) unless File.directory?(dir) begin - File.open(path, "w") { |f| f.print file.content } + File.open(path, "w") { |f| f.print request.instance.content } rescue => detail - raise Puppet::Error, "Could not write %s: %s" % [file, detail] + raise Puppet::Error, "Could not write %s: %s" % [request.key, detail] end end end diff --git a/lib/puppet/indirector/file_metadata/file.rb b/lib/puppet/indirector/file_metadata/file.rb index b36846bbe..c46015c38 100644 --- a/lib/puppet/indirector/file_metadata/file.rb +++ b/lib/puppet/indirector/file_metadata/file.rb @@ -9,14 +9,14 @@ require 'puppet/indirector/direct_file_server' class Puppet::Indirector::FileMetadata::File < Puppet::Indirector::DirectFileServer desc "Retrieve file metadata directly from the local filesystem." - def find(key, options = {}) + def find(request) return unless data = super data.collect_attributes return data end - def search(key, options = {}) + def search(request) return unless result = super result.each { |instance| instance.collect_attributes } diff --git a/lib/puppet/indirector/indirection.rb b/lib/puppet/indirector/indirection.rb index d47433c60..15358a801 100644 --- a/lib/puppet/indirector/indirection.rb +++ b/lib/puppet/indirector/indirection.rb @@ -1,4 +1,6 @@ require 'puppet/util/docs' +require 'puppet/indirector/envelope' +require 'puppet/indirector/request' # The class that connects functional classes with their different collection # back-ends. Each indirection has a set of associated terminus classes, @@ -28,8 +30,7 @@ class Puppet::Indirector::Indirection # Find an indirected model by name. This is provided so that Terminus classes # can specifically hook up with the indirections they are associated with. def self.model(name) - match = @@indirections.find { |i| i.name == name } - return nil unless match + return nil unless match = @@indirections.find { |i| i.name == name } match.model end @@ -65,6 +66,25 @@ class Puppet::Indirector::Indirection @@indirections.delete(self) if @@indirections.include?(self) end + # Set the time-to-live for instances created through this indirection. + def ttl=(value) + raise ArgumentError, "Indirection TTL must be an integer" unless value.is_a?(Fixnum) + @ttl = value + end + + # Default to the runinterval for the ttl. + def ttl + unless defined?(@ttl) + @ttl = Puppet[:runinterval].to_i + end + @ttl + end + + # Calculate the expiration date for a returned instance. + def expiration + Time.now + ttl + end + # Generate the full doc string. def doc text = "" @@ -106,6 +126,11 @@ class Puppet::Indirector::Indirection end end + # Set up our request object. + def request(method, key, arguments = nil) + Puppet::Indirector::Request.new(self.name, method, key, arguments) + end + # Return the singleton terminus for this indirection. def terminus(terminus_name = nil) # Get the name of the terminus. @@ -147,83 +172,124 @@ class Puppet::Indirector::Indirection end end - def find(key, *args) - # Select the appropriate terminus if there's a hook - # for doing so. This allows the caller to pass in some kind - # of URI that the indirection can use for routing to the appropriate - # terminus. - if respond_to?(:select_terminus) - terminus_name = select_terminus(key, *args) - else - terminus_name = terminus_class - end + # Expire a cached object, if one is cached. Note that we don't actually + # remove it, we expire it and write it back out to disk. This way people + # can still use the expired object if they want. + def expire(key, *args) + request = request(:expire, key, *args) + + return nil unless cache? + + return nil unless instance = cache.find(request(:find, key, *args)) + + Puppet.info "Expiring the %s cache of %s" % [self.name, instance.name] - check_authorization(:find, terminus_name, ([key] + args)) + # Set an expiration date in the past + instance.expiration = Time.now - 60 + + cache.save(request(:save, instance, *args)) + end + + # Search for an instance in the appropriate terminus, caching the + # results if caching is configured.. + def find(key, *args) + request = request(:find, key, *args) + terminus = prepare(request) # See if our instance is in the cache and up to date. - if cache? and cache.has_most_recent?(key, terminus(terminus_name).version(key)) - Puppet.debug "Using cached %s %s" % [self.name, key] - return cache.find(key, *args) + if cache? and cached = cache.find(request) + if cached.expired? + Puppet.info "Not using expired %s for %s from cache; expired at %s" % [self.name, request.key, cached.expiration] + else + Puppet.debug "Using cached %s for %s" % [self.name, request.key] + return cached + end end # Otherwise, return the result from the terminus, caching if appropriate. - if result = terminus(terminus_name).find(key, *args) - result.version ||= Time.now.utc + if result = terminus.find(request) + result.expiration ||= self.expiration if cache? - Puppet.info "Caching %s %s" % [self.name, key] - cache.save(result, *args) + Puppet.info "Caching %s for %s" % [self.name, request.key] + cache.save request(:save, result, *args) end - terminus(terminus_name).post_find(result) if terminus(terminus_name).respond_to?(:post_find) - return result end - end - def destroy(*args) - check_authorization(:destroy, terminus_class, args) - - terminus.destroy(*args) + return nil end - def search(*args) - check_authorization(:search, terminus_class, args) + # Remove something via the terminus. + def destroy(key, *args) + request = request(:destroy, key, *args) + terminus = prepare(request) - result = terminus.search(*args) + terminus.destroy(request) - terminus().post_search(result) if terminus().respond_to?(:post_search) + if cache? and cached = cache.find(request(:find, key, *args)) + # Reuse the existing request, since it's equivalent. + cache.destroy(request) + end - result + nil end - # these become instance methods - def save(instance, *args) - check_authorization(:save, terminus_class, ([instance] + args)) + # Search for more than one instance. Should always return an array. + def search(key, *args) + request = request(:search, key, *args) + terminus = prepare(request) - instance.version ||= Time.now.utc - dest = cache? ? cache : terminus - return if dest.has_most_recent?(instance.name, instance.version) - Puppet.info "Caching %s %s" % [self.name, instance.name] if cache? - cache.save(instance, *args) if cache? - terminus.save(instance, *args) + if result = terminus.search(request) + raise Puppet::DevError, "Search results from terminus %s are not an array" % terminus.name unless result.is_a?(Array) + + result.each do |instance| + instance.expiration ||= self.expiration + end + return result + end end - def version(*args) - terminus.version(*args) + # Save the instance in the appropriate terminus. This method is + # normally an instance method on the indirected class. + def save(instance, *args) + request = request(:save, instance, *args) + terminus = prepare(request) + + # If caching is enabled, save our document there + cache.save(request) if cache? + terminus.save(request) end private # Check authorization if there's a hook available; fail if there is one # and it returns false. - def check_authorization(method, terminus_name, arguments) - # Don't check authorization if there's no node. - # LAK:FIXME This is a hack and is quite possibly not the design we want. - return unless arguments[-1].is_a?(Hash) and arguments[-1][:node] + def check_authorization(request, terminus) + # At this point, we're assuming authorization makes no sense without + # client information. + return unless request.options[:node] + + # This is only to authorize via a terminus-specific authorization hook. + return unless terminus.respond_to?(:authorized?) + + unless terminus.authorized?(request) + raise ArgumentError, "Not authorized to call %s on %s with %s" % [request.method, request.key, request.options.inspect] + end + end - if terminus(terminus_name).respond_to?(:authorized?) and ! terminus(terminus_name).authorized?(method, *arguments) - raise ArgumentError, "Not authorized to call %s with %s" % [method, arguments[0]] + # Setup a request, pick the appropriate terminus, check the request's authorization, and return it. + def prepare(request) + # Pick our terminus. + if respond_to?(:select_terminus) + terminus_name = select_terminus(request) + else + terminus_name = terminus_class end + + check_authorization(request, terminus(terminus_name)) + + return terminus(terminus_name) end # Create a new terminus instance. diff --git a/lib/puppet/indirector/ldap.rb b/lib/puppet/indirector/ldap.rb index fb883def6..07ad38933 100644 --- a/lib/puppet/indirector/ldap.rb +++ b/lib/puppet/indirector/ldap.rb @@ -2,10 +2,10 @@ require 'puppet/indirector/terminus' class Puppet::Indirector::Ldap < Puppet::Indirector::Terminus # Perform our ldap search and process the result. - def find(name) + def find(request) # We have to use 'yield' here because the LDAP::Entry objects # get destroyed outside the scope of the search, strangely. - ldapsearch(name) { |entry| return process(name, entry) } + ldapsearch(request.key) { |entry| return process(request.key, entry) } # Return nil if we haven't found something. return nil diff --git a/lib/puppet/indirector/memory.rb b/lib/puppet/indirector/memory.rb index 5bfcec95d..19acc14e2 100644 --- a/lib/puppet/indirector/memory.rb +++ b/lib/puppet/indirector/memory.rb @@ -6,16 +6,16 @@ class Puppet::Indirector::Memory < Puppet::Indirector::Terminus @instances = {} end - def destroy(instance) - raise ArgumentError.new("Could not find %s to destroy" % instance) unless @instances.include?(instance.name) - @instances.delete(instance.name) + def destroy(request) + raise ArgumentError.new("Could not find %s to destroy" % request.key) unless @instances.include?(request.key) + @instances.delete(request.key) end - def find(name) - @instances[name] + def find(request) + @instances[request.key] end - def save(instance) - @instances[instance.name] = instance + def save(request) + @instances[request.key] = request.instance end end diff --git a/lib/puppet/indirector/node/exec.rb b/lib/puppet/indirector/node/exec.rb index dcfc625b2..52cbc370c 100644 --- a/lib/puppet/indirector/node/exec.rb +++ b/lib/puppet/indirector/node/exec.rb @@ -15,20 +15,13 @@ class Puppet::Node::Exec < Puppet::Indirector::Exec end # Look for external node definitions. - def find(name) + def find(request) output = super or return nil # Translate the output to ruby. - result = translate(name, output) + result = translate(request.key, output) - return create_node(name, result) - end - - # Use the version of the facts, since we assume that's the main thing - # that changes. If someone wants their own way of defining version, - # they can easily provide their own, um, version of this class. - def version(name) - Puppet::Node::Facts.version(name) + return create_node(request.key, result) end private diff --git a/lib/puppet/indirector/node/ldap.rb b/lib/puppet/indirector/node/ldap.rb index 73b5cdd70..6c41c18d4 100644 --- a/lib/puppet/indirector/node/ldap.rb +++ b/lib/puppet/indirector/node/ldap.rb @@ -12,8 +12,11 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap end # Look for our node in ldap. - def find(name) + def find(request) return nil unless information = super + + name = request.key + node = Puppet::Node.new(name) parent_info = nil @@ -123,8 +126,4 @@ class Puppet::Node::Ldap < Puppet::Indirector::Ldap end filter end - - def version(name) - Puppet::Node::Facts.version(name) - end end diff --git a/lib/puppet/indirector/node/plain.rb b/lib/puppet/indirector/node/plain.rb index 8058563e6..37ceb064d 100644 --- a/lib/puppet/indirector/node/plain.rb +++ b/lib/puppet/indirector/node/plain.rb @@ -11,16 +11,9 @@ class Puppet::Node::Plain < Puppet::Indirector::Plain node instance before it is returned." # Just return an empty node. - def find(name) + def find(request) node = super node.fact_merge node end - - # Use the version of the facts, since we assume that's the main thing - # that changes. If someone wants their own way of defining version, - # they can easily provide their own, um, version of this class. - def version(name) - Puppet::Node::Facts.version(name) - end end diff --git a/lib/puppet/indirector/plain.rb b/lib/puppet/indirector/plain.rb index 8bdf8469c..2caa0946d 100644 --- a/lib/puppet/indirector/plain.rb +++ b/lib/puppet/indirector/plain.rb @@ -3,7 +3,7 @@ require 'puppet/indirector/terminus' # An empty terminus type, meant to just return empty objects. class Puppet::Indirector::Plain < Puppet::Indirector::Terminus # Just return nothing. - def find(name) - indirection.model.new(name) + def find(request) + indirection.model.new(request.key) end end diff --git a/lib/puppet/indirector/report/processor.rb b/lib/puppet/indirector/report/processor.rb index fa2b7f36b..135f1649d 100644 --- a/lib/puppet/indirector/report/processor.rb +++ b/lib/puppet/indirector/report/processor.rb @@ -10,8 +10,8 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code Puppet.settings.use(:main, :reporting, :metrics) end - def save(report) - process(report) + def save(request) + process(request.instance) end private diff --git a/lib/puppet/indirector/request.rb b/lib/puppet/indirector/request.rb new file mode 100644 index 000000000..68b7ee160 --- /dev/null +++ b/lib/puppet/indirector/request.rb @@ -0,0 +1,25 @@ +require 'puppet/indirector' + +# Provide any attributes or functionality needed for indirected +# instances. +class Puppet::Indirector::Request + attr_accessor :indirection_name, :key, :method, :options, :instance + + def initialize(indirection_name, method, key, options = {}) + @indirection_name, @method, @options = indirection_name, method, (options || {}) + + if key.is_a?(String) or key.is_a?(Symbol) + @key = key + else + @instance = key + @key = @instance.name + end + + raise ArgumentError, "Request options must be a hash, not %s" % @options.class unless @options.is_a?(Hash) + end + + # Look up the indirection based on the name provided. + def indirection + Puppet::Indirector::Indirection.instance(@indirection_name) + end +end diff --git a/lib/puppet/indirector/terminus.rb b/lib/puppet/indirector/terminus.rb index 3015c8a37..22c56a4d2 100644 --- a/lib/puppet/indirector/terminus.rb +++ b/lib/puppet/indirector/terminus.rb @@ -128,20 +128,6 @@ class Puppet::Indirector::Terminus end end - # Do we have an update for this object? This compares the provided version - # to our version, and returns true if our version is at least as high - # as the asked-about version. - def has_most_recent?(key, vers) - raise Puppet::DevError.new("Cannot check update status when no 'version' method is defined") unless respond_to?(:version) - - if existing_version = version(key) - #puts "%s fresh: %s (%s vs %s)" % [self.name, (existing_version.to_f >= vers.to_f).inspect, existing_version.to_f, vers.to_f] - existing_version.to_f >= vers.to_f - else - false - end - end - def indirection self.class.indirection end @@ -163,17 +149,4 @@ class Puppet::Indirector::Terminus def terminus_type self.class.terminus_type end - - # Provide a default method for retrieving an instance's version. - # By default, just find the resource and get its version. Individual - # terminus types can override this method to provide custom definitions of - # 'versions'. - def version(name) - raise Puppet::DevError.new("Cannot retrieve an instance's version without a :find method") unless respond_to?(:find) - if instance = find(name) - instance.version - else - nil - end - end end diff --git a/lib/puppet/indirector/yaml.rb b/lib/puppet/indirector/yaml.rb index 4dd29159e..23bca02b8 100644 --- a/lib/puppet/indirector/yaml.rb +++ b/lib/puppet/indirector/yaml.rb @@ -3,23 +3,22 @@ require 'puppet/indirector/terminus' # The base class for YAML indirection termini. class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus # Read a given name's file in and convert it from YAML. - def find(name) - raise ArgumentError.new("You must specify the name of the object to retrieve") unless name - file = path(name) + def find(request) + file = path(request.key) return nil unless FileTest.exist?(file) begin return from_yaml(File.read(file)) rescue => detail - raise Puppet::Error, "Could not read YAML data for %s %s: %s" % [indirection.name, name, detail] + raise Puppet::Error, "Could not read YAML data for %s %s: %s" % [indirection.name, request.key, detail] end end # Convert our object to YAML and store it to the disk. - def save(object) - raise ArgumentError.new("You can only save objects that respond to :name") unless object.respond_to?(:name) + def save(request) + raise ArgumentError.new("You can only save objects that respond to :name") unless request.instance.respond_to?(:name) - file = path(object.name) + file = path(request.key) basedir = File.dirname(file) @@ -29,15 +28,15 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus end begin - File.open(file, "w", 0660) { |f| f.print to_yaml(object) } + File.open(file, "w", 0660) { |f| f.print to_yaml(request.instance) } rescue TypeError => detail - Puppet.err "Could not save %s %s: %s" % [self.name, object.name, detail] + Puppet.err "Could not save %s %s: %s" % [self.name, request.key, detail] end end - def version(name) - return nil unless FileTest.exist?(path(name)) - return File.stat(path(name)).mtime + # Return the path to a given node's file. + def path(name) + File.join(Puppet[:yamldir], self.class.indirection_name.to_s, name.to_s + ".yaml") end private @@ -49,9 +48,4 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus def to_yaml(object) YAML.dump(object) end - - # Return the path to a given node's file. - def path(name) - File.join(Puppet[:yamldir], self.class.indirection_name.to_s, name.to_s + ".yaml") - end end diff --git a/lib/puppet/metatype/attributes.rb b/lib/puppet/metatype/attributes.rb index b83fcdd78..3f48f22ff 100644 --- a/lib/puppet/metatype/attributes.rb +++ b/lib/puppet/metatype/attributes.rb @@ -477,13 +477,9 @@ class Puppet::Type end if obj = @parameters[name] - # We throw a failure here, because this method is too - # ambiguous when used with properties. - if obj.is_a?(Puppet::Property) - fail "[] called on a property" - else - return obj.value - end + # Note that if this is a property, then the value is the "should" value, + # not the current value. + obj.value else return nil end diff --git a/lib/puppet/module.rb b/lib/puppet/module.rb index 54212710d..b86931664 100644 --- a/lib/puppet/module.rb +++ b/lib/puppet/module.rb @@ -132,7 +132,7 @@ class Puppet::Module def manifests(rest) rest ||= "init.pp" p = File::join(path, MANIFESTS, rest) - files = Dir.glob(p) + files = Dir.glob(p).reject { |f| FileTest.directory?(f) } if files.size == 0 files = Dir.glob(p + ".pp") end diff --git a/lib/puppet/network/client/master.rb b/lib/puppet/network/client/master.rb index 4c7fa5f5b..a2b6499bb 100644 --- a/lib/puppet/network/client/master.rb +++ b/lib/puppet/network/client/master.rb @@ -49,6 +49,8 @@ class Puppet::Network::Client::Master < Puppet::Network::Client end # Return the list of dynamic facts as an array of symbols + # NOTE:LAK(2008/04/10): This code is currently unused, since we now always + # recompile. def self.dynamic_facts # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com] x = Puppet.settings[:dynamicfacts].split(/\s*,\s*/).collect { |fact| fact.downcase } @@ -96,31 +98,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client end end - # Check whether our catalog is up to date - def fresh?(facts) - if Puppet[:ignorecache] - Puppet.notice "Ignoring cache" - return false - end - unless self.compile_time - Puppet.debug "No cached compile time" - return false - end - if facts_changed?(facts) - Puppet.info "Facts have changed; recompiling" unless local? - return false - end - - newcompile = @driver.freshness - # We're willing to give a 2 second drift - if newcompile - @compile_time.to_i < 1 - return true - else - Puppet.debug "Server compile time is %s vs %s" % [newcompile, @compile_time.to_i] - return false - end - end - # Let the daemon run again, freely in the filesystem. Frolick, little # daemon! def enable @@ -147,11 +124,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client # Retrieve the plugins. getplugins() if Puppet[:pluginsync] - if (self.catalog or FileTest.exist?(self.cachefile)) and self.fresh?(facts) - Puppet.info "Configuration is up to date" - return if use_cached_config - end - Puppet.debug("Retrieving catalog") # If we can't retrieve the catalog, just return, which will either @@ -450,32 +422,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client loadfacts() - # Have the facts changed since we last compiled? - def facts_changed?(facts) - oldfacts = (Puppet::Util::Storage.cache(:configuration)[:facts] || {}).dup - newfacts = facts.dup - self.class.dynamic_facts.each do |fact| - [oldfacts, newfacts].each do |facthash| - facthash.delete(fact) if facthash.include?(fact) - end - end - - if oldfacts == newfacts - return false - else -# unless oldfacts -# puts "no old facts" -# return true -# end -# newfacts.keys.each do |k| -# unless newfacts[k] == oldfacts[k] -# puts "%s: %s vs %s" % [k, newfacts[k], oldfacts[k]] -# end -# end - return true - end - end - # Actually retrieve the catalog, either from the server or from a # local master. def get_actual_config(facts) diff --git a/lib/puppet/network/handler/configuration.rb b/lib/puppet/network/handler/configuration.rb deleted file mode 100644 index 8168ce1d5..000000000 --- a/lib/puppet/network/handler/configuration.rb +++ /dev/null @@ -1,184 +0,0 @@ -require 'openssl' -require 'puppet' -require 'puppet/parser/interpreter' -require 'puppet/sslcertificates' -require 'xmlrpc/server' -require 'yaml' - -class Puppet::Network::Handler - class Configuration < Handler - desc "Puppet's configuration compilation interface. Passed a node name - or other key, retrieves information about the node (using the ``node_source``) - and returns a compiled configuration." - - include Puppet::Util - - attr_accessor :local, :classes - - @interface = XMLRPC::Service::Interface.new("configuration") { |iface| - iface.add_method("string configuration(string)") - iface.add_method("string version()") - } - - # Compile a node's configuration. - def configuration(key, client = nil, clientip = nil) - # If we want to use the cert name as our key - if Puppet[:node_name] == 'cert' and client - key = client - end - - # Note that this is reasonable, because either their node source should actually - # know about the node, or they should be using the ``none`` node source, which - # will always return data. - unless node = Puppet::Node.find_by_any_name(key) - raise Puppet::Error, "Could not find node '%s'" % key - end - - # Add any external data to the node. - add_node_data(node) - - configuration = compile(node) - - return translate(configuration) - end - - def initialize(options = {}) - options.each do |param, value| - case param - when :Classes: @classes = value - when :Local: self.local = value - else - raise ArgumentError, "Configuration handler does not accept %s" % param - end - end - - set_server_facts - end - - # Are we running locally, or are our clients networked? - def local? - self.local - end - - # Return the configuration version. - def version(client = nil, clientip = nil) - if client and node = Puppet::Node.find_by_any_name(client) - update_node_check(node) - return interpreter.configuration_version(node) - else - # Just return something that will always result in a recompile, because - # this is local. - return (Time.now + 1000).to_i - end - end - - private - - # Add any extra data necessary to the node. - def add_node_data(node) - # Merge in our server-side facts, so they can be used during compilation. - node.merge(@server_facts) - - # Add any specified classes to the node's class list. - if @classes - @classes.each do |klass| - node.classes << klass - end - end - end - - # Compile the actual configuration. - def compile(node) - # Pick the benchmark level. - if local? - level = :none - else - level = :notice - end - - # Ask the interpreter to compile the configuration. - str = "Compiled configuration for %s" % node.name - if node.environment - str += " in environment %s" % node.environment - end - config = nil - benchmark(level, "Compiled configuration for %s" % node.name) do - begin - config = interpreter.compile(node) - rescue => detail - # If we're local, then we leave it to the local system - # to handle error reporting, but otherwise we do it here - # so the interpreter doesn't need to know if the parser - # is local or not. - Puppet.err(detail.to_s) unless local? - raise - end - end - - return config - end - - # Create our interpreter object. - def create_interpreter - return Puppet::Parser::Interpreter.new - end - - # Create/return our interpreter. - def interpreter - unless defined?(@interpreter) and @interpreter - @interpreter = create_interpreter - end - @interpreter - end - - # Initialize our server fact hash; we add these to each client, and they - # won't change while we're running, so it's safe to cache the values. - def set_server_facts - @server_facts = {} - - # Add our server version to the fact list - @server_facts["serverversion"] = Puppet.version.to_s - - # And then add the server name and IP - {"servername" => "fqdn", - "serverip" => "ipaddress" - }.each do |var, fact| - if value = Facter.value(fact) - @server_facts[var] = value - else - Puppet.warning "Could not retrieve fact %s" % fact - end - end - - if @server_facts["servername"].nil? - host = Facter.value(:hostname) - if domain = Facter.value(:domain) - @server_facts["servername"] = [host, domain].join(".") - else - @server_facts["servername"] = host - end - end - end - - # Translate our configuration appropriately for sending back to a client. - def translate(config) - if local? - config - else - CGI.escape(config.to_yaml(:UseBlock => true)) - end - end - - # Mark that the node has checked in. FIXME this needs to be moved into - # the Node class, or somewhere that's got abstract backends. - def update_node_check(node) - if Puppet.features.rails? and Puppet[:storeconfigs] - Puppet::Rails.connect - - host = Puppet::Rails::Host.find_or_create_by_name(node.name) - host.last_freshcheck = Time.now - host.save - end - end - end -end diff --git a/lib/puppet/network/handler/master.rb b/lib/puppet/network/handler/master.rb index dabfaca50..851ccc7b2 100644 --- a/lib/puppet/network/handler/master.rb +++ b/lib/puppet/network/handler/master.rb @@ -23,8 +23,8 @@ class Puppet::Network::Handler # Tell a client whether there's a fresh config for it def freshness(client = nil, clientip = nil) - client ||= Facter.value("hostname") - config_handler.version(client, clientip) + # Always force a recompile. Newer clients shouldn't do this (as of April 2008). + Time.now end def initialize(hash = {}) @@ -51,8 +51,6 @@ class Puppet::Network::Handler if hash.include?(:Classes) args[:Classes] = hash[:Classes] end - - @config_handler = Puppet::Network::Handler.handler(:configuration).new(args) end # Call our various handlers; this handler is getting deprecated. @@ -63,13 +61,9 @@ class Puppet::Network::Handler # Pass the facts to the fact handler Puppet::Node::Facts.new(client, facts).save unless local? - # And get the configuration from the config handler - config = nil - benchmark(:notice, "Compiled configuration for %s" % client) do - config = config_handler.configuration(client) - end + catalog = Puppet::Node::Catalog.find(client) - return translate(config.extract) + return translate(catalog.extract) end private @@ -93,13 +87,6 @@ class Puppet::Network::Handler return client, clientip end - def config_handler - unless defined? @config_handler - @config_handler = Puppet::Network::Handler.handler(:config).new :local => local? - end - @config_handler - end - # def decode_facts(facts) if @local diff --git a/lib/puppet/network/xmlrpc/client.rb b/lib/puppet/network/xmlrpc/client.rb index f6a5e8db6..357a766a1 100644 --- a/lib/puppet/network/xmlrpc/client.rb +++ b/lib/puppet/network/xmlrpc/client.rb @@ -49,6 +49,11 @@ module Puppet::Network self.recycle_connection retry end + ["certificate verify failed", "hostname was not match", "hostname not match"].each do |str| + if detail.message.include?(str) + Puppet.warning "Certificate validation failed; considering using the certname configuration option" + end + end raise XMLRPCClientError, "Certificates were not trusted: %s" % detail rescue ::XMLRPC::FaultException => detail diff --git a/lib/puppet/node/facts.rb b/lib/puppet/node/facts.rb index c60be3fcf..8ee90b4ac 100755 --- a/lib/puppet/node/facts.rb +++ b/lib/puppet/node/facts.rb @@ -8,8 +8,16 @@ class Puppet::Node::Facts # the node sources. extend Puppet::Indirector + # We want to expire any cached nodes if the facts are saved. + module NodeExpirer + def save(instance, *args) + Puppet::Node.expire(instance.name) + super + end + end + # Use the node source as the indirection terminus. - indirects :facts, :terminus_class => :facter + indirects :facts, :terminus_class => :facter, :extend => NodeExpirer attr_accessor :name, :values diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb index b86a4792b..d70722fdd 100644 --- a/lib/puppet/parser/parser_support.rb +++ b/lib/puppet/parser/parser_support.rb @@ -237,7 +237,9 @@ class Puppet::Parser::Parser end end - return true if classes.include?(classname) + # We don't know whether we're looking for a class or definition, so we have + # to test for both. + return true if classes.include?(classname) || definitions.include?(classname) unless @loaded.include?(filename) @loaded << filename @@ -249,7 +251,9 @@ class Puppet::Parser::Parser # We couldn't load the file end end - return classes.include?(classname) + # We don't know whether we're looking for a class or definition, so we have + # to test for both. + return classes.include?(classname) || definitions.include?(classname) end # Split an fq name into a namespace and name diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb index 4b48ff6cf..d214a60ee 100644 --- a/lib/puppet/parser/resource.rb +++ b/lib/puppet/parser/resource.rb @@ -303,6 +303,12 @@ class Puppet::Parser::Resource return bucket end + # Convert this resource to a RAL resource. We hackishly go via the + # transportable stuff. + def to_type + to_trans.to_type + end + def to_transobject # Now convert to a transobject obj = Puppet::TransObject.new(@ref.title, @ref.type) diff --git a/lib/puppet/provider/service/debian.rb b/lib/puppet/provider/service/debian.rb index f0f6fe1ef..da38c10a2 100755 --- a/lib/puppet/provider/service/debian.rb +++ b/lib/puppet/provider/service/debian.rb @@ -22,7 +22,7 @@ Puppet::Type.type(:service).provide :debian, :parent => :init do # If it's enabled, then it will print output showing removal of # links. - if output =~ /etc\/rc[\dS].d|not installed/ + if output =~ /etc\/rc[\dS].d\/S|not installed/ return :true else return :false diff --git a/lib/puppet/reference/report.rb b/lib/puppet/reference/report.rb new file mode 100644 index 000000000..be8e64751 --- /dev/null +++ b/lib/puppet/reference/report.rb @@ -0,0 +1,23 @@ +require 'puppet/reports' + +report = Puppet::Util::Reference.newreference :report, :doc => "All available transaction reports" do + Puppet::Reports.reportdocs +end + +report.header = " +Puppet clients can report back to the server after each transaction. This +transaction report is sent as a YAML dump of the +``Puppet::Transaction::Report`` class and includes every log message that was +generated during the transaction along with as many metrics as Puppet knows how +to collect. See `ReportsAndReporting Reports and Reporting`:trac: +for more information on how to use reports. + +Currently, clients default to not sending in reports; you can enable reporting +by setting the ``report`` parameter to true. + +To use a report, set the ``reports`` parameter on the server; multiple +reports must be comma-separated. You can also specify ``none`` to disable +reports entirely. + +Puppet provides multiple report handlers that will process client reports: +" diff --git a/lib/puppet/reports/rrdgraph.rb b/lib/puppet/reports/rrdgraph.rb index 2611f0369..03d8a5bdd 100644 --- a/lib/puppet/reports/rrdgraph.rb +++ b/lib/puppet/reports/rrdgraph.rb @@ -1,8 +1,10 @@ Puppet::Reports.register_report(:rrdgraph) do desc "Graph all available data about hosts using the RRD library. You must have the Ruby RRDtool library installed to use this report, which - you can get from `the RubyRRDTool RubyForge page`_. This package requires - the binary rrdtool2 package to be installed. + you can get from `the RubyRRDTool RubyForge page`_. This package may also + be available as ``ruby-rrd`` or ``rrdtool-ruby`` in your distribution's package + management system. The library and/or package will both require the binary + ``rrdtool`` package from your distribution to be installed. .. _the RubyRRDTool RubyForge page: http://rubyforge.org/projects/rubyrrdtool/ diff --git a/lib/puppet/transaction/report.rb b/lib/puppet/transaction/report.rb index 56f8a602a..bd62ebbe6 100644 --- a/lib/puppet/transaction/report.rb +++ b/lib/puppet/transaction/report.rb @@ -34,6 +34,10 @@ class Puppet::Transaction::Report end end + def name + host + end + # Create a new metric. def newmetric(name, hash) metric = Puppet::Util::Metric.new(name) diff --git a/lib/puppet/type/file/group.rb b/lib/puppet/type/file/group.rb index 5f7caf342..cc482ff31 100755 --- a/lib/puppet/type/file/group.rb +++ b/lib/puppet/type/file/group.rb @@ -11,12 +11,8 @@ module Puppet end def id2name(id) - if id > 70000 - return nil - end - if id.is_a?(Symbol) - return id.to_s - end + return id.to_s if id.is_a?(Symbol) + return nil if id > Puppet[:maximum_uid].to_i begin group = Etc.getgrgid(id) rescue ArgumentError @@ -73,7 +69,17 @@ module Puppet @method = :chown end - return stat.gid + currentvalue = stat.gid + + # On OS X, files that are owned by -2 get returned as really + # large GIDs instead of negative ones. This isn't a Ruby bug, + # it's an OS X bug, since it shows up in perl, too. + if currentvalue > Puppet[:maximum_uid].to_i + self.warning "Apparently using negative GID (%s) on a platform that does not consistently handle them" % currentvalue + currentvalue = :silly + end + + return currentvalue end # Determine if the group is valid, and if so, return the GID diff --git a/lib/puppet/type/mount.rb b/lib/puppet/type/mount.rb index ca8e27e17..e18630cc8 100755 --- a/lib/puppet/type/mount.rb +++ b/lib/puppet/type/mount.rb @@ -95,7 +95,7 @@ module Puppet # Solaris specifies two devices, not just one. newproperty(:blockdevice) do - desc "The the device to fsck. This is property is only valid + desc "The device to fsck. This is property is only valid on Solaris, and in most cases will default to the correct value." diff --git a/lib/puppet/type/nagios_hostescalation.rb b/lib/puppet/type/nagios_hostescalation.rb new file mode 100644 index 000000000..5d18af2a6 --- /dev/null +++ b/lib/puppet/type/nagios_hostescalation.rb @@ -0,0 +1,3 @@ +require 'puppet/util/nagios_maker' + +Puppet::Util::NagiosMaker.create_nagios_type :hostescalation diff --git a/lib/puppet/type/nagios_servicegroup.rb b/lib/puppet/type/nagios_servicegroup.rb new file mode 100644 index 000000000..fef669639 --- /dev/null +++ b/lib/puppet/type/nagios_servicegroup.rb @@ -0,0 +1,3 @@ +require 'puppet/util/nagios_maker' + +Puppet::Util::NagiosMaker.create_nagios_type :servicegroup diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb index 98b6a63de..0b668395d 100755 --- a/lib/puppet/type/user.rb +++ b/lib/puppet/type/user.rb @@ -220,6 +220,9 @@ module Puppet if value =~ /^\d+$/ raise ArgumentError, "Group names must be provided, not numbers" end + if value.include?(",") + raise ArgumentError, "Group names must be provided as an array, not a comma-separated list" + end end end diff --git a/lib/puppet/util/posix.rb b/lib/puppet/util/posix.rb index 0b1e1c2f2..8228734ef 100755 --- a/lib/puppet/util/posix.rb +++ b/lib/puppet/util/posix.rb @@ -13,7 +13,7 @@ module Puppet::Util::POSIX end prefix = "get" + space.to_s if id.is_a?(Integer) - if id > 1000000 + if id > Puppet[:maximum_uid].to_i Puppet.err "Tried to get %s field for silly id %s" % [field, id] return nil end @@ -40,7 +40,7 @@ module Puppet::Util::POSIX end if id.is_a?(Integer) integer = true - if id > 1000000 + if id > Puppet[:maximum_uid].to_i Puppet.err "Tried to get %s field for silly id %s" % [field, id] return nil end |