summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2007-02-07 23:56:59 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2007-02-07 23:56:59 +0000
commit6d8068eddd0d29ec53f62557eb53f6ebb8e40591 (patch)
tree8c93181b9325fee95d7ecdc6e79341ff6d3604b0 /lib
parent162602323406117444ce4375ead91d8f92f2b31a (diff)
downloadpuppet-6d8068eddd0d29ec53f62557eb53f6ebb8e40591.tar.gz
puppet-6d8068eddd0d29ec53f62557eb53f6ebb8e40591.tar.xz
puppet-6d8068eddd0d29ec53f62557eb53f6ebb8e40591.zip
Moving some of the stand-alone classes into the util/ subdirectory, to clean up the top-level namespace a bit. This is a lot of file modifications, but most of them just change class names and file paths.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@2178 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet.rb30
-rw-r--r--lib/puppet/client.rb2
-rw-r--r--lib/puppet/client/master.rb8
-rw-r--r--lib/puppet/configuration.rb2
-rwxr-xr-xlib/puppet/daemon.rb8
-rw-r--r--lib/puppet/dsl.rb4
-rwxr-xr-xlib/puppet/filetype.rb302
-rw-r--r--lib/puppet/inifile.rb212
-rw-r--r--lib/puppet/log.rb550
-rw-r--r--lib/puppet/metatype/manager.rb4
-rw-r--r--lib/puppet/metatype/metaparams.rb2
-rw-r--r--lib/puppet/metric.rb160
-rw-r--r--lib/puppet/networkclient.rb1
-rw-r--r--lib/puppet/parameter.rb2
-rw-r--r--lib/puppet/parser/ast.rb4
-rw-r--r--lib/puppet/parser/functions.rb6
-rw-r--r--lib/puppet/parser/grammar.ra2
-rw-r--r--lib/puppet/parser/interpreter.rb4
-rw-r--r--lib/puppet/parser/parser.rb8
-rwxr-xr-xlib/puppet/provider/parsedfile.rb8
-rw-r--r--lib/puppet/reports/log.rb2
-rw-r--r--lib/puppet/reports/rrdgraph.rb2
-rw-r--r--lib/puppet/reports/store.rb2
-rw-r--r--lib/puppet/server/authconfig.rb4
-rwxr-xr-xlib/puppet/server/fileserver.rb2
-rwxr-xr-xlib/puppet/server/logger.rb2
-rwxr-xr-xlib/puppet/server/report.rb2
-rw-r--r--lib/puppet/sslcertificates/ca.rb2
-rw-r--r--lib/puppet/storage.rb106
-rw-r--r--lib/puppet/suidmanager.rb88
-rw-r--r--lib/puppet/transaction.rb4
-rw-r--r--lib/puppet/transaction/report.rb2
-rw-r--r--lib/puppet/type.rb12
-rwxr-xr-xlib/puppet/type/cron.rb6
-rwxr-xr-xlib/puppet/type/exec.rb17
-rwxr-xr-xlib/puppet/type/parsedtype.rb2
-rw-r--r--lib/puppet/type/pfile.rb4
-rwxr-xr-xlib/puppet/type/pfile/owner.rb2
-rwxr-xr-xlib/puppet/type/pfile/source.rb2
-rw-r--r--lib/puppet/type/pfile/target.rb2
-rw-r--r--lib/puppet/type/property.rb2
-rw-r--r--lib/puppet/type/yumrepo.rb12
-rw-r--r--lib/puppet/util.rb24
-rw-r--r--lib/puppet/util/autoload.rb (renamed from lib/puppet/autoload.rb)2
-rw-r--r--lib/puppet/util/config.rb (renamed from lib/puppet/config.rb)22
-rw-r--r--lib/puppet/util/feature.rb (renamed from lib/puppet/feature.rb)4
-rwxr-xr-xlib/puppet/util/filetype.rb300
-rw-r--r--lib/puppet/util/inifile.rb209
-rwxr-xr-xlib/puppet/util/loadedfile.rb (renamed from lib/puppet/loadedfile.rb)2
-rw-r--r--lib/puppet/util/log.rb548
-rw-r--r--lib/puppet/util/logging.rb6
-rw-r--r--lib/puppet/util/metric.rb158
-rw-r--r--lib/puppet/util/storage.rb103
-rw-r--r--lib/puppet/util/suidmanager.rb86
54 files changed, 1524 insertions, 1538 deletions
diff --git a/lib/puppet.rb b/lib/puppet.rb
index 739113fc9..f12645357 100644
--- a/lib/puppet.rb
+++ b/lib/puppet.rb
@@ -4,11 +4,11 @@ require 'facter'
require 'puppet/error'
require 'puppet/external/event-loop'
require 'puppet/util'
-require 'puppet/log'
-require 'puppet/autoload'
-require 'puppet/config'
-require 'puppet/feature'
-require 'puppet/suidmanager'
+require 'puppet/util/log'
+require 'puppet/util/autoload'
+require 'puppet/util/config'
+require 'puppet/util/feature'
+require 'puppet/util/suidmanager'
#------------------------------------------------------------
# the top-level module
@@ -47,18 +47,18 @@ module Puppet
end
# the hash that determines how our system behaves
- @@config = Puppet::Config.new
+ @@config = Puppet::Util::Config.new
# The services running in this process.
@services ||= []
# define helper messages for each of the message levels
- Puppet::Log.eachlevel { |level|
+ Puppet::Util::Log.eachlevel { |level|
define_method(level,proc { |args|
if args.is_a?(Array)
args = args.join(" ")
end
- Puppet::Log.create(
+ Puppet::Util::Log.create(
:level => level,
:message => args
)
@@ -71,7 +71,7 @@ module Puppet
alias :error :err
# The feature collection
- @features = Puppet::Feature.new('puppet/feature')
+ @features = Puppet::Util::Feature.new('puppet/feature')
# Store a new default value.
def self.setdefaults(section, hash)
@@ -85,7 +85,7 @@ module Puppet
def self.[](param)
case param
when :debug:
- if Puppet::Log.level == :debug
+ if Puppet::Util::Log.level == :debug
return true
else
return false
@@ -106,9 +106,9 @@ module Puppet
def self.debug=(value)
if value
- Puppet::Log.level=(:debug)
+ Puppet::Util::Log.level=(:debug)
else
- Puppet::Log.level=(:notice)
+ Puppet::Util::Log.level=(:notice)
end
end
@@ -194,7 +194,7 @@ module Puppet
command = $0 + " " + self.args.join(" ")
Puppet.notice "Restarting with '%s'" % command
Puppet.shutdown(false)
- Puppet::Log.reopen
+ Puppet::Util::Log.reopen
exec(command)
end
@@ -245,7 +245,7 @@ module Puppet
end
trap(:USR2) do
- Puppet::Log.reopen
+ Puppet::Util::Log.reopen
end
end
@@ -389,7 +389,7 @@ end
require 'puppet/server'
require 'puppet/type'
-require 'puppet/storage'
+require 'puppet/util/storage'
if Puppet[:storeconfigs]
require 'puppet/rails'
end
diff --git a/lib/puppet/client.rb b/lib/puppet/client.rb
index de3b3eaec..e668aa27a 100644
--- a/lib/puppet/client.rb
+++ b/lib/puppet/client.rb
@@ -153,7 +153,7 @@ module Puppet
else
self.stopping = true
if self.respond_to? :running? and self.running?
- Puppet::Storage.store
+ Puppet::Util::Storage.store
end
rmpidfile()
end
diff --git a/lib/puppet/client/master.rb b/lib/puppet/client/master.rb
index b59d710c9..046e0c5aa 100644
--- a/lib/puppet/client/master.rb
+++ b/lib/puppet/client/master.rb
@@ -137,7 +137,7 @@ class Puppet::Client::MasterClient < Puppet::Client
puts detail.backtrace
end
ensure
- Puppet::Storage.store
+ Puppet::Util::Storage.store
end
if Puppet[:report]
@@ -177,8 +177,8 @@ class Puppet::Client::MasterClient < Puppet::Client
# Initialize and load storage
def dostorage
begin
- Puppet::Storage.load
- @compile_time ||= Puppet::Storage.cache(:configuration)[:compile_time]
+ Puppet::Util::Storage.load
+ @compile_time ||= Puppet::Util::Storage.cache(:configuration)[:compile_time]
rescue => detail
if Puppet[:trace]
puts detail.backtrace
@@ -626,7 +626,7 @@ class Puppet::Client::MasterClient < Puppet::Client
fromcache = true
else
@compile_time = Time.now
- Puppet::Storage.cache(:configuration)[:compile_time] = @compile_time
+ Puppet::Util::Storage.cache(:configuration)[:compile_time] = @compile_time
end
begin
diff --git a/lib/puppet/configuration.rb b/lib/puppet/configuration.rb
index 952a54397..5b2d90af8 100644
--- a/lib/puppet/configuration.rb
+++ b/lib/puppet/configuration.rb
@@ -4,7 +4,7 @@ module Puppet
# use basedirs that are in the user's home directory.
conf = nil
var = nil
- if self.name != "puppetmasterd" and Puppet::SUIDManager.uid != 0
+ if self.name != "puppetmasterd" and Puppet::Util::SUIDManager.uid != 0
conf = File.expand_path("~/.puppet")
var = File.expand_path("~/.puppet/var")
else
diff --git a/lib/puppet/daemon.rb b/lib/puppet/daemon.rb
index bd02a9dc3..9fdb33bcf 100755
--- a/lib/puppet/daemon.rb
+++ b/lib/puppet/daemon.rb
@@ -29,7 +29,7 @@ module Puppet
end
# Get rid of console logging
- Puppet::Log.close(:console)
+ Puppet::Util::Log.close(:console)
Process.setsid
Dir.chdir("/")
@@ -37,7 +37,7 @@ module Puppet
$stdin.reopen "/dev/null"
$stdout.reopen "/dev/null", "a"
$stderr.reopen $stdout
- Puppet::Log.reopen
+ Puppet::Util::Log.reopen
rescue => detail
File.open("/tmp/daemonout", "w") { |f|
f.puts "Could not start %s: %s" % [Puppet.name, detail]
@@ -264,8 +264,8 @@ module Puppet
rmpidfile()
# And close all logs except the console.
- Puppet::Log.destinations.reject { |d| d == :console }.each do |dest|
- Puppet::Log.close(dest)
+ Puppet::Util::Log.destinations.reject { |d| d == :console }.each do |dest|
+ Puppet::Util::Log.close(dest)
end
super
diff --git a/lib/puppet/dsl.rb b/lib/puppet/dsl.rb
index 071a3f6dd..44c03e8a9 100644
--- a/lib/puppet/dsl.rb
+++ b/lib/puppet/dsl.rb
@@ -95,8 +95,8 @@ module Puppet
end
Puppet[:user] = Process.uid
Puppet[:group] = Process.gid
- Puppet::Log.newdestination(:console)
- Puppet::Log.level = :info
+ Puppet::Util::Log.newdestination(:console)
+ Puppet::Util::Log.level = :info
end
private
diff --git a/lib/puppet/filetype.rb b/lib/puppet/filetype.rb
deleted file mode 100755
index d05c1469d..000000000
--- a/lib/puppet/filetype.rb
+++ /dev/null
@@ -1,302 +0,0 @@
-module Puppet
- # Basic classes for reading, writing, and emptying files. Not much
- # to see here.
- class FileType
- attr_accessor :loaded, :path, :synced
-
- class << self
- attr_accessor :name
- include Puppet::Util::ClassGen
- end
-
- # Create a new filetype.
- def self.newfiletype(name, &block)
- @filetypes ||= {}
-
- klass = genclass(name,
- :block => block,
- :prefix => "FileType",
- :hash => @filetypes
- )
-
- # Rename the read and write methods, so that we're sure they
- # maintain the stats.
- klass.class_eval do
- # Rename the read method
- define_method(:real_read, instance_method(:read))
- define_method(:read) do
- begin
- val = real_read()
- @loaded = Time.now
- if val
- return val.gsub(/# HEADER.*\n/,'')
- else
- return ""
- end
- rescue Puppet::Error => detail
- raise
- rescue => detail
- if Puppet[:trace]
- puts detail.backtrace
- end
- raise Puppet::Error, "%s could not read %s: %s" %
- [self.class, @path, detail]
- end
- end
-
- # And then the write method
- define_method(:real_write, instance_method(:write))
- define_method(:write) do |text|
- begin
- val = real_write(text)
- @synced = Time.now
- return val
- rescue Puppet::Error => detail
- raise
- rescue => detail
- if Puppet[:debug]
- puts detail.backtrace
- end
- raise Puppet::Error, "%s could not write %s: %s" %
- [self.class, @path, detail]
- end
- end
- end
- end
-
- def self.filetype(type)
- @filetypes[type]
- end
-
- def initialize(path)
- @path = path
- end
-
- # Operate on plain files.
- newfiletype(:flat) do
- # Read the file.
- def read
- if File.exists?(@path)
- File.read(@path)
- else
- return nil
- end
- end
-
- # Remove the file.
- def remove
- if File.exists?(@path)
- File.unlink(@path)
- end
- end
-
- # Overwrite the file.
- def write(text)
- File.open(@path, "w") { |f| f.print text; f.flush }
- end
- end
-
- # Operate on plain files.
- newfiletype(:ram) do
- @@tabs = {}
-
- def self.clear
- @@tabs.clear
- end
-
- def initialize(path)
- super
- @@tabs[@path] ||= ""
- end
-
- # Read the file.
- def read
- Puppet.info "Reading %s from RAM" % @path
- @@tabs[@path]
- end
-
- # Remove the file.
- def remove
- Puppet.info "Removing %s from RAM" % @path
- @@tabs[@path] = ""
- end
-
- # Overwrite the file.
- def write(text)
- Puppet.info "Writing %s to RAM" % @path
- @@tabs[@path] = text
- end
- end
-
- # Handle Linux-style cron tabs.
- newfiletype(:crontab) do
- def initialize(user)
- self.path = user
- end
-
- def path=(user)
- begin
- @uid = Puppet::Util.uid(user)
- rescue Puppet::Error => detail
- raise Puppet::Error, "Could not retrieve user %s" % user
- end
-
- # XXX We have to have the user name, not the uid, because some
- # systems *cough*linux*cough* require it that way
- @path = user
- end
-
- # Read a specific @path's cron tab.
- def read
- %x{#{cmdbase()} -l 2>/dev/null}
- end
-
- # Remove a specific @path's cron tab.
- def remove
- if Facter.value("operatingsystem") == "FreeBSD"
- %x{/bin/echo yes | #{cmdbase()} -r 2>/dev/null}
- else
- %x{#{cmdbase()} -r 2>/dev/null}
- end
- end
-
- # Overwrite a specific @path's cron tab; must be passed the @path name
- # and the text with which to create the cron tab.
- def write(text)
- IO.popen("#{cmdbase()} -", "w") { |p|
- p.print text
- }
- end
-
- private
-
- # Only add the -u flag when the @path is different. Fedora apparently
- # does not think I should be allowed to set the @path to my own user name
- def cmdbase
- cmd = nil
- if @uid == Puppet::SUIDManager.uid
- return "crontab"
- else
- return "crontab -u #{@path}"
- end
- end
- end
-
- # SunOS has completely different cron commands; this class implements
- # its versions.
- newfiletype(:suntab) do
- # Read a specific @path's cron tab.
- def read
- Puppet::SUIDManager.asuser(@path) {
- %x{crontab -l 2>/dev/null}
- }
- end
-
- # Remove a specific @path's cron tab.
- def remove
- Puppet::SUIDManager.asuser(@path) {
- %x{crontab -r 2>/dev/null}
- }
- end
-
- # Overwrite a specific @path's cron tab; must be passed the @path name
- # and the text with which to create the cron tab.
- def write(text)
- Puppet::SUIDManager.asuser(@path) {
- IO.popen("crontab", "w") { |p|
- p.print text
- }
- }
- end
- end
-
- # Treat netinfo tables as a single file, just for simplicity of certain
- # types
- newfiletype(:netinfo) do
- class << self
- attr_accessor :format
- end
- def read
- %x{nidump -r /#{@path} /}
- end
-
- # This really only makes sense for cron tabs.
- def remove
- %x{nireport / /#{@path} name}.split("\n").each do |name|
- newname = name.gsub(/\//, '\/').sub(/\s+$/, '')
- output = %x{niutil -destroy / '/#{@path}/#{newname}'}
-
- unless $? == 0
- raise Puppet::Error, "Could not remove %s from %s" %
- [name, @path]
- end
- end
- end
-
- # Convert our table to an array of hashes. This only works for
- # handling one table at a time.
- def to_array(text = nil)
- unless text
- text = read
- end
-
- hash = nil
-
- # Initialize it with the first record
- records = []
- text.split("\n").each do |line|
- next if line =~ /^[{}]$/ # Skip the wrapping lines
- next if line =~ /"name" = \( "#{@path}" \)/ # Skip the table name
- next if line =~ /CHILDREN = \(/ # Skip this header
- next if line =~ /^ \)/ # and its closer
-
- # Now we should have nothing but records, wrapped in braces
-
- case line
- when /^\s+\{/: hash = {}
- when /^\s+\}/: records << hash
- when /\s+"(\w+)" = \( (.+) \)/
- field = $1
- values = $2
-
- # Always use an array
- hash[field] = []
-
- values.split(/, /).each do |value|
- if value =~ /^"(.*)"$/
- hash[field] << $1
- else
- raise ArgumentError, "Could not match value %s" % value
- end
- end
- else
- raise ArgumentError, "Could not match line %s" % line
- end
- end
-
- records
- end
-
- def write(text)
- text.gsub!(/^#.*\n/,'')
- text.gsub!(/^$/,'')
- if text == "" or text == "\n"
- self.remove
- return
- end
- unless format = self.class.format
- raise Puppe::DevError, "You must define the NetInfo format to inport"
- end
- IO.popen("niload -d #{format} . 1>/dev/null 2>/dev/null", "w") { |p|
- p.print text
- }
-
- unless $? == 0
- raise ArgumentError, "Failed to write %s" % @path
- end
- end
- end
- end
-end
-
-# $Id$
diff --git a/lib/puppet/inifile.rb b/lib/puppet/inifile.rb
deleted file mode 100644
index 3ffd6d137..000000000
--- a/lib/puppet/inifile.rb
+++ /dev/null
@@ -1,212 +0,0 @@
-# Module Puppet::IniConfig
-# A generic way to parse .ini style files and manipulate them in memory
-# One 'file' can be made up of several physical files. Changes to sections
-# on the file are tracked so that only the physical files in which
-# something has changed are written back to disk
-# Great care is taken to preserve comments and blank lines from the original
-# files
-#
-# The parsing tries to stay close to python's ConfigParser
-
-require 'puppet/filetype'
-
-module Puppet
- module IniConfig
-
- # A section in a .ini file
- class Section
- attr_reader :name, :file
-
- def initialize(name, file)
- @name = name
- @file = file
- @dirty = false
- @entries = []
- end
-
- # Has this section been modified since it's been read in
- # or written back to disk
- def dirty?
- @dirty
- end
-
- # Should only be used internally
- def mark_clean
- @dirty = false
- end
-
- # Add a line of text (e.g., a comment) Such lines
- # will be written back out in exactly the same
- # place they were read in
- def add_line(line)
- @entries << line
- end
-
- # Set the entry 'key=value'. If no entry with the
- # given key exists, one is appended to teh end of the section
- def []=(key, value)
- entry = find_entry(key)
- @dirty = true
- if entry.nil?
- @entries << [key, value]
- else
- entry[1] = value
- end
- end
-
- # Return the value associated with KEY. If no such entry
- # exists, return nil
- def [](key)
- entry = find_entry(key)
- if entry.nil?
- return nil
- end
- return entry[1]
- end
-
- # Format the section as text in the way it should be
- # written to file
- def format
- text = "[#{name}]\n"
- @entries.each do |entry|
- if entry.is_a?(Array)
- key, value = entry
- unless value.nil?
- text << "#{key}=#{value}\n"
- end
- else
- text << entry
- end
- end
- return text
- end
-
- private
- def find_entry(key)
- @entries.each do |entry|
- if entry.is_a?(Array) && entry[0] == key
- return entry
- end
- end
- return nil
- end
-
- end
-
- # A logical .ini-file that can be spread across several physical
- # files. For each physical file, call #read with the filename
- class File
- def initialize
- @files = {}
- end
-
- # Add the contents of the file with name FILE to the
- # already existing sections
- def read(file)
- text = Puppet::FileType.filetype(:flat).new(file).read
- if text.nil?
- raise "Could not find #{file}"
- end
-
- section = nil # The name of the current section
- optname = nil # The name of the last option in section
- line = 0
- @files[file] = []
- text.each_line do |l|
- line += 1
- if l.strip.empty? || "#;".include?(l[0,1]) ||
- (l.split(nil, 2)[0].downcase == "rem" &&
- l[0,1].downcase == "r")
- # Whitespace or comment
- if section.nil?
- @files[file] << l
- else
- section.add_line(l)
- end
- elsif " \t\r\n\f".include?(l[0,1]) && section && optname
- # continuation line
- section[optname] += "\n" + l.chomp
- elsif l =~ /^\[([^\]]+)\]/
- # section heading
- section.mark_clean unless section.nil?
- section = add_section($1, file)
- optname = nil
- elsif l =~ /^\s*([^\s=]+)\s*\=(.+)$/
- # We allow space around the keys, but not the values
- # For the values, we don't know if space is significant
- if section.nil?
- raise "#{file}:#{line}:Key/value pair outside of a section for key #{$1}"
- else
- section[$1] = $2
- optname = $1
- end
- else
- raise "#{file}:#{line}: Can't parse '#{l.chomp}'"
- end
- end
- section.mark_clean unless section.nil?
- end
-
- # Store all modifications made to sections in this file back
- # to the physical files. If no modifications were made to
- # a physical file, nothing is written
- def store
- @files.each do |file, lines|
- text = ""
- dirty = false
- lines.each do |l|
- if l.is_a?(Section)
- dirty ||= l.dirty?
- text << l.format
- l.mark_clean
- else
- text << l
- end
- end
- if dirty
- Puppet::FileType.filetype(:flat).new(file).write(text)
- end
- end
- end
-
- # Execute BLOCK, passing each section in this file
- # as an argument
- def each_section(&block)
- @files.each do |file, list|
- list.each do |entry|
- if entry.is_a?(Section)
- yield(entry)
- end
- end
- end
- end
-
- # Return the Section with the given name or nil
- def [](name)
- name = name.to_s
- each_section do |section|
- return section if section.name == name
- end
- return nil
- end
-
- # Return true if the file contains a section with name NAME
- def include?(name)
- return ! self[name].nil?
- end
-
- # Add a section to be stored in FILE when store is called
- def add_section(name, file)
- if include?(name)
- raise "A section with name #{name} already exists"
- end
- result = Section.new(name, file)
- @files[file] ||= []
- @files[file] << result
- return result
- end
- end
-
-
- end
-end
diff --git a/lib/puppet/log.rb b/lib/puppet/log.rb
deleted file mode 100644
index 44b4352ce..000000000
--- a/lib/puppet/log.rb
+++ /dev/null
@@ -1,550 +0,0 @@
-require 'syslog'
-
-module Puppet
- # Pass feedback to the user. Log levels are modeled after syslog's, and it is
- # expected that that will be the most common log destination. Supports
- # multiple destinations, one of which is a remote server.
- class Log
- include Puppet::Util
-
- @levels = [:debug,:info,:notice,:warning,:err,:alert,:emerg,:crit]
- @loglevel = 2
-
- @desttypes = {}
-
- # A type of log destination.
- class Destination
- class << self
- attr_accessor :name
- end
-
- def self.initvars
- @matches = []
- end
-
- # Mark the things we're supposed to match.
- def self.match(obj)
- @matches ||= []
- @matches << obj
- end
-
- # See whether we match a given thing.
- def self.match?(obj)
- # Convert single-word strings into symbols like :console and :syslog
- if obj.is_a? String and obj =~ /^\w+$/
- obj = obj.downcase.intern
- end
-
- @matches.each do |thing|
- # Search for direct matches or class matches
- return true if thing === obj or thing == obj.class.to_s
- end
- return false
- end
-
- def name
- if defined? @name
- return @name
- else
- return self.class.name
- end
- end
-
- # Set how to handle a message.
- def self.sethandler(&block)
- define_method(:handle, &block)
- end
-
- # Mark how to initialize our object.
- def self.setinit(&block)
- define_method(:initialize, &block)
- end
- end
-
- # Create a new destination type.
- def self.newdesttype(name, options = {}, &block)
- dest = genclass(name, :parent => Destination, :prefix => "Dest",
- :block => block,
- :hash => @desttypes,
- :attributes => options
- )
- dest.match(dest.name)
-
- return dest
- end
-
- @destinations = {}
-
- class << self
- include Puppet::Util
- include Puppet::Util::ClassGen
- end
-
- # Reset all logs to basics. Basically just closes all files and undefs
- # all of the other objects.
- def Log.close(dest = nil)
- if dest
- if @destinations.include?(dest)
- if @destinations.respond_to?(:close)
- @destinations[dest].close
- end
- @destinations.delete(dest)
- end
- else
- @destinations.each { |name, dest|
- if dest.respond_to?(:flush)
- dest.flush
- end
- if dest.respond_to?(:close)
- dest.close
- end
- }
- @destinations = {}
- end
- end
-
- # Flush any log destinations that support such operations.
- def Log.flush
- @destinations.each { |type, dest|
- if dest.respond_to?(:flush)
- dest.flush
- end
- }
- end
-
- # Create a new log message. The primary role of this method is to
- # avoid creating log messages below the loglevel.
- def Log.create(hash)
- unless hash.include?(:level)
- raise Puppet::DevError, "Logs require a level"
- end
- unless @levels.index(hash[:level])
- raise Puppet::DevError, "Invalid log level %s" % hash[:level]
- end
- if @levels.index(hash[:level]) >= @loglevel
- return Puppet::Log.new(hash)
- else
- return nil
- end
- end
-
- def Log.destinations
- return @destinations.keys
- end
-
- # Yield each valid level in turn
- def Log.eachlevel
- @levels.each { |level| yield level }
- end
-
- # Return the current log level.
- def Log.level
- return @levels[@loglevel]
- end
-
- # Set the current log level.
- def Log.level=(level)
- unless level.is_a?(Symbol)
- level = level.intern
- end
-
- unless @levels.include?(level)
- raise Puppet::DevError, "Invalid loglevel %s" % level
- end
-
- @loglevel = @levels.index(level)
- end
-
- def Log.levels
- @levels.dup
- end
-
- newdesttype :syslog do
- def close
- Syslog.close
- end
-
- def initialize
- if Syslog.opened?
- Syslog.close
- end
- name = Puppet.name
- name = "puppet-#{name}" unless name =~ /puppet/
-
- options = Syslog::LOG_PID | Syslog::LOG_NDELAY
-
- # XXX This should really be configurable.
- str = Puppet[:syslogfacility]
- begin
- facility = Syslog.const_get("LOG_#{str.upcase}")
- rescue NameError
- raise Puppet::Error, "Invalid syslog facility %s" % str
- end
-
- @syslog = Syslog.open(name, options, facility)
- end
-
- def handle(msg)
- # XXX Syslog currently has a bug that makes it so you
- # cannot log a message with a '%' in it. So, we get rid
- # of them.
- if msg.source == "Puppet"
- @syslog.send(msg.level, msg.to_s.gsub("%", '%%'))
- else
- @syslog.send(msg.level, "(%s) %s" %
- [msg.source.to_s.gsub("%", ""),
- msg.to_s.gsub("%", '%%')
- ]
- )
- end
- end
- end
-
- newdesttype :file do
- match(/^\//)
-
- def close
- if defined? @file
- @file.close
- @file = nil
- end
- end
-
- def flush
- if defined? @file
- @file.flush
- end
- end
-
- def initialize(path)
- @name = path
- # 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(path))
- Puppet.recmkdir(File.dirname(path))
- Puppet.info "Creating log directory %s" % File.dirname(path)
- end
-
- # create the log file, if it doesn't already exist
- file = File.open(path, File::WRONLY|File::CREAT|File::APPEND)
-
- @file = file
-
- @autoflush = Puppet[:autoflush]
- end
-
- def handle(msg)
- @file.puts("%s %s (%s): %s" %
- [msg.time, msg.source, msg.level, msg.to_s])
-
- @file.flush if @autoflush
- end
- end
-
- newdesttype :console do
-
-
- PINK = {:console => "", :html => "FFA0A0"}
- GREEN = {:console => "", :html => "00CD00"}
- YELLOW = {:console => "", :html => "FFFF60"}
- SLATE = {:console => "", :html => "80A0FF"}
- ORANGE = {:console => "", :html => "FFA500"}
- BLUE = {:console => "", :html => "40FFFF"}
- RESET = {:console => "", :html => ""}
-
- @@colormap = {
- :debug => SLATE,
- :info => GREEN,
- :notice => PINK,
- :warning => ORANGE,
- :err => YELLOW,
- :alert => BLUE,
- :emerg => RESET,
- :crit => RESET
- }
-
- def colorize(level, str)
- case Puppet[:color]
- when false: str
- when true, :ansi, "ansi": console_color(level, str)
- when :html, "html": html_color(level, str)
- end
- end
-
- def console_color(level, str)
- @@colormap[level][:console] + str + RESET[:console]
- end
-
- def html_color(level, str)
- %{<span style="color: %s">%s</span>} % [@@colormap[level][:html], str]
- end
-
- def initialize
- # Flush output immediately.
- $stdout.sync = true
- end
-
- def handle(msg)
- if msg.source == "Puppet"
- puts colorize(msg.level, "%s: %s" % [msg.level, msg.to_s])
- else
- puts colorize(msg.level, "%s: %s: %s" % [msg.level, msg.source, msg.to_s])
- end
- end
- end
-
- newdesttype :host do
- def initialize(host)
- Puppet.info "Treating %s as a hostname" % host
- args = {}
- if host =~ /:(\d+)/
- args[:Port] = $1
- args[:Server] = host.sub(/:\d+/, '')
- else
- args[:Server] = host
- end
-
- @name = host
-
- @driver = Puppet::Client::LogClient.new(args)
- end
-
- def handle(msg)
- unless msg.is_a?(String) or msg.remote
- unless defined? @hostname
- @hostname = Facter["hostname"].value
- end
- unless defined? @domain
- @domain = Facter["domain"].value
- if @domain
- @hostname += "." + @domain
- end
- end
- if msg.source =~ /^\//
- msg.source = @hostname + ":" + msg.source
- elsif msg.source == "Puppet"
- msg.source = @hostname + " " + msg.source
- else
- msg.source = @hostname + " " + msg.source
- end
- begin
- #puts "would have sent %s" % msg
- #puts "would have sent %s" %
- # CGI.escape(YAML.dump(msg))
- begin
- tmp = CGI.escape(YAML.dump(msg))
- rescue => detail
- puts "Could not dump: %s" % detail.to_s
- return
- end
- # Add the hostname to the source
- @driver.addlog(tmp)
- rescue => detail
- if Puppet[:trace]
- puts detail.backtrace
- end
- Puppet.err detail
- Puppet::Log.close(self)
- end
- end
- end
- end
-
- # Log to a transaction report.
- newdesttype :report do
- match "Puppet::Transaction::Report"
-
- def initialize(report)
- @report = report
- end
-
- def handle(msg)
- # Only add messages from objects, since anything else is
- # probably unrelated to this run.
- if msg.objectsource?
- @report.newlog(msg)
- end
- end
- end
-
- # Log to an array, just for testing.
- newdesttype :array do
- match "Array"
-
- def initialize(array)
- @array = array
- end
-
- def handle(msg)
- @array << msg
- end
- end
-
- # Create a new log destination.
- def Log.newdestination(dest)
- # Each destination can only occur once.
- if @destinations.find { |name, obj| obj.name == dest }
- return
- end
-
- name, type = @desttypes.find do |name, klass|
- klass.match?(dest)
- end
-
- unless type
- raise Puppet::DevError, "Unknown destination type %s" % dest
- end
-
- begin
- if type.instance_method(:initialize).arity == 1
- @destinations[dest] = type.new(dest)
- else
- @destinations[dest] = type.new()
- end
- rescue => detail
- if Puppet[:debug]
- puts detail.backtrace
- end
-
- # If this was our only destination, then add the console back in.
- if @destinations.empty? and (dest != :console and dest != "console")
- newdestination(:console)
- end
- end
- end
-
- # Route the actual message. FIXME There are lots of things this method
- # should do, like caching, storing messages when there are not yet
- # destinations, a bit more. It's worth noting that there's a potential
- # for a loop here, if the machine somehow gets the destination set as
- # itself.
- def Log.newmessage(msg)
- if @levels.index(msg.level) < @loglevel
- return
- end
-
- @destinations.each do |name, dest|
- threadlock(dest) do
- dest.handle(msg)
- end
- end
- end
-
- def Log.sendlevel?(level)
- @levels.index(level) >= @loglevel
- end
-
- # Reopen all of our logs.
- def Log.reopen
- Puppet.notice "Reopening log files"
- types = @destinations.keys
- @destinations.each { |type, dest|
- if dest.respond_to?(:close)
- dest.close
- end
- }
- @destinations.clear
- # We need to make sure we always end up with some kind of destination
- begin
- types.each { |type|
- Log.newdestination(type)
- }
- rescue => detail
- if @destinations.empty?
- Log.newdestination(:syslog)
- Puppet.err detail.to_s
- end
- end
- end
-
- # Is the passed level a valid log level?
- def self.validlevel?(level)
- @levels.include?(level)
- end
-
- attr_accessor :level, :message, :time, :tags, :remote
- attr_reader :source
-
- def initialize(args)
- unless args.include?(:level) && args.include?(:message)
- raise Puppet::DevError, "Puppet::Log called incorrectly"
- end
-
- if args[:level].class == String
- @level = args[:level].intern
- elsif args[:level].class == Symbol
- @level = args[:level]
- else
- raise Puppet::DevError,
- "Level is not a string or symbol: #{args[:level].class}"
- end
-
- # Just return unless we're actually at a level we should send
- #return unless self.class.sendlevel?(@level)
-
- @message = args[:message].to_s
- @time = Time.now
- # this should include the host name, and probly lots of other
- # stuff, at some point
- unless self.class.validlevel?(level)
- raise Puppet::DevError, "Invalid message level #{level}"
- end
-
- if args.include?(:tags)
- @tags = args[:tags]
- end
-
- if args.include?(:source)
- self.source = args[:source]
- else
- @source = "Puppet"
- end
-
- Log.newmessage(self)
- end
-
- # Was the source of this log an object?
- def objectsource?
- if defined? @objectsource and @objectsource
- @objectsource
- else
- false
- end
- end
-
- # If they pass a source in to us, we make sure it is a string, and
- # we retrieve any tags we can.
- def source=(source)
- # We can't store the actual source, we just store the path.
- # We can't just check for whether it responds to :path, because
- # plenty of providers respond to that in their normal function.
- if source.is_a?(Puppet::Element) and source.respond_to?(:path)
- @objectsource = true
- @source = source.path
- else
- @objectsource = false
- @source = source.to_s
- end
- unless defined? @tags and @tags
- if source.respond_to?(:tags)
- @tags = source.tags
- end
- end
- end
-
- def tagged?(tag)
- @tags.detect { |t| t.to_s == tag.to_s }
- end
-
- def to_report
- "%s %s (%s): %s" % [self.time, self.source, self.level, self.to_s]
- end
-
- def to_s
- return @message
- end
- end
-end
-
-# $Id$
diff --git a/lib/puppet/metatype/manager.rb b/lib/puppet/metatype/manager.rb
index 1e2d6db97..1c0194c16 100644
--- a/lib/puppet/metatype/manager.rb
+++ b/lib/puppet/metatype/manager.rb
@@ -109,7 +109,7 @@ module Manager
end
# Now set up autoload any providers that might exist for this type.
- klass.providerloader = Puppet::Autoload.new(klass,
+ klass.providerloader = Puppet::Util::Autoload.new(klass,
"puppet/provider/#{klass.name.to_s}"
)
@@ -156,7 +156,7 @@ module Manager
# Create a loader for Puppet types.
def typeloader
unless defined? @typeloader
- @typeloader = Puppet::Autoload.new(self,
+ @typeloader = Puppet::Util::Autoload.new(self,
"puppet/type", :wrap => false
)
end
diff --git a/lib/puppet/metatype/metaparams.rb b/lib/puppet/metatype/metaparams.rb
index ee667bfb3..4c85699ba 100644
--- a/lib/puppet/metatype/metaparams.rb
+++ b/lib/puppet/metatype/metaparams.rb
@@ -136,7 +136,7 @@ class Puppet::Type
syslog (which is currently the default)."
defaultto :notice
- newvalues(*Puppet::Log.levels)
+ newvalues(*Puppet::Util::Log.levels)
newvalues(:verbose)
munge do |loglevel|
diff --git a/lib/puppet/metric.rb b/lib/puppet/metric.rb
deleted file mode 100644
index 3749d257f..000000000
--- a/lib/puppet/metric.rb
+++ /dev/null
@@ -1,160 +0,0 @@
-# included so we can test object types
-require 'puppet'
-
-module Puppet
- # A class for handling metrics. This is currently ridiculously hackish.
- class Metric
- Puppet.config.setdefaults("metrics",
- :rrddir => {:default => "$vardir/rrd",
- :owner => "$user",
- :group => "$group",
- :desc => "The directory where RRD database files are stored.
- Directories for each reporting host will be created under
- this directory."
- },
- :rrdgraph => [false, "Whether RRD information should be graphed."],
- :rrdinterval => ["$runinterval", "How often RRD should expect data.
- This should match how often the hosts report back to the server."]
- )
-
- # Load the library as a feature, so we can test its presence.
- Puppet.features.add :rrd, :libs => 'RRD'
-
- attr_accessor :type, :name, :value, :label
-
- attr_writer :basedir
-
- def basedir
- if defined? @basedir
- @basedir
- else
- Puppet[:rrddir]
- end
- end
-
- def create(start = nil)
- Puppet.config.use(:metrics)
-
- start ||= Time.now.to_i - 5
-
- path = self.path
- args = [
- path,
- "--start", start,
- "--step", Puppet[:rrdinterval]
- ]
-
- values.each { |value|
- # the 7200 is the heartbeat -- this means that any data that isn't
- # more frequently than every two hours gets thrown away
- args.push "DS:%s:GAUGE:7200:U:U" % [value[0]]
- }
- args.push "RRA:AVERAGE:0.5:1:300"
-
- begin
- RRD.create(*args)
- rescue => detail
- raise "Could not create RRD file %s: %s" % [path,detail]
- end
- end
-
- def dump
- puts RRD.info(self.path)
- end
-
- def graph(range = nil)
- unless Puppet.features.rrd?
- Puppet.warning "RRD library is missing; cannot graph metrics"
- return
- end
-
- unit = 60 * 60 * 24
- colorstack = %w{#ff0000 #00ff00 #0000ff #099000 #000990 #f00990 #0f0f0f}
-
- {:daily => unit, :weekly => unit * 7, :monthly => unit * 30, :yearly => unit * 365}.each do |name, time|
- file = self.path.sub(/\.rrd$/, "-%s.png" % name)
- args = [file]
-
- args.push("--title",self.label)
- args.push("--imgformat","PNG")
- args.push("--interlace")
- i = 0
- defs = []
- lines = []
- #p @values.collect { |s,l| s }
- values.zip(colorstack).each { |value,color|
- next if value.nil?
- # this actually uses the data label
- defs.push("DEF:%s=%s:%s:AVERAGE" % [value[0],self.path,value[0]])
- lines.push("LINE2:%s%s:%s" % [value[0],color,value[1]])
- }
- args << defs
- args << lines
- args.flatten!
- if range
- args.push("--start",range[0],"--end",range[1])
- else
- args.push("--start", Time.now.to_i - time, "--end", Time.now.to_i)
- end
-
- begin
- RRD.graph(*args)
- rescue => detail
- Puppet.err "Failed to graph %s: %s" % [self.name,detail]
- end
- end
- end
-
- def initialize(name,label = nil)
- @name = name.to_s
-
- if label
- @label = label
- else
- @label = name.to_s.capitalize.gsub("_", " ")
- end
-
- @values = []
- end
-
- def path
- return File.join(self.basedir, @name + ".rrd")
- end
-
- def newvalue(name,value,label = nil)
- unless label
- label = name.to_s.capitalize.gsub("_", " ")
- end
- @values.push [name,label,value]
- end
-
- def store(time)
- unless Puppet.features.rrd?
- Puppet.warning "RRD library is missing; cannot store metrics"
- return
- end
- unless FileTest.exists?(self.path)
- self.create(time - 5)
- end
-
- # XXX this is not terribly error-resistant
- args = [time]
- values.each { |value|
- args.push value[2]
- }
- arg = args.join(":")
- begin
- RRD.update(self.path,arg)
- #system("rrdtool updatev %s '%s'" % [self.path, arg])
- rescue => detail
- raise Puppet::Error, "Failed to update %s: %s" % [self.name,detail]
- end
- end
-
- def values
- @values.sort { |a, b| a[1] <=> b[1] }
- end
- end
-end
-
-# $Id$
diff --git a/lib/puppet/networkclient.rb b/lib/puppet/networkclient.rb
index 8951c3ccb..f082665c0 100644
--- a/lib/puppet/networkclient.rb
+++ b/lib/puppet/networkclient.rb
@@ -5,7 +5,6 @@ require 'facter'
require 'openssl'
require 'puppet/transaction'
require 'puppet/transportable'
-require 'puppet/metric'
require 'puppet/daemon'
require 'puppet/server'
require 'puppet/external/base64'
diff --git a/lib/puppet/parameter.rb b/lib/puppet/parameter.rb
index 35db58815..d34bc7a9e 100644
--- a/lib/puppet/parameter.rb
+++ b/lib/puppet/parameter.rb
@@ -284,7 +284,7 @@ class Puppet::Parameter < Puppet::Element
self.devfail "Parent %s has no loglevel" %
@parent.name
end
- Puppet::Log.create(
+ Puppet::Util::Log.create(
:level => @parent[:loglevel],
:message => msg,
:source => self
diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb
index e8cfcc4dd..d8d421c47 100644
--- a/lib/puppet/parser/ast.rb
+++ b/lib/puppet/parser/ast.rb
@@ -1,7 +1,7 @@
# the parent class for all of our syntactical objects
require 'puppet'
-require 'puppet/autoload'
+require 'puppet/util/autoload'
# The base class for all of the objects that make up the parse trees.
# Handles things like file name, line #, and also does the initialization
@@ -114,7 +114,7 @@ class Puppet::Parser::AST
end
#---------------------------------------------------------------
# Now autoload everything.
- @autoloader = Puppet::Autoload.new(self,
+ @autoloader = Puppet::Util::Autoload.new(self,
"puppet/parser/ast"
)
@autoloader.loadall
diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb
index 9fbec43df..47c5ff110 100644
--- a/lib/puppet/parser/functions.rb
+++ b/lib/puppet/parser/functions.rb
@@ -1,5 +1,5 @@
# Grr
-require 'puppet/autoload'
+require 'puppet/util/autoload'
require 'puppet/parser/scope'
module Puppet::Parser
@@ -13,7 +13,7 @@ module Functions
def self.autoloader
unless defined? @autoloader
- @autoloader = Puppet::Autoload.new(self,
+ @autoloader = Puppet::Util::Autoload.new(self,
"puppet/parser/functions",
:wrap => false
)
@@ -181,7 +181,7 @@ module Functions
end
# Runs a newfunction to create a function for each of the log levels
- Puppet::Log.levels.each do |level|
+ Puppet::Util::Log.levels.each do |level|
newfunction(level, :doc => "Log a message on the server at level
#{level.to_s}.") do |vals|
send(level, vals.join(" "))
diff --git a/lib/puppet/parser/grammar.ra b/lib/puppet/parser/grammar.ra
index fe4a08c57..5877439ec 100644
--- a/lib/puppet/parser/grammar.ra
+++ b/lib/puppet/parser/grammar.ra
@@ -615,7 +615,7 @@ endcomma: # nothing
end
---- header ----
require 'puppet'
-require 'puppet/loadedfile'
+require 'puppet/util/loadedfile'
require 'puppet/parser/lexer'
require 'puppet/parser/ast'
#require 'puppet/parser/interpreter'
diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb
index 63b107985..3b268c16c 100644
--- a/lib/puppet/parser/interpreter.rb
+++ b/lib/puppet/parser/interpreter.rb
@@ -611,8 +611,8 @@ class Puppet::Parser::Interpreter
# reparsed.
def newfile(*files)
files.each do |file|
- unless file.is_a? Puppet::LoadedFile
- file = Puppet::LoadedFile.new(file)
+ unless file.is_a? Puppet::Util::LoadedFile
+ file = Puppet::Util::LoadedFile.new(file)
end
@files << file
end
diff --git a/lib/puppet/parser/parser.rb b/lib/puppet/parser/parser.rb
index 414405302..94d4f7fad 100644
--- a/lib/puppet/parser/parser.rb
+++ b/lib/puppet/parser/parser.rb
@@ -8,7 +8,7 @@ require 'racc/parser'
require 'puppet'
-require 'puppet/loadedfile'
+require 'puppet/util/loadedfile'
require 'puppet/parser/lexer'
require 'puppet/parser/ast'
#require 'puppet/parser/interpreter'
@@ -29,7 +29,7 @@ module Puppet
class Parser < Racc::Parser
-module_eval <<'..end grammar.ra modeval..id0df015d0a0', 'grammar.ra', 633
+module_eval <<'..end grammar.ra modeval..id05c09a2dac', 'grammar.ra', 633
require 'puppet/parser/functions'
attr_reader :file, :interp
@@ -101,7 +101,7 @@ def file=(file)
if @files.detect { |f| f.file == file }
raise Puppet::ImportError.new("Import loop detected")
else
- @files << Puppet::LoadedFile.new(file)
+ @files << Puppet::Util::LoadedFile.new(file)
@lexer.file = file
end
end
@@ -199,7 +199,7 @@ end
# $Id$
-..end grammar.ra modeval..id0df015d0a0
+..end grammar.ra modeval..id05c09a2dac
##### racc 1.4.5 generates ###
diff --git a/lib/puppet/provider/parsedfile.rb b/lib/puppet/provider/parsedfile.rb
index a685c7250..f1b77e56b 100755
--- a/lib/puppet/provider/parsedfile.rb
+++ b/lib/puppet/provider/parsedfile.rb
@@ -1,5 +1,5 @@
require 'puppet'
-require 'puppet/filetype'
+require 'puppet/util/filetype'
require 'puppet/util/fileparsing'
# This provider can be used as the parent class for a provider that
@@ -37,7 +37,7 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
def self.filetype
unless defined? @filetype
- @filetype = Puppet::FileType.filetype(:flat)
+ @filetype = Puppet::Util::FileType.filetype(:flat)
end
return @filetype
end
@@ -45,7 +45,7 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
def self.filetype=(type)
if type.is_a?(Class)
@filetype = type
- elsif klass = Puppet::FileType.filetype(type)
+ elsif klass = Puppet::Util::FileType.filetype(type)
@filetype = klass
else
raise ArgumentError, "Invalid filetype %s" % type
@@ -101,7 +101,7 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
@target = nil
# Default to flat files
- @filetype = Puppet::FileType.filetype(:flat)
+ @filetype = Puppet::Util::FileType.filetype(:flat)
super
end
diff --git a/lib/puppet/reports/log.rb b/lib/puppet/reports/log.rb
index 4df832980..614a07c7a 100644
--- a/lib/puppet/reports/log.rb
+++ b/lib/puppet/reports/log.rb
@@ -5,7 +5,7 @@ Puppet::Server::Report.newreport(:log) do
def process
self.logs.each do |log|
- Puppet::Log.newmessage(log)
+ Puppet::Util::Log.newmessage(log)
end
end
end
diff --git a/lib/puppet/reports/rrdgraph.rb b/lib/puppet/reports/rrdgraph.rb
index 86f54bf5d..ef353a1b9 100644
--- a/lib/puppet/reports/rrdgraph.rb
+++ b/lib/puppet/reports/rrdgraph.rb
@@ -96,7 +96,7 @@ Puppet::Server::Report.newreport(:rrdgraph) do
unless File.directory?(hostdir)
# Some hackishness to create the dir
- config = Puppet::Config.new
+ config = Puppet::Util::Config.new
config.setdefaults(:reports, :hostdir => [hostdir, "eh"])
# This creates the dir.
diff --git a/lib/puppet/reports/store.rb b/lib/puppet/reports/store.rb
index cb0aa0a3c..23bbc037e 100644
--- a/lib/puppet/reports/store.rb
+++ b/lib/puppet/reports/store.rb
@@ -11,7 +11,7 @@ Puppet::Server::Report.newreport(:store, :useyaml => true) do
default report)."
def mkclientdir(client, dir)
- config = Puppet::Config.new
+ config = Puppet::Util::Config.new
config.setdefaults("reportclient-#{client}",
"clientdir-#{client}" => { :default => dir,
:mode => 0750,
diff --git a/lib/puppet/server/authconfig.rb b/lib/puppet/server/authconfig.rb
index 073ff9516..d43371a77 100644
--- a/lib/puppet/server/authconfig.rb
+++ b/lib/puppet/server/authconfig.rb
@@ -1,4 +1,4 @@
-require 'puppet/loadedfile'
+require 'puppet/util/loadedfile'
require 'puppet/server/rights'
module Puppet
@@ -6,7 +6,7 @@ class Server
class ConfigurationError < Puppet::Error; end
-class AuthConfig < Puppet::LoadedFile
+class AuthConfig < Puppet::Util::LoadedFile
Puppet.config.setdefaults(:puppet,
:authconfig => [ "$confdir/namespaceauth.conf",
"The configuration file that defines the rights to the different
diff --git a/lib/puppet/server/fileserver.rb b/lib/puppet/server/fileserver.rb
index b541f2474..3ea44d785 100755
--- a/lib/puppet/server/fileserver.rb
+++ b/lib/puppet/server/fileserver.rb
@@ -75,7 +75,7 @@ class Server
if hash[:Config] == false
@noreadconfig = true
else
- @config = Puppet::LoadedFile.new(
+ @config = Puppet::Util::LoadedFile.new(
hash[:Config] || Puppet[:fileserverconfig]
)
@noreadconfig = false
diff --git a/lib/puppet/server/logger.rb b/lib/puppet/server/logger.rb
index 2170a5772..aa3521573 100755
--- a/lib/puppet/server/logger.rb
+++ b/lib/puppet/server/logger.rb
@@ -42,7 +42,7 @@ class Server
end
end
- Puppet::Log.newmessage(message)
+ Puppet::Util::Log.newmessage(message)
# This is necessary or XMLRPC gets all pukey
return ""
diff --git a/lib/puppet/server/report.rb b/lib/puppet/server/report.rb
index 3c325041d..4298f8ee6 100755
--- a/lib/puppet/server/report.rb
+++ b/lib/puppet/server/report.rb
@@ -39,7 +39,7 @@ class Server
)
@reports = {}
- @reportloader = Puppet::Autoload.new(self, "puppet/reports")
+ @reportloader = Puppet::Util::Autoload.new(self, "puppet/reports")
class << self
attr_reader :hooks
diff --git a/lib/puppet/sslcertificates/ca.rb b/lib/puppet/sslcertificates/ca.rb
index 13b845472..0d5678b7a 100644
--- a/lib/puppet/sslcertificates/ca.rb
+++ b/lib/puppet/sslcertificates/ca.rb
@@ -237,7 +237,7 @@ class Puppet::SSLCertificates::CA
)
# This creates the cakey file
- Puppet::SUIDManager.asuser(Puppet[:user], Puppet[:group]) do
+ Puppet::Util::SUIDManager.asuser(Puppet[:user], Puppet[:group]) do
@cert = cert.mkselfsigned
end
Puppet.config.write(:cacert) do |f|
diff --git a/lib/puppet/storage.rb b/lib/puppet/storage.rb
deleted file mode 100644
index ebebb8ee5..000000000
--- a/lib/puppet/storage.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-require 'yaml'
-require 'sync'
-#require 'puppet/lockfile'
-
-module Puppet
- # a class for storing state
- class Storage
- include Singleton
- include Puppet::Util
-
- def initialize
- self.class.load
- end
-
- # Return a hash that will be stored to disk. It's worth noting
- # here that we use the object's full path, not just the name/type
- # combination. At the least, this is useful for those non-isomorphic
- # types like exec, but it also means that if an object changes locations
- # in the configuration it will lose its cache.
- def self.cache(object)
- if object.is_a? Puppet::Type
- # We used to store things by path, now we store them by ref.
- # In oscar(0.20.0) this changed to using the ref.
- if @@state.include?(object.path)
- @@state[object.ref] = @@state[object.path]
- @@state.delete(object.path)
- end
- name = object.ref
- elsif object.is_a?(Symbol)
- name = object
- else
- raise ArgumentError, "You can only cache information for Types and symbols"
- end
-
- return @@state[name] ||= {}
- end
-
- def self.clear
- @@state.clear
- Storage.init
- end
-
- def self.init
- @@state = {}
- @@splitchar = "\t"
- end
-
- self.init
-
- def self.load
- Puppet.config.use(:puppet)
-
- unless File.exists?(Puppet[:statefile])
- unless defined? @@state and ! @@state.nil?
- self.init
- end
- return
- end
- Puppet::Util.benchmark(:debug, "Loaded state") do
- Puppet::Util.readlock(Puppet[:statefile]) do |file|
- begin
- @@state = YAML.load(file)
- rescue => detail
- Puppet.err "Checksumfile %s is corrupt (%s); replacing" %
- [Puppet[:statefile], detail]
- begin
- File.rename(Puppet[:statefile],
- Puppet[:statefile] + ".bad")
- rescue
- raise Puppet::Error,
- "Could not rename corrupt %s; remove manually" %
- Puppet[:statefile]
- end
- end
- end
- end
-
- unless @@state.is_a?(Hash)
- Puppet.err "State got corrupted"
- self.init
- end
-
- #Puppet.debug "Loaded state is %s" % @@state.inspect
- end
-
- def self.stateinspect
- @@state.inspect
- end
-
- def self.store
- Puppet.debug "Storing state"
-
- unless FileTest.exist?(Puppet[:statefile])
- Puppet.info "Creating state file %s" % Puppet[:statefile]
- end
-
- Puppet::Util.benchmark(:debug, "Stored state") do
- Puppet::Util.writelock(Puppet[:statefile], 0660) do |file|
- file.print YAML.dump(@@state)
- end
- end
- end
- end
-end
-
-# $Id$
diff --git a/lib/puppet/suidmanager.rb b/lib/puppet/suidmanager.rb
deleted file mode 100644
index 659ffaab8..000000000
--- a/lib/puppet/suidmanager.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-require 'facter'
-require 'puppet/util/warnings'
-
-module Puppet
- module SUIDManager
- include Puppet::Util::Warnings
-
- platform = Facter["kernel"].value
- [:uid=, :gid=, :uid, :gid].each do |method|
- define_method(method) do |*args|
- # NOTE: 'method' is closed here.
- newmethod = method
-
- if platform == "Darwin" and (method == :uid= or method == :gid=)
- Puppet::Util::Warnings.warnonce "Cannot change real UID on Darwin"
- newmethod = ("e" + method.to_s).intern
- end
-
- return Process.send(newmethod, *args)
- end
- module_function method
- end
-
- [:euid=, :euid, :egid=, :egid].each do |method|
- define_method(method) do |*args|
- Process.send(method, *args)
- end
- module_function method
- end
-
- def asuser(new_euid=nil, new_egid=nil)
- # Unless we're root, don't do a damn thing.
- unless Process.uid == 0
- return yield
- end
- old_egid = old_euid = nil
- if new_egid
- old_egid = self.egid
- self.egid = convert_xid(:gid, new_egid)
- end
- if new_euid
- old_euid = self.euid
- self.euid = convert_xid(:uid, new_euid)
- end
-
- return yield
- ensure
- self.euid = old_euid if old_euid
- self.egid = old_egid if old_egid
- end
-
- # Make sure the passed argument is a number.
- def convert_xid(type, id)
- map = {:gid => :group, :uid => :user}
- raise ArgumentError, "Invalid id type %s" % type unless map.include?(type)
- ret = Puppet::Util.send(type, id)
- if ret == nil
- raise Puppet::Error, "Invalid %s: %s" % [map[type], id]
- end
- return ret
- end
-
- module_function :asuser, :convert_xid
-
- def run_and_capture(command, new_uid=nil, new_gid=nil)
- output = nil
-
- output = Puppet::Util.execute(command, false, new_uid, new_gid)
-
- [output, $?.dup]
- end
-
- module_function :run_and_capture
-
- def system(command, new_uid=nil, new_gid=nil)
- status = nil
- asuser(new_uid, new_gid) do
- Kernel.system(command)
- status = $?.dup
- end
- status
- end
-
- module_function :system
- end
-end
-
-# $Id$
diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb
index 3c8a3a2e8..43ee135a6 100644
--- a/lib/puppet/transaction.rb
+++ b/lib/puppet/transaction.rb
@@ -292,7 +292,7 @@ class Transaction
graph(@resources, :resources)
# Start logging.
- Puppet::Log.newdestination(@report)
+ Puppet::Util::Log.newdestination(@report)
prepare()
@@ -314,7 +314,7 @@ class Transaction
}.flatten.reject { |e| e.nil? }
ensure
# And then close the transaction log.
- Puppet::Log.close(@report)
+ Puppet::Util::Log.close(@report)
end
Puppet.debug "Finishing transaction %s with %s changes" %
diff --git a/lib/puppet/transaction/report.rb b/lib/puppet/transaction/report.rb
index 769866ef0..e14135140 100644
--- a/lib/puppet/transaction/report.rb
+++ b/lib/puppet/transaction/report.rb
@@ -25,7 +25,7 @@ class Puppet::Transaction::Report
# Create a new metric.
def newmetric(name, hash)
- metric = Puppet::Metric.new(name)
+ metric = Puppet::Util::Metric.new(name)
hash.each do |name, value|
metric.newvalue(name, value)
diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb
index fd4704ae5..023f85ab3 100644
--- a/lib/puppet/type.rb
+++ b/lib/puppet/type.rb
@@ -1,12 +1,12 @@
require 'puppet'
-require 'puppet/log'
+require 'puppet/util/log'
require 'puppet/element'
require 'puppet/event'
-require 'puppet/metric'
+require 'puppet/util/metric'
require 'puppet/type/property'
require 'puppet/parameter'
require 'puppet/util'
-require 'puppet/autoload'
+require 'puppet/util/autoload'
require 'puppet/metatype/manager'
# see the bottom of the file for the rest of the inclusions
@@ -141,7 +141,7 @@ class Type < Puppet::Element
# create a log at specified level
def log(msg)
- Puppet::Log.create(
+ Puppet::Util::Log.create(
:level => @parameters[:loglevel].value,
:message => msg,
:source => self
@@ -299,13 +299,13 @@ class Type < Puppet::Element
# Return a cached value
def cached(name)
- Puppet::Storage.cache(self)[name]
+ Puppet::Util::Storage.cache(self)[name]
#@cache[name] ||= nil
end
# Cache a value
def cache(name, value)
- Puppet::Storage.cache(self)[name] = value
+ Puppet::Util::Storage.cache(self)[name] = value
#@cache[name] = value
end
diff --git a/lib/puppet/type/cron.rb b/lib/puppet/type/cron.rb
index 9c991886e..a91af13ed 100755
--- a/lib/puppet/type/cron.rb
+++ b/lib/puppet/type/cron.rb
@@ -1,7 +1,7 @@
require 'etc'
require 'facter'
require 'puppet/type/property'
-require 'puppet/filetype'
+require 'puppet/util/filetype'
require 'puppet/type/parsedtype'
module Puppet
@@ -433,9 +433,9 @@ module Puppet
def self.defaulttype
case Facter["operatingsystem"].value
when "Solaris":
- return Puppet::FileType.filetype(:suntab)
+ return Puppet::Util::FileType.filetype(:suntab)
else
- return Puppet::FileType.filetype(:crontab)
+ return Puppet::Util::FileType.filetype(:crontab)
end
end
diff --git a/lib/puppet/type/exec.rb b/lib/puppet/type/exec.rb
index 9dfa2b05e..33796b129 100755
--- a/lib/puppet/type/exec.rb
+++ b/lib/puppet/type/exec.rb
@@ -195,7 +195,7 @@ module Puppet
# Most validation is handled by the SUIDManager class.
validate do |user|
- unless Puppet::SUIDManager.uid == 0
+ unless Puppet::Util::SUIDManager.uid == 0
self.fail "Only root can execute commands as other users"
end
end
@@ -235,7 +235,7 @@ module Puppet
values = [:true, :false]
# And all of the log levels
- Puppet::Log.eachlevel { |level| values << level }
+ Puppet::Util::Log.eachlevel { |level| values << level }
newvalues(*values)
end
@@ -473,9 +473,12 @@ module Puppet
self.collect { |i| i }
end
- # Verify that we pass all of the checks.
- def check
+ # Verify that we pass all of the checks. The argument determines whether
+ # we skip the :refreshonly check, which is necessary because we now check
+ # within refresh()
+ def check(refreshing = false)
self.class.checks.each { |check|
+ next if refreshing and check == :refreshonly
if @parameters.include?(check)
val = @parameters[check].value
val = [val] unless val.is_a? Array
@@ -498,9 +501,9 @@ module Puppet
end
end
- # this might be a very, very bad idea...
+ # Run the command, or optionally run a separately-specified command.
def refresh
- if self.check
+ if self.check(true)
if cmd = self[:refresh]
self.run(cmd)
else
@@ -563,7 +566,7 @@ module Puppet
withenv env do
Timeout::timeout(self[:timeout]) do
- output, status = Puppet::SUIDManager.run_and_capture(
+ output, status = Puppet::Util::SUIDManager.run_and_capture(
[command], self[:user], self[:group]
)
end
diff --git a/lib/puppet/type/parsedtype.rb b/lib/puppet/type/parsedtype.rb
index 1232c979e..40a90d5ae 100755
--- a/lib/puppet/type/parsedtype.rb
+++ b/lib/puppet/type/parsedtype.rb
@@ -1,6 +1,6 @@
require 'etc'
require 'facter'
-require 'puppet/filetype'
+require 'puppet/util/filetype'
require 'puppet/type/property'
module Puppet
diff --git a/lib/puppet/type/pfile.rb b/lib/puppet/type/pfile.rb
index 478978623..89e94d140 100644
--- a/lib/puppet/type/pfile.rb
+++ b/lib/puppet/type/pfile.rb
@@ -270,7 +270,7 @@ module Puppet
# Determine the user to write files as.
def asuser
if self.should(:owner) and ! self.should(:owner).is_a?(Symbol)
- writeable = Puppet::SUIDManager.asuser(self.should(:owner)) {
+ writeable = Puppet::Util::SUIDManager.asuser(self.should(:owner)) {
FileTest.writable?(File.dirname(self[:path]))
}
@@ -1058,7 +1058,7 @@ module Puppet
yield
# We're getting different behaviors from different versions of ruby, so...
# asroot = true
- # Puppet::SUIDManager.asuser(asuser(), self.should(:group)) do
+ # Puppet::Util::SUIDManager.asuser(asuser(), self.should(:group)) do
# if FileTest.writable?(dir)
# asroot = false
# yield
diff --git a/lib/puppet/type/pfile/owner.rb b/lib/puppet/type/pfile/owner.rb
index 908f25d0f..07a2b880b 100755
--- a/lib/puppet/type/pfile/owner.rb
+++ b/lib/puppet/type/pfile/owner.rb
@@ -121,7 +121,7 @@ module Puppet
end
def sync
- unless Puppet::SUIDManager.uid == 0
+ unless Puppet::Util::SUIDManager.uid == 0
unless defined? @@notifieduid
self.notice "Cannot manage ownership unless running as root"
#@parent.delete(self.name)
diff --git a/lib/puppet/type/pfile/source.rb b/lib/puppet/type/pfile/source.rb
index 12bb7003e..d06366a79 100755
--- a/lib/puppet/type/pfile/source.rb
+++ b/lib/puppet/type/pfile/source.rb
@@ -105,7 +105,7 @@ module Puppet
}
# we can't manage ownership as root, so don't even try
- unless Puppet::SUIDManager.uid == 0
+ unless Puppet::Util::SUIDManager.uid == 0
args.delete(:owner)
end
diff --git a/lib/puppet/type/pfile/target.rb b/lib/puppet/type/pfile/target.rb
index f6ae0f9c8..3de74bb74 100644
--- a/lib/puppet/type/pfile/target.rb
+++ b/lib/puppet/type/pfile/target.rb
@@ -28,7 +28,7 @@ module Puppet
@parent.remove_existing(target)
Dir.chdir(File.dirname(@parent[:path])) do
- Puppet::SUIDManager.asuser(@parent.asuser()) do
+ Puppet::Util::SUIDManager.asuser(@parent.asuser()) do
mode = @parent.should(:mode)
if mode
Puppet::Util.withumask(000) do
diff --git a/lib/puppet/type/property.rb b/lib/puppet/type/property.rb
index 7279ffee7..b4dcdfae0 100644
--- a/lib/puppet/type/property.rb
+++ b/lib/puppet/type/property.rb
@@ -281,7 +281,7 @@ class Property < Puppet::Parameter
self.devfail "Parent %s has no loglevel" %
@parent.name
end
- Puppet::Log.create(
+ Puppet::Util::Log.create(
:level => @parent[:loglevel],
:message => msg,
:source => self
diff --git a/lib/puppet/type/yumrepo.rb b/lib/puppet/type/yumrepo.rb
index b7a1ff5e7..94ba3ef6c 100644
--- a/lib/puppet/type/yumrepo.rb
+++ b/lib/puppet/type/yumrepo.rb
@@ -1,7 +1,7 @@
# Description of yum repositories
require 'puppet/propertychange'
-require 'puppet/inifile'
+require 'puppet/util/inifile'
require 'puppet/type/parsedtype'
module Puppet
@@ -72,7 +72,7 @@ module Puppet
attr_accessor :yumconf
end
- self.filetype = Puppet::FileType.filetype(:flat)
+ self.filetype = Puppet::Util::FileType.filetype(:flat)
@inifile = nil
@@ -102,7 +102,7 @@ module Puppet
l
end
- # Return the Puppet::IniConfig::File for the whole yum config
+ # Return the Puppet::Util::IniConfig::File for the whole yum config
def self.inifile
if @inifile.nil?
@inifile = read()
@@ -134,7 +134,7 @@ module Puppet
# Non-test code should use self.inifile to get at the
# underlying file
def self.read
- result = Puppet::IniConfig::File.new()
+ result = Puppet::Util::IniConfig::File.new()
result.read(yumconf)
main = result['main']
if main.nil?
@@ -161,7 +161,7 @@ module Puppet
return result
end
- # Return the Puppet::IniConfig::Section with name NAME
+ # Return the Puppet::Util::IniConfig::Section with name NAME
# from the yum config
def self.section(name)
result = inifile[name]
@@ -189,7 +189,7 @@ module Puppet
super
end
- # Return the Puppet::IniConfig::Section for this yumrepo element
+ # Return the Puppet::Util::IniConfig::Section for this yumrepo element
def section
self.class.section(self[:name])
end
diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb
index 2bd3035c6..3bd7d277c 100644
--- a/lib/puppet/util.rb
+++ b/lib/puppet/util.rb
@@ -33,10 +33,10 @@ module Util
unless group
raise Puppet::Error, "No such group %s" % Puppet[:group]
end
- unless Puppet::SUIDManager.gid == group
+ unless Puppet::Util::SUIDManager.gid == group
begin
- Puppet::SUIDManager.egid = group
- Puppet::SUIDManager.gid = group
+ Puppet::Util::SUIDManager.egid = group
+ Puppet::Util::SUIDManager.gid = group
rescue => detail
Puppet.warning "could not change to group %s: %s" %
[group.inspect, detail]
@@ -54,10 +54,10 @@ module Util
unless user
raise Puppet::Error, "No such user %s" % Puppet[:user]
end
- unless Puppet::SUIDManager.uid == user
+ unless Puppet::Util::SUIDManager.uid == user
begin
- Puppet::SUIDManager.uid = user
- Puppet::SUIDManager.euid = user
+ Puppet::Util::SUIDManager.uid = user
+ Puppet::Util::SUIDManager.euid = user
rescue
$stderr.puts "could not change to user %s" % user
exit(74)
@@ -104,19 +104,19 @@ module Util
# the messages to be a little richer. Most classes will be calling this
# method.
def self.logmethods(klass, useself = true)
- Puppet::Log.eachlevel { |level|
+ Puppet::Util::Log.eachlevel { |level|
klass.send(:define_method, level, proc { |args|
if args.is_a?(Array)
args = args.join(" ")
end
if useself
- Puppet::Log.create(
+ Puppet::Util::Log.create(
:level => level,
:source => self,
:message => args
)
else
- Puppet::Log.create(
+ Puppet::Util::Log.create(
:level => level,
:message => args
)
@@ -206,7 +206,7 @@ module Util
end
# Only benchmark if our log level is high enough
- if level != :none and Puppet::Log.sendlevel?(level)
+ if level != :none and Puppet::Util::Log.sendlevel?(level)
result = nil
seconds = Benchmark.realtime {
yield
@@ -285,10 +285,10 @@ module Util
end
if uid
- uid = Puppet::SUIDManager.convert_xid(:uid, uid)
+ uid = Puppet::Util::SUIDManager.convert_xid(:uid, uid)
end
if gid
- gid = Puppet::SUIDManager.convert_xid(:gid, gid)
+ gid = Puppet::Util::SUIDManager.convert_xid(:gid, gid)
end
@@os ||= Facter.value(:operatingsystem)
diff --git a/lib/puppet/autoload.rb b/lib/puppet/util/autoload.rb
index 862aabbff..f171254af 100644
--- a/lib/puppet/autoload.rb
+++ b/lib/puppet/util/autoload.rb
@@ -1,5 +1,5 @@
# Autoload paths, either based on names or all at once.
-class Puppet::Autoload
+class Puppet::Util::Autoload
include Puppet::Util
@autoloaders = {}
diff --git a/lib/puppet/config.rb b/lib/puppet/util/config.rb
index 77838fec0..097d59b9f 100644
--- a/lib/puppet/config.rb
+++ b/lib/puppet/util/config.rb
@@ -2,9 +2,8 @@ require 'puppet'
require 'sync'
require 'puppet/transportable'
-module Puppet
# The class for handling configuration files.
-class Config
+class Puppet::Util::Config
include Enumerable
include Puppet::Util
@@ -216,7 +215,7 @@ class Config
raise ArgumentError, "Default %s is not a file" % default
end
- Puppet::SUIDManager.asuser(obj.owner, obj.group) do
+ Puppet::Util::SUIDManager.asuser(obj.owner, obj.group) do
mode = obj.mode || 0750
Dir.mkdir(obj.value, mode)
end
@@ -248,10 +247,10 @@ class Config
def parse(file)
text = nil
- if file.is_a? Puppet::LoadedFile
+ if file.is_a? Puppet::Util::LoadedFile
@file = file
else
- @file = Puppet::LoadedFile.new(file)
+ @file = Puppet::Util::LoadedFile.new(file)
end
# Create a timer so that this.
@@ -430,7 +429,7 @@ class Config
newobj[:comment] ||= "%s user" % name
end
else
- newobj = TransObject.new(name, type.to_s)
+ newobj = Puppet::TransObject.new(name, type.to_s)
newobj.tags = ["puppet", "configuration", section]
newobj[:ensure] = "present"
if type == :user
@@ -643,12 +642,12 @@ Generated on #{Time.now}.
end
chown = nil
- if Puppet::SUIDManager.uid == 0
+ if Puppet::Util::SUIDManager.uid == 0
chown = [obj.owner, obj.group]
else
chown = [nil, nil]
end
- Puppet::SUIDManager.asuser(*chown) do
+ Puppet::Util::SUIDManager.asuser(*chown) do
mode = obj.mode || 0640
if args.empty?
@@ -676,13 +675,13 @@ Generated on #{Time.now}.
end
chown = nil
- if Puppet::SUIDManager.uid == 0
+ if Puppet::Util::SUIDManager.uid == 0
chown = [obj.owner, obj.group]
else
chown = [nil, nil]
end
- Puppet::SUIDManager.asuser(*chown) do
+ Puppet::Util::SUIDManager.asuser(*chown) do
mode = obj.mode || 0640
if args.empty?
args << "w"
@@ -906,7 +905,7 @@ Generated on #{Time.now}.
}
# Only chown or chgrp when root
- if Puppet::SUIDManager.uid == 0
+ if Puppet::Util::SUIDManager.uid == 0
[:group, :owner].each { |var|
if value = self.send(var)
obj[var] = value
@@ -956,6 +955,5 @@ Generated on #{Time.now}.
end
end
end
-end
# $Id$
diff --git a/lib/puppet/feature.rb b/lib/puppet/util/feature.rb
index ece8ec86a..30c38e286 100644
--- a/lib/puppet/feature.rb
+++ b/lib/puppet/util/feature.rb
@@ -1,7 +1,7 @@
# Created by Luke Kanies on 2006-11-07.
# Copyright (c) 2006. All rights reserved.
-class Puppet::Feature
+class Puppet::Util::Feature
attr_reader :path
# Create a new feature test. You have to pass the feature name,
@@ -52,7 +52,7 @@ class Puppet::Feature
# Create a new feature collection.
def initialize(path)
@path = path
- @loader = Puppet::Autoload.new(self, @path)
+ @loader = Puppet::Util::Autoload.new(self, @path)
end
def load
diff --git a/lib/puppet/util/filetype.rb b/lib/puppet/util/filetype.rb
new file mode 100755
index 000000000..8abe0cc00
--- /dev/null
+++ b/lib/puppet/util/filetype.rb
@@ -0,0 +1,300 @@
+# Basic classes for reading, writing, and emptying files. Not much
+# to see here.
+class Puppet::Util::FileType
+ attr_accessor :loaded, :path, :synced
+
+ class << self
+ attr_accessor :name
+ include Puppet::Util::ClassGen
+ end
+
+ # Create a new filetype.
+ def self.newfiletype(name, &block)
+ @filetypes ||= {}
+
+ klass = genclass(name,
+ :block => block,
+ :prefix => "FileType",
+ :hash => @filetypes
+ )
+
+ # Rename the read and write methods, so that we're sure they
+ # maintain the stats.
+ klass.class_eval do
+ # Rename the read method
+ define_method(:real_read, instance_method(:read))
+ define_method(:read) do
+ begin
+ val = real_read()
+ @loaded = Time.now
+ if val
+ return val.gsub(/# HEADER.*\n/,'')
+ else
+ return ""
+ end
+ rescue Puppet::Error => detail
+ raise
+ rescue => detail
+ if Puppet[:trace]
+ puts detail.backtrace
+ end
+ raise Puppet::Error, "%s could not read %s: %s" %
+ [self.class, @path, detail]
+ end
+ end
+
+ # And then the write method
+ define_method(:real_write, instance_method(:write))
+ define_method(:write) do |text|
+ begin
+ val = real_write(text)
+ @synced = Time.now
+ return val
+ rescue Puppet::Error => detail
+ raise
+ rescue => detail
+ if Puppet[:debug]
+ puts detail.backtrace
+ end
+ raise Puppet::Error, "%s could not write %s: %s" %
+ [self.class, @path, detail]
+ end
+ end
+ end
+ end
+
+ def self.filetype(type)
+ @filetypes[type]
+ end
+
+ def initialize(path)
+ @path = path
+ end
+
+ # Operate on plain files.
+ newfiletype(:flat) do
+ # Read the file.
+ def read
+ if File.exists?(@path)
+ File.read(@path)
+ else
+ return nil
+ end
+ end
+
+ # Remove the file.
+ def remove
+ if File.exists?(@path)
+ File.unlink(@path)
+ end
+ end
+
+ # Overwrite the file.
+ def write(text)
+ File.open(@path, "w") { |f| f.print text; f.flush }
+ end
+ end
+
+ # Operate on plain files.
+ newfiletype(:ram) do
+ @@tabs = {}
+
+ def self.clear
+ @@tabs.clear
+ end
+
+ def initialize(path)
+ super
+ @@tabs[@path] ||= ""
+ end
+
+ # Read the file.
+ def read
+ Puppet.info "Reading %s from RAM" % @path
+ @@tabs[@path]
+ end
+
+ # Remove the file.
+ def remove
+ Puppet.info "Removing %s from RAM" % @path
+ @@tabs[@path] = ""
+ end
+
+ # Overwrite the file.
+ def write(text)
+ Puppet.info "Writing %s to RAM" % @path
+ @@tabs[@path] = text
+ end
+ end
+
+ # Handle Linux-style cron tabs.
+ newfiletype(:crontab) do
+ def initialize(user)
+ self.path = user
+ end
+
+ def path=(user)
+ begin
+ @uid = Puppet::Util.uid(user)
+ rescue Puppet::Error => detail
+ raise Puppet::Error, "Could not retrieve user %s" % user
+ end
+
+ # XXX We have to have the user name, not the uid, because some
+ # systems *cough*linux*cough* require it that way
+ @path = user
+ end
+
+ # Read a specific @path's cron tab.
+ def read
+ %x{#{cmdbase()} -l 2>/dev/null}
+ end
+
+ # Remove a specific @path's cron tab.
+ def remove
+ if Facter.value("operatingsystem") == "FreeBSD"
+ %x{/bin/echo yes | #{cmdbase()} -r 2>/dev/null}
+ else
+ %x{#{cmdbase()} -r 2>/dev/null}
+ end
+ end
+
+ # Overwrite a specific @path's cron tab; must be passed the @path name
+ # and the text with which to create the cron tab.
+ def write(text)
+ IO.popen("#{cmdbase()} -", "w") { |p|
+ p.print text
+ }
+ end
+
+ private
+
+ # Only add the -u flag when the @path is different. Fedora apparently
+ # does not think I should be allowed to set the @path to my own user name
+ def cmdbase
+ cmd = nil
+ if @uid == Puppet::Util::SUIDManager.uid
+ return "crontab"
+ else
+ return "crontab -u #{@path}"
+ end
+ end
+ end
+
+ # SunOS has completely different cron commands; this class implements
+ # its versions.
+ newfiletype(:suntab) do
+ # Read a specific @path's cron tab.
+ def read
+ Puppet::Util::SUIDManager.asuser(@path) {
+ %x{crontab -l 2>/dev/null}
+ }
+ end
+
+ # Remove a specific @path's cron tab.
+ def remove
+ Puppet::Util::SUIDManager.asuser(@path) {
+ %x{crontab -r 2>/dev/null}
+ }
+ end
+
+ # Overwrite a specific @path's cron tab; must be passed the @path name
+ # and the text with which to create the cron tab.
+ def write(text)
+ Puppet::Util::SUIDManager.asuser(@path) {
+ IO.popen("crontab", "w") { |p|
+ p.print text
+ }
+ }
+ end
+ end
+
+ # Treat netinfo tables as a single file, just for simplicity of certain
+ # types
+ newfiletype(:netinfo) do
+ class << self
+ attr_accessor :format
+ end
+ def read
+ %x{nidump -r /#{@path} /}
+ end
+
+ # This really only makes sense for cron tabs.
+ def remove
+ %x{nireport / /#{@path} name}.split("\n").each do |name|
+ newname = name.gsub(/\//, '\/').sub(/\s+$/, '')
+ output = %x{niutil -destroy / '/#{@path}/#{newname}'}
+
+ unless $? == 0
+ raise Puppet::Error, "Could not remove %s from %s" %
+ [name, @path]
+ end
+ end
+ end
+
+ # Convert our table to an array of hashes. This only works for
+ # handling one table at a time.
+ def to_array(text = nil)
+ unless text
+ text = read
+ end
+
+ hash = nil
+
+ # Initialize it with the first record
+ records = []
+ text.split("\n").each do |line|
+ next if line =~ /^[{}]$/ # Skip the wrapping lines
+ next if line =~ /"name" = \( "#{@path}" \)/ # Skip the table name
+ next if line =~ /CHILDREN = \(/ # Skip this header
+ next if line =~ /^ \)/ # and its closer
+
+ # Now we should have nothing but records, wrapped in braces
+
+ case line
+ when /^\s+\{/: hash = {}
+ when /^\s+\}/: records << hash
+ when /\s+"(\w+)" = \( (.+) \)/
+ field = $1
+ values = $2
+
+ # Always use an array
+ hash[field] = []
+
+ values.split(/, /).each do |value|
+ if value =~ /^"(.*)"$/
+ hash[field] << $1
+ else
+ raise ArgumentError, "Could not match value %s" % value
+ end
+ end
+ else
+ raise ArgumentError, "Could not match line %s" % line
+ end
+ end
+
+ records
+ end
+
+ def write(text)
+ text.gsub!(/^#.*\n/,'')
+ text.gsub!(/^$/,'')
+ if text == "" or text == "\n"
+ self.remove
+ return
+ end
+ unless format = self.class.format
+ raise Puppe::DevError, "You must define the NetInfo format to inport"
+ end
+ IO.popen("niload -d #{format} . 1>/dev/null 2>/dev/null", "w") { |p|
+ p.print text
+ }
+
+ unless $? == 0
+ raise ArgumentError, "Failed to write %s" % @path
+ end
+ end
+ end
+end
+
+# $Id$
diff --git a/lib/puppet/util/inifile.rb b/lib/puppet/util/inifile.rb
new file mode 100644
index 000000000..d050e6dd1
--- /dev/null
+++ b/lib/puppet/util/inifile.rb
@@ -0,0 +1,209 @@
+# Module Puppet::IniConfig
+# A generic way to parse .ini style files and manipulate them in memory
+# One 'file' can be made up of several physical files. Changes to sections
+# on the file are tracked so that only the physical files in which
+# something has changed are written back to disk
+# Great care is taken to preserve comments and blank lines from the original
+# files
+#
+# The parsing tries to stay close to python's ConfigParser
+
+require 'puppet/util/filetype'
+
+module Puppet::Util::IniConfig
+ # A section in a .ini file
+ class Section
+ attr_reader :name, :file
+
+ def initialize(name, file)
+ @name = name
+ @file = file
+ @dirty = false
+ @entries = []
+ end
+
+ # Has this section been modified since it's been read in
+ # or written back to disk
+ def dirty?
+ @dirty
+ end
+
+ # Should only be used internally
+ def mark_clean
+ @dirty = false
+ end
+
+ # Add a line of text (e.g., a comment) Such lines
+ # will be written back out in exactly the same
+ # place they were read in
+ def add_line(line)
+ @entries << line
+ end
+
+ # Set the entry 'key=value'. If no entry with the
+ # given key exists, one is appended to teh end of the section
+ def []=(key, value)
+ entry = find_entry(key)
+ @dirty = true
+ if entry.nil?
+ @entries << [key, value]
+ else
+ entry[1] = value
+ end
+ end
+
+ # Return the value associated with KEY. If no such entry
+ # exists, return nil
+ def [](key)
+ entry = find_entry(key)
+ if entry.nil?
+ return nil
+ end
+ return entry[1]
+ end
+
+ # Format the section as text in the way it should be
+ # written to file
+ def format
+ text = "[#{name}]\n"
+ @entries.each do |entry|
+ if entry.is_a?(Array)
+ key, value = entry
+ unless value.nil?
+ text << "#{key}=#{value}\n"
+ end
+ else
+ text << entry
+ end
+ end
+ return text
+ end
+
+ private
+ def find_entry(key)
+ @entries.each do |entry|
+ if entry.is_a?(Array) && entry[0] == key
+ return entry
+ end
+ end
+ return nil
+ end
+
+ end
+
+ # A logical .ini-file that can be spread across several physical
+ # files. For each physical file, call #read with the filename
+ class File
+ def initialize
+ @files = {}
+ end
+
+ # Add the contents of the file with name FILE to the
+ # already existing sections
+ def read(file)
+ text = Puppet::Util::FileType.filetype(:flat).new(file).read
+ if text.nil?
+ raise "Could not find #{file}"
+ end
+
+ section = nil # The name of the current section
+ optname = nil # The name of the last option in section
+ line = 0
+ @files[file] = []
+ text.each_line do |l|
+ line += 1
+ if l.strip.empty? || "#;".include?(l[0,1]) ||
+ (l.split(nil, 2)[0].downcase == "rem" &&
+ l[0,1].downcase == "r")
+ # Whitespace or comment
+ if section.nil?
+ @files[file] << l
+ else
+ section.add_line(l)
+ end
+ elsif " \t\r\n\f".include?(l[0,1]) && section && optname
+ # continuation line
+ section[optname] += "\n" + l.chomp
+ elsif l =~ /^\[([^\]]+)\]/
+ # section heading
+ section.mark_clean unless section.nil?
+ section = add_section($1, file)
+ optname = nil
+ elsif l =~ /^\s*([^\s=]+)\s*\=(.+)$/
+ # We allow space around the keys, but not the values
+ # For the values, we don't know if space is significant
+ if section.nil?
+ raise "#{file}:#{line}:Key/value pair outside of a section for key #{$1}"
+ else
+ section[$1] = $2
+ optname = $1
+ end
+ else
+ raise "#{file}:#{line}: Can't parse '#{l.chomp}'"
+ end
+ end
+ section.mark_clean unless section.nil?
+ end
+
+ # Store all modifications made to sections in this file back
+ # to the physical files. If no modifications were made to
+ # a physical file, nothing is written
+ def store
+ @files.each do |file, lines|
+ text = ""
+ dirty = false
+ lines.each do |l|
+ if l.is_a?(Section)
+ dirty ||= l.dirty?
+ text << l.format
+ l.mark_clean
+ else
+ text << l
+ end
+ end
+ if dirty
+ Puppet::Util::FileType.filetype(:flat).new(file).write(text)
+ end
+ end
+ end
+
+ # Execute BLOCK, passing each section in this file
+ # as an argument
+ def each_section(&block)
+ @files.each do |file, list|
+ list.each do |entry|
+ if entry.is_a?(Section)
+ yield(entry)
+ end
+ end
+ end
+ end
+
+ # Return the Section with the given name or nil
+ def [](name)
+ name = name.to_s
+ each_section do |section|
+ return section if section.name == name
+ end
+ return nil
+ end
+
+ # Return true if the file contains a section with name NAME
+ def include?(name)
+ return ! self[name].nil?
+ end
+
+ # Add a section to be stored in FILE when store is called
+ def add_section(name, file)
+ if include?(name)
+ raise "A section with name #{name} already exists"
+ end
+ result = Section.new(name, file)
+ @files[file] ||= []
+ @files[file] << result
+ return result
+ end
+ end
+end
+
+# $Id$
diff --git a/lib/puppet/loadedfile.rb b/lib/puppet/util/loadedfile.rb
index cfd666e36..362b5df09 100755
--- a/lib/puppet/loadedfile.rb
+++ b/lib/puppet/util/loadedfile.rb
@@ -5,7 +5,7 @@ require 'puppet'
module Puppet
class NoSuchFile < Puppet::Error; end
- class LoadedFile
+ class Util::LoadedFile
attr_reader :file, :statted
# Provide a hook for setting the timestamp during testing, so we don't
diff --git a/lib/puppet/util/log.rb b/lib/puppet/util/log.rb
new file mode 100644
index 000000000..dd7544dae
--- /dev/null
+++ b/lib/puppet/util/log.rb
@@ -0,0 +1,548 @@
+require 'syslog'
+
+# Pass feedback to the user. Log levels are modeled after syslog's, and it is
+# expected that that will be the most common log destination. Supports
+# multiple destinations, one of which is a remote server.
+class Puppet::Util::Log
+ include Puppet::Util
+
+ @levels = [:debug,:info,:notice,:warning,:err,:alert,:emerg,:crit]
+ @loglevel = 2
+
+ @desttypes = {}
+
+ # A type of log destination.
+ class Destination
+ class << self
+ attr_accessor :name
+ end
+
+ def self.initvars
+ @matches = []
+ end
+
+ # Mark the things we're supposed to match.
+ def self.match(obj)
+ @matches ||= []
+ @matches << obj
+ end
+
+ # See whether we match a given thing.
+ def self.match?(obj)
+ # Convert single-word strings into symbols like :console and :syslog
+ if obj.is_a? String and obj =~ /^\w+$/
+ obj = obj.downcase.intern
+ end
+
+ @matches.each do |thing|
+ # Search for direct matches or class matches
+ return true if thing === obj or thing == obj.class.to_s
+ end
+ return false
+ end
+
+ def name
+ if defined? @name
+ return @name
+ else
+ return self.class.name
+ end
+ end
+
+ # Set how to handle a message.
+ def self.sethandler(&block)
+ define_method(:handle, &block)
+ end
+
+ # Mark how to initialize our object.
+ def self.setinit(&block)
+ define_method(:initialize, &block)
+ end
+ end
+
+ # Create a new destination type.
+ def self.newdesttype(name, options = {}, &block)
+ dest = genclass(name, :parent => Destination, :prefix => "Dest",
+ :block => block,
+ :hash => @desttypes,
+ :attributes => options
+ )
+ dest.match(dest.name)
+
+ return dest
+ end
+
+ @destinations = {}
+
+ class << self
+ include Puppet::Util
+ include Puppet::Util::ClassGen
+ end
+
+ # Reset all logs to basics. Basically just closes all files and undefs
+ # all of the other objects.
+ def Log.close(dest = nil)
+ if dest
+ if @destinations.include?(dest)
+ if @destinations.respond_to?(:close)
+ @destinations[dest].close
+ end
+ @destinations.delete(dest)
+ end
+ else
+ @destinations.each { |name, dest|
+ if dest.respond_to?(:flush)
+ dest.flush
+ end
+ if dest.respond_to?(:close)
+ dest.close
+ end
+ }
+ @destinations = {}
+ end
+ end
+
+ # Flush any log destinations that support such operations.
+ def Log.flush
+ @destinations.each { |type, dest|
+ if dest.respond_to?(:flush)
+ dest.flush
+ end
+ }
+ end
+
+ # Create a new log message. The primary role of this method is to
+ # avoid creating log messages below the loglevel.
+ def Log.create(hash)
+ unless hash.include?(:level)
+ raise Puppet::DevError, "Logs require a level"
+ end
+ unless @levels.index(hash[:level])
+ raise Puppet::DevError, "Invalid log level %s" % hash[:level]
+ end
+ if @levels.index(hash[:level]) >= @loglevel
+ return Puppet::Util::Log.new(hash)
+ else
+ return nil
+ end
+ end
+
+ def Log.destinations
+ return @destinations.keys
+ end
+
+ # Yield each valid level in turn
+ def Log.eachlevel
+ @levels.each { |level| yield level }
+ end
+
+ # Return the current log level.
+ def Log.level
+ return @levels[@loglevel]
+ end
+
+ # Set the current log level.
+ def Log.level=(level)
+ unless level.is_a?(Symbol)
+ level = level.intern
+ end
+
+ unless @levels.include?(level)
+ raise Puppet::DevError, "Invalid loglevel %s" % level
+ end
+
+ @loglevel = @levels.index(level)
+ end
+
+ def Log.levels
+ @levels.dup
+ end
+
+ newdesttype :syslog do
+ def close
+ Syslog.close
+ end
+
+ def initialize
+ if Syslog.opened?
+ Syslog.close
+ end
+ name = Puppet.name
+ name = "puppet-#{name}" unless name =~ /puppet/
+
+ options = Syslog::LOG_PID | Syslog::LOG_NDELAY
+
+ # XXX This should really be configurable.
+ str = Puppet[:syslogfacility]
+ begin
+ facility = Syslog.const_get("LOG_#{str.upcase}")
+ rescue NameError
+ raise Puppet::Error, "Invalid syslog facility %s" % str
+ end
+
+ @syslog = Syslog.open(name, options, facility)
+ end
+
+ def handle(msg)
+ # XXX Syslog currently has a bug that makes it so you
+ # cannot log a message with a '%' in it. So, we get rid
+ # of them.
+ if msg.source == "Puppet"
+ @syslog.send(msg.level, msg.to_s.gsub("%", '%%'))
+ else
+ @syslog.send(msg.level, "(%s) %s" %
+ [msg.source.to_s.gsub("%", ""),
+ msg.to_s.gsub("%", '%%')
+ ]
+ )
+ end
+ end
+ end
+
+ newdesttype :file do
+ match(/^\//)
+
+ def close
+ if defined? @file
+ @file.close
+ @file = nil
+ end
+ end
+
+ def flush
+ if defined? @file
+ @file.flush
+ end
+ end
+
+ def initialize(path)
+ @name = path
+ # 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(path))
+ Puppet.recmkdir(File.dirname(path))
+ Puppet.info "Creating log directory %s" % File.dirname(path)
+ end
+
+ # create the log file, if it doesn't already exist
+ file = File.open(path, File::WRONLY|File::CREAT|File::APPEND)
+
+ @file = file
+
+ @autoflush = Puppet[:autoflush]
+ end
+
+ def handle(msg)
+ @file.puts("%s %s (%s): %s" %
+ [msg.time, msg.source, msg.level, msg.to_s])
+
+ @file.flush if @autoflush
+ end
+ end
+
+ newdesttype :console do
+
+
+ PINK = {:console => "", :html => "FFA0A0"}
+ GREEN = {:console => "", :html => "00CD00"}
+ YELLOW = {:console => "", :html => "FFFF60"}
+ SLATE = {:console => "", :html => "80A0FF"}
+ ORANGE = {:console => "", :html => "FFA500"}
+ BLUE = {:console => "", :html => "40FFFF"}
+ RESET = {:console => "", :html => ""}
+
+ @@colormap = {
+ :debug => SLATE,
+ :info => GREEN,
+ :notice => PINK,
+ :warning => ORANGE,
+ :err => YELLOW,
+ :alert => BLUE,
+ :emerg => RESET,
+ :crit => RESET
+ }
+
+ def colorize(level, str)
+ case Puppet[:color]
+ when false: str
+ when true, :ansi, "ansi": console_color(level, str)
+ when :html, "html": html_color(level, str)
+ end
+ end
+
+ def console_color(level, str)
+ @@colormap[level][:console] + str + RESET[:console]
+ end
+
+ def html_color(level, str)
+ %{<span style="color: %s">%s</span>} % [@@colormap[level][:html], str]
+ end
+
+ def initialize
+ # Flush output immediately.
+ $stdout.sync = true
+ end
+
+ def handle(msg)
+ if msg.source == "Puppet"
+ puts colorize(msg.level, "%s: %s" % [msg.level, msg.to_s])
+ else
+ puts colorize(msg.level, "%s: %s: %s" % [msg.level, msg.source, msg.to_s])
+ end
+ end
+ end
+
+ newdesttype :host do
+ def initialize(host)
+ Puppet.info "Treating %s as a hostname" % host
+ args = {}
+ if host =~ /:(\d+)/
+ args[:Port] = $1
+ args[:Server] = host.sub(/:\d+/, '')
+ else
+ args[:Server] = host
+ end
+
+ @name = host
+
+ @driver = Puppet::Client::LogClient.new(args)
+ end
+
+ def handle(msg)
+ unless msg.is_a?(String) or msg.remote
+ unless defined? @hostname
+ @hostname = Facter["hostname"].value
+ end
+ unless defined? @domain
+ @domain = Facter["domain"].value
+ if @domain
+ @hostname += "." + @domain
+ end
+ end
+ if msg.source =~ /^\//
+ msg.source = @hostname + ":" + msg.source
+ elsif msg.source == "Puppet"
+ msg.source = @hostname + " " + msg.source
+ else
+ msg.source = @hostname + " " + msg.source
+ end
+ begin
+ #puts "would have sent %s" % msg
+ #puts "would have sent %s" %
+ # CGI.escape(YAML.dump(msg))
+ begin
+ tmp = CGI.escape(YAML.dump(msg))
+ rescue => detail
+ puts "Could not dump: %s" % detail.to_s
+ return
+ end
+ # Add the hostname to the source
+ @driver.addlog(tmp)
+ rescue => detail
+ if Puppet[:trace]
+ puts detail.backtrace
+ end
+ Puppet.err detail
+ Puppet::Util::Log.close(self)
+ end
+ end
+ end
+ end
+
+ # Log to a transaction report.
+ newdesttype :report do
+ match "Puppet::Transaction::Report"
+
+ def initialize(report)
+ @report = report
+ end
+
+ def handle(msg)
+ # Only add messages from objects, since anything else is
+ # probably unrelated to this run.
+ if msg.objectsource?
+ @report.newlog(msg)
+ end
+ end
+ end
+
+ # Log to an array, just for testing.
+ newdesttype :array do
+ match "Array"
+
+ def initialize(array)
+ @array = array
+ end
+
+ def handle(msg)
+ @array << msg
+ end
+ end
+
+ # Create a new log destination.
+ def Log.newdestination(dest)
+ # Each destination can only occur once.
+ if @destinations.find { |name, obj| obj.name == dest }
+ return
+ end
+
+ name, type = @desttypes.find do |name, klass|
+ klass.match?(dest)
+ end
+
+ unless type
+ raise Puppet::DevError, "Unknown destination type %s" % dest
+ end
+
+ begin
+ if type.instance_method(:initialize).arity == 1
+ @destinations[dest] = type.new(dest)
+ else
+ @destinations[dest] = type.new()
+ end
+ rescue => detail
+ if Puppet[:debug]
+ puts detail.backtrace
+ end
+
+ # If this was our only destination, then add the console back in.
+ if @destinations.empty? and (dest != :console and dest != "console")
+ newdestination(:console)
+ end
+ end
+ end
+
+ # Route the actual message. FIXME There are lots of things this method
+ # should do, like caching, storing messages when there are not yet
+ # destinations, a bit more. It's worth noting that there's a potential
+ # for a loop here, if the machine somehow gets the destination set as
+ # itself.
+ def Log.newmessage(msg)
+ if @levels.index(msg.level) < @loglevel
+ return
+ end
+
+ @destinations.each do |name, dest|
+ threadlock(dest) do
+ dest.handle(msg)
+ end
+ end
+ end
+
+ def Log.sendlevel?(level)
+ @levels.index(level) >= @loglevel
+ end
+
+ # Reopen all of our logs.
+ def Log.reopen
+ Puppet.notice "Reopening log files"
+ types = @destinations.keys
+ @destinations.each { |type, dest|
+ if dest.respond_to?(:close)
+ dest.close
+ end
+ }
+ @destinations.clear
+ # We need to make sure we always end up with some kind of destination
+ begin
+ types.each { |type|
+ Log.newdestination(type)
+ }
+ rescue => detail
+ if @destinations.empty?
+ Log.newdestination(:syslog)
+ Puppet.err detail.to_s
+ end
+ end
+ end
+
+ # Is the passed level a valid log level?
+ def self.validlevel?(level)
+ @levels.include?(level)
+ end
+
+ attr_accessor :level, :message, :time, :tags, :remote
+ attr_reader :source
+
+ def initialize(args)
+ unless args.include?(:level) && args.include?(:message)
+ raise Puppet::DevError, "Puppet::Util::Log called incorrectly"
+ end
+
+ if args[:level].class == String
+ @level = args[:level].intern
+ elsif args[:level].class == Symbol
+ @level = args[:level]
+ else
+ raise Puppet::DevError,
+ "Level is not a string or symbol: #{args[:level].class}"
+ end
+
+ # Just return unless we're actually at a level we should send
+ #return unless self.class.sendlevel?(@level)
+
+ @message = args[:message].to_s
+ @time = Time.now
+ # this should include the host name, and probly lots of other
+ # stuff, at some point
+ unless self.class.validlevel?(level)
+ raise Puppet::DevError, "Invalid message level #{level}"
+ end
+
+ if args.include?(:tags)
+ @tags = args[:tags]
+ end
+
+ if args.include?(:source)
+ self.source = args[:source]
+ else
+ @source = "Puppet"
+ end
+
+ Log.newmessage(self)
+ end
+
+ # Was the source of this log an object?
+ def objectsource?
+ if defined? @objectsource and @objectsource
+ @objectsource
+ else
+ false
+ end
+ end
+
+ # If they pass a source in to us, we make sure it is a string, and
+ # we retrieve any tags we can.
+ def source=(source)
+ # We can't store the actual source, we just store the path.
+ # We can't just check for whether it responds to :path, because
+ # plenty of providers respond to that in their normal function.
+ if source.is_a?(Puppet::Element) and source.respond_to?(:path)
+ @objectsource = true
+ @source = source.path
+ else
+ @objectsource = false
+ @source = source.to_s
+ end
+ unless defined? @tags and @tags
+ if source.respond_to?(:tags)
+ @tags = source.tags
+ end
+ end
+ end
+
+ def tagged?(tag)
+ @tags.detect { |t| t.to_s == tag.to_s }
+ end
+
+ def to_report
+ "%s %s (%s): %s" % [self.time, self.source, self.level, self.to_s]
+ end
+
+ def to_s
+ return @message
+ end
+end
+
+# $Id$
diff --git a/lib/puppet/util/logging.rb b/lib/puppet/util/logging.rb
index 1245e24de..298df93ba 100644
--- a/lib/puppet/util/logging.rb
+++ b/lib/puppet/util/logging.rb
@@ -1,14 +1,14 @@
# A module to make logging a bit easier.
-require 'puppet/log'
+require 'puppet/util/log'
module Puppet::Util::Logging
# Create a method for each log level.
- Puppet::Log.eachlevel do |level|
+ Puppet::Util::Log.eachlevel do |level|
define_method(level) do |args|
if args.is_a?(Array)
args = args.join(" ")
end
- Puppet::Log.create(
+ Puppet::Util::Log.create(
:level => level,
:source => self,
:message => args
diff --git a/lib/puppet/util/metric.rb b/lib/puppet/util/metric.rb
new file mode 100644
index 000000000..4c62df315
--- /dev/null
+++ b/lib/puppet/util/metric.rb
@@ -0,0 +1,158 @@
+# included so we can test object types
+require 'puppet'
+
+# A class for handling metrics. This is currently ridiculously hackish.
+class Puppet::Util::Metric
+ Puppet.config.setdefaults("metrics",
+ :rrddir => {:default => "$vardir/rrd",
+ :owner => "$user",
+ :group => "$group",
+ :desc => "The directory where RRD database files are stored.
+ Directories for each reporting host will be created under
+ this directory."
+ },
+ :rrdgraph => [false, "Whether RRD information should be graphed."],
+ :rrdinterval => ["$runinterval", "How often RRD should expect data.
+ This should match how often the hosts report back to the server."]
+ )
+
+ # Load the library as a feature, so we can test its presence.
+ Puppet.features.add :rrd, :libs => 'RRD'
+
+ attr_accessor :type, :name, :value, :label
+
+ attr_writer :basedir
+
+ def basedir
+ if defined? @basedir
+ @basedir
+ else
+ Puppet[:rrddir]
+ end
+ end
+
+ def create(start = nil)
+ Puppet.config.use(:metrics)
+
+ start ||= Time.now.to_i - 5
+
+ path = self.path
+ args = [
+ path,
+ "--start", start,
+ "--step", Puppet[:rrdinterval]
+ ]
+
+ values.each { |value|
+ # the 7200 is the heartbeat -- this means that any data that isn't
+ # more frequently than every two hours gets thrown away
+ args.push "DS:%s:GAUGE:7200:U:U" % [value[0]]
+ }
+ args.push "RRA:AVERAGE:0.5:1:300"
+
+ begin
+ RRD.create(*args)
+ rescue => detail
+ raise "Could not create RRD file %s: %s" % [path,detail]
+ end
+ end
+
+ def dump
+ puts RRD.info(self.path)
+ end
+
+ def graph(range = nil)
+ unless Puppet.features.rrd?
+ Puppet.warning "RRD library is missing; cannot graph metrics"
+ return
+ end
+
+ unit = 60 * 60 * 24
+ colorstack = %w{#ff0000 #00ff00 #0000ff #099000 #000990 #f00990 #0f0f0f}
+
+ {:daily => unit, :weekly => unit * 7, :monthly => unit * 30, :yearly => unit * 365}.each do |name, time|
+ file = self.path.sub(/\.rrd$/, "-%s.png" % name)
+ args = [file]
+
+ args.push("--title",self.label)
+ args.push("--imgformat","PNG")
+ args.push("--interlace")
+ i = 0
+ defs = []
+ lines = []
+ #p @values.collect { |s,l| s }
+ values.zip(colorstack).each { |value,color|
+ next if value.nil?
+ # this actually uses the data label
+ defs.push("DEF:%s=%s:%s:AVERAGE" % [value[0],self.path,value[0]])
+ lines.push("LINE2:%s%s:%s" % [value[0],color,value[1]])
+ }
+ args << defs
+ args << lines
+ args.flatten!
+ if range
+ args.push("--start",range[0],"--end",range[1])
+ else
+ args.push("--start", Time.now.to_i - time, "--end", Time.now.to_i)
+ end
+
+ begin
+ RRD.graph(*args)
+ rescue => detail
+ Puppet.err "Failed to graph %s: %s" % [self.name,detail]
+ end
+ end
+ end
+
+ def initialize(name,label = nil)
+ @name = name.to_s
+
+ if label
+ @label = label
+ else
+ @label = name.to_s.capitalize.gsub("_", " ")
+ end
+
+ @values = []
+ end
+
+ def path
+ return File.join(self.basedir, @name + ".rrd")
+ end
+
+ def newvalue(name,value,label = nil)
+ unless label
+ label = name.to_s.capitalize.gsub("_", " ")
+ end
+ @values.push [name,label,value]
+ end
+
+ def store(time)
+ unless Puppet.features.rrd?
+ Puppet.warning "RRD library is missing; cannot store metrics"
+ return
+ end
+ unless FileTest.exists?(self.path)
+ self.create(time - 5)
+ end
+
+ # XXX this is not terribly error-resistant
+ args = [time]
+ values.each { |value|
+ args.push value[2]
+ }
+ arg = args.join(":")
+ begin
+ RRD.update(self.path,arg)
+ #system("rrdtool updatev %s '%s'" % [self.path, arg])
+ rescue => detail
+ raise Puppet::Error, "Failed to update %s: %s" % [self.name,detail]
+ end
+ end
+
+ def values
+ @values.sort { |a, b| a[1] <=> b[1] }
+ end
+end
+
+# $Id$
diff --git a/lib/puppet/util/storage.rb b/lib/puppet/util/storage.rb
new file mode 100644
index 000000000..d76c67433
--- /dev/null
+++ b/lib/puppet/util/storage.rb
@@ -0,0 +1,103 @@
+require 'yaml'
+require 'sync'
+
+# a class for storing state
+class Puppet::Util::Storage
+ include Singleton
+ include Puppet::Util
+
+ def initialize
+ self.class.load
+ end
+
+ # Return a hash that will be stored to disk. It's worth noting
+ # here that we use the object's full path, not just the name/type
+ # combination. At the least, this is useful for those non-isomorphic
+ # types like exec, but it also means that if an object changes locations
+ # in the configuration it will lose its cache.
+ def self.cache(object)
+ if object.is_a? Puppet::Type
+ # We used to store things by path, now we store them by ref.
+ # In oscar(0.20.0) this changed to using the ref.
+ if @@state.include?(object.path)
+ @@state[object.ref] = @@state[object.path]
+ @@state.delete(object.path)
+ end
+ name = object.ref
+ elsif object.is_a?(Symbol)
+ name = object
+ else
+ raise ArgumentError, "You can only cache information for Types and symbols"
+ end
+
+ return @@state[name] ||= {}
+ end
+
+ def self.clear
+ @@state.clear
+ Storage.init
+ end
+
+ def self.init
+ @@state = {}
+ @@splitchar = "\t"
+ end
+
+ self.init
+
+ def self.load
+ Puppet.config.use(:puppet)
+
+ unless File.exists?(Puppet[:statefile])
+ unless defined? @@state and ! @@state.nil?
+ self.init
+ end
+ return
+ end
+ Puppet::Util.benchmark(:debug, "Loaded state") do
+ Puppet::Util.readlock(Puppet[:statefile]) do |file|
+ begin
+ @@state = YAML.load(file)
+ rescue => detail
+ Puppet.err "Checksumfile %s is corrupt (%s); replacing" %
+ [Puppet[:statefile], detail]
+ begin
+ File.rename(Puppet[:statefile],
+ Puppet[:statefile] + ".bad")
+ rescue
+ raise Puppet::Error,
+ "Could not rename corrupt %s; remove manually" %
+ Puppet[:statefile]
+ end
+ end
+ end
+ end
+
+ unless @@state.is_a?(Hash)
+ Puppet.err "State got corrupted"
+ self.init
+ end
+
+ #Puppet.debug "Loaded state is %s" % @@state.inspect
+ end
+
+ def self.stateinspect
+ @@state.inspect
+ end
+
+ def self.store
+ Puppet.debug "Storing state"
+
+ unless FileTest.exist?(Puppet[:statefile])
+ Puppet.info "Creating state file %s" % Puppet[:statefile]
+ end
+
+ Puppet::Util.benchmark(:debug, "Stored state") do
+ Puppet::Util.writelock(Puppet[:statefile], 0660) do |file|
+ file.print YAML.dump(@@state)
+ end
+ end
+ end
+end
+
+# $Id$
diff --git a/lib/puppet/util/suidmanager.rb b/lib/puppet/util/suidmanager.rb
new file mode 100644
index 000000000..7a0c3ae2c
--- /dev/null
+++ b/lib/puppet/util/suidmanager.rb
@@ -0,0 +1,86 @@
+require 'facter'
+require 'puppet/util/warnings'
+
+module Puppet::Util::SUIDManager
+ include Puppet::Util::Warnings
+
+ platform = Facter["kernel"].value
+ [:uid=, :gid=, :uid, :gid].each do |method|
+ define_method(method) do |*args|
+ # NOTE: 'method' is closed here.
+ newmethod = method
+
+ if platform == "Darwin" and (method == :uid= or method == :gid=)
+ Puppet::Util::Warnings.warnonce "Cannot change real UID on Darwin"
+ newmethod = ("e" + method.to_s).intern
+ end
+
+ return Process.send(newmethod, *args)
+ end
+ module_function method
+ end
+
+ [:euid=, :euid, :egid=, :egid].each do |method|
+ define_method(method) do |*args|
+ Process.send(method, *args)
+ end
+ module_function method
+ end
+
+ def asuser(new_euid=nil, new_egid=nil)
+ # Unless we're root, don't do a damn thing.
+ unless Process.uid == 0
+ return yield
+ end
+ old_egid = old_euid = nil
+ if new_egid
+ old_egid = self.egid
+ self.egid = convert_xid(:gid, new_egid)
+ end
+ if new_euid
+ old_euid = self.euid
+ self.euid = convert_xid(:uid, new_euid)
+ end
+
+ return yield
+ ensure
+ self.euid = old_euid if old_euid
+ self.egid = old_egid if old_egid
+ end
+
+ # Make sure the passed argument is a number.
+ def convert_xid(type, id)
+ map = {:gid => :group, :uid => :user}
+ raise ArgumentError, "Invalid id type %s" % type unless map.include?(type)
+ ret = Puppet::Util.send(type, id)
+ if ret == nil
+ raise Puppet::Error, "Invalid %s: %s" % [map[type], id]
+ end
+ return ret
+ end
+
+ module_function :asuser, :convert_xid
+
+ def run_and_capture(command, new_uid=nil, new_gid=nil)
+ output = nil
+
+ output = Puppet::Util.execute(command, false, new_uid, new_gid)
+
+ [output, $?.dup]
+ end
+
+ module_function :run_and_capture
+
+ def system(command, new_uid=nil, new_gid=nil)
+ status = nil
+ asuser(new_uid, new_gid) do
+ Kernel.system(command)
+ status = $?.dup
+ end
+ status
+ end
+
+ module_function :system
+end
+
+# $Id$