diff options
author | Luke Kanies <luke@madstop.com> | 2008-08-18 11:47:40 -0500 |
---|---|---|
committer | Luke Kanies <luke@madstop.com> | 2008-08-18 11:47:40 -0500 |
commit | e3971b9751141cd448a8197da024be43581f6dcd (patch) | |
tree | 3ae780db3d9dae0a4df10ec24f928bf3a844e749 | |
parent | 025edc5c3737f476119df4bab73ebdc68be19430 (diff) | |
parent | 2ec4e298c3274abc8eaad4230bca8d39a48d2e35 (diff) | |
download | puppet-e3971b9751141cd448a8197da024be43581f6dcd.tar.gz puppet-e3971b9751141cd448a8197da024be43581f6dcd.tar.xz puppet-e3971b9751141cd448a8197da024be43581f6dcd.zip |
Merge branch '0.24.x'
Conflicts:
CHANGELOG
test/util/posixtest.rb
40 files changed, 892 insertions, 164 deletions
@@ -7,6 +7,51 @@ whether we should even use a CRL. This way we aren't trying to set file paths to 'false' to disable the CRL. +0.24.x + Fixed #1502 - Fixed poor stored configuration performance + + Fixed #1510 - Storeconfiguration fixed for Rails 2.1 + + Add the -P/--ping option to puppetrun, fixes #1501 + + Fixed #1394 - Added stored configuration clearing script to /ext + + Fixed #1442 - replaced use of Facter for report titling with certname + + Fixed $1456 - add proxy configuration capability to yum repo + + Fixed #1457 - removed confine warning + + A working script to create an OS X pkg out of the Puppet repository + + Fixed #1441 - Updated console colours + + Expose all puppet variables as instance member variables of the template wrapper. + This helps resolve redmine #1427, by providing a safe mechanism to access variables. + + * Implement Puppet::Parser::Scope#to_hash, which returns a hash containing all the + variable bindings in the current and, optionally, parent scope. + * Use that to set instance member variables into Puppet::Parser::Templatewrapper + * Report the time taken for variable binding at debug level, to help identify any + performance regression that is encountered in the real world. + * Rename the @scope and @file members of the template wrapper, to avoid clashing + with a scope variable exposed within puppet. + + Ensure that we consistently use either string #{} interpolation or String.% + interpolation, not both, to avoid issues where a #{} interpolated value + contains a % character. + + Feature #1476: Allow specification of --bindir --sbindir --sitelibdir --mandir --destdir + in installation + + Added feature #1241 : Improve performance of group lookups + + Fixed bug #1448: Puppet CA incorrectly writes out all certs to inventory .txt on each + certificate signing + + Fixing puppetlast to make it work with 0.24.5 / 0.25. Made puppetlast work on 0.24.5 + by using the YAML indirector + 0.24.5 You can now select the encoding format when transferring the catalog, with 'yaml' still being the default but 'marshal' being an option. @@ -22,6 +67,8 @@ The fix for #1431 is actually just removing the tests that exposed this change; the change happened when I refactored how confines work. + Removed faulty interface type + Updated /spec/unit/rails.rb test Fix #1426 - services on redhat are restarted again and status is diff --git a/bin/puppetrun b/bin/puppetrun index f1e30245b..f33c7f8a1 100755 --- a/bin/puppetrun +++ b/bin/puppetrun @@ -9,7 +9,7 @@ # # puppetrun [-a|--all] [-c|--class <class>] [-d|--debug] [-f|--foreground] # [-h|--help] [--host <host>] [--no-fqdn] [--ignoreschedules] -# [-t|--tag <tag>] [--test] +# [-t|--tag <tag>] [--test] [-p|--ping] # # = Description # @@ -108,6 +108,10 @@ # Print the hosts you would connect to but do not actually connect. This # option requires LDAP support at this point. # +# ping:: +# +# Do a ICMP echo against the target host. Skip hosts that don't respond to ping. +# # = Example # # sudo puppetrun -p 10 --host host1 --host host2 -t remotefile -t webserver @@ -154,6 +158,7 @@ flags = [ [ "--help", "-h", GetoptLong::NO_ARGUMENT ], [ "--host", GetoptLong::REQUIRED_ARGUMENT ], [ "--parallel", "-p", GetoptLong::REQUIRED_ARGUMENT ], + [ "--ping", "-P", GetoptLong::NO_ARGUMENT ], [ "--no-fqdn", "-n", GetoptLong::NO_ARGUMENT ], [ "--test", GetoptLong::NO_ARGUMENT ], [ "--version", "-V", GetoptLong::NO_ARGUMENT ] @@ -168,6 +173,7 @@ options = { :ignoreschedules => false, :foreground => false, :parallel => 1, + :ping => false, :debug => false, :test => false, :all => false, @@ -215,6 +221,8 @@ begin $stderr.puts "Could not convert %s to an integer" % arg.inspect exit(23) end + when "--ping" + options[:ping] = true when "--foreground" options[:foreground] = true when "--debug" @@ -294,12 +302,12 @@ while go if children.length < options[:parallel] and ! todo.empty? host = todo.shift pid = fork do - # First make sure the client is up - out = %x{ping -c 1 #{host}} - - unless $? == 0 - $stderr.print "Could not contact %s\n" % host - next + if options[:ping] + out = %x{ping -c 1 #{host}} + unless $? == 0 + $stderr.print "Could not contact %s\n" % host + next + end end client = Puppet::Network::Client.runner.new( :Server => host, diff --git a/conf/osx/PackageInfo.plist b/conf/osx/PackageInfo.plist new file mode 100644 index 000000000..9706a80a6 --- /dev/null +++ b/conf/osx/PackageInfo.plist @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleIdentifier</key> + <string>com.reductivelabs.puppet</string> + <key>CFBundleShortVersionString</key> + <string>{SHORTVERSION}</string> + <key>IFMajorVersion</key> + <integer>{MAJORVERSION}</integer> + <key>IFMinorVersion</key> + <integer>{MINORVERSION}</integer> + <key>IFPkgFlagAllowBackRev</key> + <false/> + <key>IFPkgFlagAuthorizationAction</key> + <string>RootAuthorization</string> + <key>IFPkgFlagDefaultLocation</key> + <string>/</string> + <key>IFPkgFlagFollowLinks</key> + <true/> + <key>IFPkgFlagInstallFat</key> + <false/> + <key>IFPkgFlagIsRequired</key> + <false/> + <key>IFPkgFlagOverwritePermissions</key> + <false/> + <key>IFPkgFlagRelocatable</key> + <false/> + <key>IFPkgFlagRestartAction</key> + <string>None</string> + <key>IFPkgFlagRootVolumeOnly</key> + <true/> + <key>IFPkgFlagUpdateInstalledLanguages</key> + <false/> +</dict> +</plist> diff --git a/conf/osx/createpackage.sh b/conf/osx/createpackage.sh new file mode 100755 index 000000000..3ac4d09de --- /dev/null +++ b/conf/osx/createpackage.sh @@ -0,0 +1,167 @@ +#!/bin/bash +# +# Script to build an "old style" not flat pkg out of the puppet repository. +# +# Author: Nigel Kersten (nigelk@google.com) +# +# Last Updated: 2008-07-31 +# +# Copyright 2008 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License + + +INSTALLRB="install.rb" +BINDIR="/usr/bin" +SITELIBDIR="/usr/lib/ruby/site_ruby/1.8" +PACKAGEMAKER="/Developer/usr/bin/packagemaker" +PROTO_PLIST="PackageInfo.plist" +PREFLIGHT="preflight" + + +function find_installer() { + # we walk up three directories to make this executable from the root, + # root/conf or root/conf/osx + if [ -f "./${INSTALLRB}" ]; then + installer="$(pwd)/${INSTALLRB}" + elif [ -f "../${INSTALLRB}" ]; then + installer="$(pwd)/../${INSTALLRB}" + elif [ -f "../../${INSTALLRB}" ]; then + installer="$(pwd)/../${INSTALLRB}" + else + installer="" + fi +} + +function find_puppet_root() { + puppet_root=$(dirname "${installer}") +} + +function install_puppet() { + echo "Installing Puppet to ${pkgroot}" + "${installer}" --destdir="${pkgroot}" --bindir="${BINDIR}" --sitelibdir="${SITELIBDIR}" &> /dev/null + chown -R root:admin "${pkgroot}" +} + +function get_puppet_version() { + puppet_version=$(RUBYLIB="${pkgroot}/${SITELIBDIR}:${RUBYLIB}" ruby -e "require 'puppet'; puts Puppet.version") +} + +function prepare_package() { + # As we can't specify to follow symlinks from the command line, we have + # to go through the hassle of creating an Info.plist file for packagemaker + # to look at for package creation and substitue the version strings out. + # Major/Minor versions can only be integers, so we have "0" and "245" for + # puppet version 0.24.5 + # Note too that for 10.5 compatibility this Info.plist *must* be set to + # follow symlinks. + VER1=$(echo ${puppet_version} | awk -F "." '{print $1}') + VER2=$(echo ${puppet_version} | awk -F "." '{print $2}') + VER3=$(echo ${puppet_version} | awk -F "." '{print $3}') + major_version="${VER1}" + minor_version="${VER2}${VER3}" + cp "${puppet_root}/conf/osx/${PROTO_PLIST}" "${pkgtemp}" + sed -i '' "s/{SHORTVERSION}/${puppet_version}/g" "${pkgtemp}/${PROTO_PLIST}" + sed -i '' "s/{MAJORVERSION}/${major_version}/g" "${pkgtemp}/${PROTO_PLIST}" + sed -i '' "s/{MINORVERSION}/${minor_version}/g" "${pkgtemp}/${PROTO_PLIST}" + + # We need to create a preflight script to remove traces of previous + # puppet installs due to limitations in Apple's pkg format. + mkdir "${pkgtemp}/scripts" + cp "${puppet_root}/conf/osx/${PREFLIGHT}" "${pkgtemp}/scripts" + + # substitute in the sitelibdir specified above on the assumption that this + # is where any previous puppet install exists that should be cleaned out. + sed -i '' "s|{SITELIBDIR}|${SITELIBDIR}|g" "${pkgtemp}/scripts/${PREFLIGHT}" + chmod 0755 "${pkgtemp}/scripts/${PREFLIGHT}" +} + +function create_package() { + rm -fr "$(pwd)/puppet-${puppet_version}.pkg" + echo "Building package" + echo "Note that packagemaker is reknowned for spurious errors. Don't panic." + "${PACKAGEMAKER}" --root "${pkgroot}" \ + --info "${pkgtemp}/${PROTO_PLIST}" \ + --scripts ${pkgtemp}/scripts \ + --out "$(pwd)/puppet-${puppet_version}.pkg" + if [ $? -ne 0 ]; then + echo "There was a problem building the package." + cleanup_and_exit 1 + exit 1 + else + echo "The package has been built at:" + echo "$(pwd)/puppet-${puppet_version}.pkg" + fi +} + +function cleanup_and_exit() { + if [ -d "${pkgroot}" ]; then + rm -fr "${pkgroot}" + fi + if [ -d "${pkgtemp}" ]; then + rm -fr "${pkgtemp}" + fi + exit $1 +} + +# Program entry point +function main() { + + if [ $(whoami) != "root" ]; then + echo "This script needs to be run as root via su or sudo." + cleanup_and_exit 1 + fi + + find_installer + + if [ ! "${installer}" ]; then + echo "Unable to find ${INSTALLRB}" + cleanup_and_exit 1 + fi + + find_puppet_root + + if [ ! "${puppet_root}" ]; then + echo "Unable to find puppet repository root." + cleanup_and_exit 1 + fi + + pkgroot=$(mktemp -d -t puppetpkg) + + if [ ! "${pkgroot}" ]; then + echo "Unable to create temporary package root." + cleanup_and_exit 1 + fi + + pkgtemp=$(mktemp -d -t puppettmp) + + if [ ! "${pkgtemp}" ]; then + echo "Unable to create temporary package root." + cleanup_and_exit 1 + fi + + install_puppet + get_puppet_version + + if [ ! "${puppet_version}" ]; then + echo "Unable to retrieve puppet version" + cleanup_and_exit 1 + fi + + prepare_package + create_package + + cleanup_and_exit 0 +} + +main "$@" diff --git a/conf/osx/preflight b/conf/osx/preflight new file mode 100755 index 000000000..57ebcb67e --- /dev/null +++ b/conf/osx/preflight @@ -0,0 +1,11 @@ +#!/bin/bash +# +# Make sure that old puppet cruft is removed +# This also allows us to downgrade puppet as +# it's more likely that installing old versions +# over new will cause issues. +# +# ${3} is the destination volume so that this works correctly +# when being installed to volumes other than the current OS. + +rm -Rf "${3}{SITELIBDIR}/puppet*" diff --git a/conf/redhat/puppet.spec b/conf/redhat/puppet.spec index 65cb4939c..92a42ce7b 100644 --- a/conf/redhat/puppet.spec +++ b/conf/redhat/puppet.spec @@ -7,7 +7,7 @@ Summary: A network tool for managing many disparate systems Name: puppet -Version: 0.24.4 +Version: 0.24.5 Release: 1%{?dist} License: GPLv2+ Group: System Environment/Base @@ -73,6 +73,7 @@ mv %{buildroot}%{_sbindir}/puppet %{buildroot}%{_bindir}/puppet mv %{buildroot}%{_sbindir}/ralsh %{buildroot}%{_bindir}/ralsh mv %{buildroot}%{_sbindir}/filebucket %{buildroot}%{_bindir}/filebucket mv %{buildroot}%{_sbindir}/puppetrun %{buildroot}%{_bindir}/puppetrun +mv %{buildroot}%{_sbindir}/puppetdoc %{buildroot}%{_bindir}/puppetdoc install -Dp -m0644 %{pbuild}/lib/puppet.rb %{buildroot}%{ruby_sitelibdir}/puppet.rb cp -a %{pbuild}/lib/puppet %{buildroot}%{ruby_sitelibdir} find %{buildroot}%{ruby_sitelibdir} -type f -perm +ugo+x -print0 | xargs -0 -r chmod a-x @@ -94,6 +95,8 @@ touch %{buildroot}%{_sysconfdir}/puppet/puppetd.conf %{_bindir}/puppet %{_bindir}/ralsh %{_bindir}/filebucket +%{_bindir}/puppetdoc +%exclude %{_mandir}/man8/pi.8.gz %{_sbindir}/puppetd %{ruby_sitelibdir}/* %{_initrddir}/puppet @@ -102,13 +105,17 @@ touch %{buildroot}%{_sysconfdir}/puppet/puppetd.conf %config(noreplace) %{_sysconfdir}/puppet/puppet.conf %ghost %config(noreplace,missingok) %{_sysconfdir}/puppet/puppetd.conf %doc CHANGELOG COPYING LICENSE README examples -%exclude %{_sbindir}/puppetdoc %config(noreplace) %{_sysconfdir}/logrotate.d/puppet # These need to be owned by puppet so the server can # write to them %attr(-, puppet, puppet) %{_localstatedir}/run/puppet %attr(-, puppet, puppet) %{_localstatedir}/log/puppet %attr(-, puppet, puppet) %{_localstatedir}/lib/puppet +%doc %{_mandir}/man8/puppet.8.gz +%doc %{_mandir}/man8/puppet.conf.8.gz +%doc %{_mandir}/man8/puppetd.8.gz +%doc %{_mandir}/man8/ralsh.8.gz +%doc %{_mandir}/man8/puppetdoc.8.gz %files server %defattr(-, root, root, 0755) @@ -157,6 +164,24 @@ fi rm -rf %{buildroot} %changelog +* Mon Jul 28 2008 David Lutterkort <dlutter@redhat.com> - 0.24.5-1 +- Add /usr/bin/puppetdoc + +* Thu Jul 24 2008 Brenton Leanhardt <bleanhar@redhat.com> +- New version +- man pages now ship with tarball +- examples/code moved to root examples dir in upstream tarball + +* Tue Mar 25 2008 David Lutterkort <dlutter@redhat.com> - 0.24.4-1 +- Add man pages (from separate tarball, upstream will fix to + include in main tarball) + +* Mon Mar 24 2008 David Lutterkort <dlutter@redhat.com> - 0.24.3-1 +- New version + +* Wed Mar 5 2008 David Lutterkort <dlutter@redhat.com> - 0.24.2-1 +- New version + * Sat Dec 22 2007 David Lutterkort <dlutter@redhat.com> - 0.24.1-1 - New version diff --git a/ext/puppetlast b/ext/puppetlast index e8c2ea1a7..d9b698cfe 100755 --- a/ext/puppetlast +++ b/ext/puppetlast @@ -1,40 +1,15 @@ #!/usr/bin/env ruby +# Puppetlast, a script to output the last check-in time of nodes. Also outputs the cached configuration state, if expired or not. # -# Script to print out when puppet ran successfully last -# AJ Christensen <aj@junglist.gen.nz> +# AJ "Fujin" Christensen <aj@junglist.gen.nz> # - require 'puppet' -require 'puppet/defaults' -require 'yaml' Puppet[:config] = "/etc/puppet/puppet.conf" Puppet.parse_config +Puppet[:name] = "puppetmasterd" +Puppet::Node::Facts.terminus_class = :yaml -print "puppetlast\n" - -nodes = {} - -yfdir = Puppet.settings.value(:vardir) + "/yaml/facts" - -if yfdir - begin - Dir.chdir(yfdir) do - Dir.glob("*.yaml").each do |yaml| - data = YAML.load_file(yaml) - t = Time.now - age = t - data.version - nodes[data.name] = age.to_i - end - end - - nodes.sort.each do |node,age| - minutes = age / 60 + 0.5 - print minutes.floor.to_s + ' minutes ago: ' + node + "\n" - end - - rescue - print 'error: ' + $! + "\n" - end - +Puppet::Node::Facts.search("*").sort.each do |node| + puts "#{node.name} #{node.expired? ? 'cached expired, ' : ''}checked in #{((Time.now - node.values[:_timestamp]) / 60).floor} minutes ago" end diff --git a/ext/puppetstoredconfigclean.rb b/ext/puppetstoredconfigclean.rb new file mode 100644 index 000000000..f286df2df --- /dev/null +++ b/ext/puppetstoredconfigclean.rb @@ -0,0 +1,87 @@ +#!/usr/bin/env ruby + +# Script to clean up stored configs for (a) given host(s) +# +# Credits: +# Script was taken from http://reductivelabs.com/trac/puppet/attachment/wiki/UsingStoredConfiguration/kill_node_in_storedconfigs_db.rb +# which haven been initially posted by James Turnbull +# duritong adapted and improved the script a bit. + +require 'getoptlong' +config = '/etc/puppet/puppet.conf' + +def printusage(error_code) + puts "Usage: #{$0} [ list of hostnames as stored in hosts table ]" + puts "\n Options:" + puts "--config <puppet config file>" + exit(error_code) +end + +opts = GetoptLong.new( + [ "--config", "-c", GetoptLong::REQUIRED_ARGUMENT ], + [ "--help", "-h", GetoptLong::NO_ARGUMENT ], + [ "--usage", "-u", GetoptLong::NO_ARGUMENT ], + [ "--version", "-v", GetoptLong::NO_ARGUMENT ] +) + +begin + opts.each do |opt, arg| + case opt + when "--config" + config = arg + + when "--help" + printusage(0) + + when "--usage" + printusage(0) + + when "--version" + puts "%s" % Puppet.version + exit + end + end +rescue GetoptLong::InvalidOption => detail + $stderr.puts "Try '#{$0} --help'" + exit(1) +end + +printusage(1) unless ARGV.size > 0 + +require 'puppet/rails' +Puppet[:config] = config +Puppet.parse_config +pm_conf = Puppet.settings.instance_variable_get(:@values)[:puppetmasterd] + +adapter = pm_conf[:dbadapter] +args = {:adapter => adapter, :log_level => pm_conf[:rails_loglevel]} + +case adapter + when "sqlite3": + args[:dbfile] = pm_conf[:dblocation] + when "mysql", "postgresql": + args[:host] = pm_conf[:dbserver] unless pm_conf[:dbserver].to_s.empty? + args[:username] = pm_conf[:dbuser] unless pm_conf[:dbuser].to_s.empty? + args[:password] = pm_conf[:dbpassword] unless pm_conf[:dbpassword].to_s.empty? + args[:database] = pm_conf[:dbname] unless pm_conf[:dbname].to_s.empty? + socket = pm_conf[:dbsocket] + args[:socket] = socket unless socket.to_s.empty? + else + raise ArgumentError, "Invalid db adapter %s" % adapter +end + +args[:database] = "puppet" unless not args[:database].to_s.empty? + +ActiveRecord::Base.establish_connection(args) + +ARGV.each { |hostname| + if @host = Puppet::Rails::Host.find_by_name(hostname.strip) + print "Killing #{hostname}..." + $stdout.flush + @host.destroy + puts "done." + else + puts "Can't find host #{hostname}." + end +} +exit 0 diff --git a/install.rb b/install.rb index 27b09397e..a2cbdb429 100755 --- a/install.rb +++ b/install.rb @@ -175,6 +175,21 @@ def prepare_installation opts.on('--[no-]tests', 'Prevents the execution of unit tests.', 'Default on.') do |ontest| InstallOptions.tests = ontest end + opts.on('--destdir[=OPTIONAL]', 'Installation prefix for all targets', 'Default essentially /') do |destdir| + InstallOptions.destdir = destdir + end + opts.on('--bindir[=OPTIONAL]', 'Installation directory for binaries', 'overrides Config::CONFIG["bindir"]') do |bindir| + InstallOptions.bindir = bindir + end + opts.on('--sbindir[=OPTIONAL]', 'Installation directory for system binaries', 'overrides Config::CONFIG["sbindir"]') do |sbindir| + InstallOptions.sbindir = sbindir + end + opts.on('--sitelibdir[=OPTIONAL]', 'Installation directory for libraries', 'overrides Config::CONFIG["sitelibdir"]') do |sitelibdir| + InstallOptions.sitelibdir = sitelibdir + end + opts.on('--mandir[=OPTIONAL]', 'Installation directory for man pages', 'overrides Config::CONFIG["mandir"]') do |mandir| + InstallOptions.mandir = mandir + end opts.on('--quick', 'Performs a quick installation. Only the', 'installation is done.') do |quick| InstallOptions.rdoc = false InstallOptions.ri = false @@ -200,16 +215,6 @@ def prepare_installation version = [Config::CONFIG["MAJOR"], Config::CONFIG["MINOR"]].join(".") libdir = File.join(Config::CONFIG["libdir"], "ruby", version) - sitelibdir = Config::CONFIG["sitelibdir"] - if sitelibdir.nil? - sitelibdir = $:.find { |x| x =~ /site_ruby/ } - if sitelibdir.nil? - sitelibdir = File.join(libdir, "site_ruby") - elsif sitelibdir !~ Regexp.quote(version) - sitelibdir = File.join(sitelibdir, version) - end - end - # Mac OS X 10.5 declares bindir and sbindir as # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin # /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/sbin @@ -218,25 +223,65 @@ def prepare_installation Config::CONFIG['bindir'] = "/usr/bin" Config::CONFIG['sbindir'] = "/usr/sbin" end + + if not InstallOptions.bindir.nil? + bindir = InstallOptions.bindir + else + bindir = Config::CONFIG['bindir'] + end + + if not InstallOptions.sbindir.nil? + sbindir = InstallOptions.sbindir + else + sbindir = Config::CONFIG['sbindir'] + end + + if not InstallOptions.sitelibdir.nil? + sitelibdir = InstallOptions.sitelibdir + else + sitelibdir = Config::CONFIG["sitelibdir"] + if sitelibdir.nil? + sitelibdir = $:.find { |x| x =~ /site_ruby/ } + if sitelibdir.nil? + sitelibdir = File.join(libdir, "site_ruby") + elsif sitelibdir !~ Regexp.quote(version) + sitelibdir = File.join(sitelibdir, version) + end + end + end + + if not InstallOptions.mandir.nil? + mandir = InstallOptions.mandir + else + mandir = Config::CONFIG['mandir'] + end + # To be deprecated once people move over to using --destdir option if (destdir = ENV['DESTDIR']) - bindir = "#{destdir}#{Config::CONFIG['bindir']}" - sbindir = "#{destdir}#{Config::CONFIG['sbindir']}" - mandir = "#{destdir}#{Config::CONFIG['mandir']}" + bindir = "#{destdir}#{bindir}" + sbindir = "#{destdir}#{sbindir}" + mandir = "#{destdir}#{mandir}" + sitelibdir = "#{destdir}#{sitelibdir}" + + FileUtils.makedirs(bindir) + FileUtils.makedirs(sbindir) + FileUtils.makedirs(mandir) + FileUtils.makedirs(sitelibdir) + # This is the new way forward + elsif (destdir = InstallOptions.destdir) + bindir = "#{destdir}#{bindir}" + sbindir = "#{destdir}#{sbindir}" + mandir = "#{destdir}#{mandir}" sitelibdir = "#{destdir}#{sitelibdir}" - tmpdirs << bindir FileUtils.makedirs(bindir) FileUtils.makedirs(sbindir) FileUtils.makedirs(mandir) FileUtils.makedirs(sitelibdir) - else - bindir = Config::CONFIG['bindir'] - sbindir = Config::CONFIG['sbindir'] - mandir = Config::CONFIG['mandir'] - tmpdirs << Config::CONFIG['bindir'] end + tmpdirs << bindir + InstallOptions.tmp_dirs = tmpdirs.compact InstallOptions.site_dir = sitelibdir InstallOptions.bin_dir = bindir diff --git a/lib/puppet.rb b/lib/puppet.rb index c3095f02e..cc3c8e304 100644 --- a/lib/puppet.rb +++ b/lib/puppet.rb @@ -25,7 +25,7 @@ require 'puppet/util/suidmanager' # it's also a place to find top-level commands like 'debug' module Puppet - PUPPETVERSION = '0.24.4' + PUPPETVERSION = '0.24.5' def Puppet.version return PUPPETVERSION diff --git a/lib/puppet/indirector/facts/facter.rb b/lib/puppet/indirector/facts/facter.rb index 465d90c13..6ed89dac1 100644 --- a/lib/puppet/indirector/facts/facter.rb +++ b/lib/puppet/indirector/facts/facter.rb @@ -12,12 +12,13 @@ class Puppet::Node::Facts::Facter < Puppet::Indirector::Code Dir.entries(dir).find_all { |e| e =~ /\.rb$/ }.each do |file| fqfile = ::File.join(dir, file) begin - Puppet.info "Loading #{type} %s" % ::File.basename(file.sub(".rb",'')) + Puppet.info "Loading %s %s" % + [type, ::File.basename(file.sub(".rb",''))] Timeout::timeout(self.timeout) do load fqfile end rescue => detail - Puppet.warning "Could not load #{type} %s: %s" % [fqfile, detail] + Puppet.warning "Could not load %s %s: %s" % [type, fqfile, detail] end end end diff --git a/lib/puppet/indirector/yaml.rb b/lib/puppet/indirector/yaml.rb index 3573ba560..3f05ce618 100644 --- a/lib/puppet/indirector/yaml.rb +++ b/lib/puppet/indirector/yaml.rb @@ -34,11 +34,20 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus end end + # Get the yaml directory + def base + (Puppet[:name] == "puppetmasterd") ? Puppet[:yamldir] : Puppet[:clientyamldir] + end + # Return the path to a given node's file. def path(name) - base = (Puppet[:name] == "puppetmasterd") ? Puppet[:yamldir] : Puppet[:clientyamldir] File.join(base, self.class.indirection_name.to_s, name.to_s + ".yaml") end + + # Do a glob on the yaml directory, loading each file found + def search(request) + Dir.glob(File.join(base, self.class.indirection_name.to_s, request.key)).collect { |f| YAML.load_file(f) } + end private diff --git a/lib/puppet/metatype/metaparams.rb b/lib/puppet/metatype/metaparams.rb index bf64d3a93..9ba786ee2 100644 --- a/lib/puppet/metatype/metaparams.rb +++ b/lib/puppet/metatype/metaparams.rb @@ -255,7 +255,8 @@ class Puppet::Type @value.each do |value| unless @resource.catalog.resource(*value) description = self.class.direction == :in ? "dependency" : "dependent" - fail Puppet::Error, "Could not find #{description} %s[%s] for %s" % [value[0].to_s.capitalize, value[1], resource.ref] + fail Puppet::Error, "Could not find %s %s[%s] for %s" % + [description, value[0].to_s.capitalize, value[1], resource.ref] end end end diff --git a/lib/puppet/network/client/master.rb b/lib/puppet/network/client/master.rb index d401cd393..5ca898dab 100644 --- a/lib/puppet/network/client/master.rb +++ b/lib/puppet/network/client/master.rb @@ -337,7 +337,7 @@ class Puppet::Network::Client::Master < Puppet::Network::Client if Puppet[:debug] puts detail.backtrace end - Puppet.err "Could not retrieve #{args[:name]}s: %s" % detail + Puppet.err "Could not retrieve %ss: %s" % [args[:name], detail] end # Now clean up after ourselves @@ -388,12 +388,13 @@ class Puppet::Network::Client::Master < Puppet::Network::Client Dir.entries(dir).find_all { |e| e =~ /\.rb$/ }.each do |file| fqfile = ::File.join(dir, file) begin - Puppet.info "Loading #{type} %s" % ::File.basename(file.sub(".rb",'')) + Puppet.info "Loading %s %s" % + [type, ::File.basename(file.sub(".rb",''))] Timeout::timeout(self.timeout) do load fqfile end rescue => detail - Puppet.warning "Could not load #{type} %s: %s" % [fqfile, detail] + Puppet.warning "Could not load %s %s: %s" % [type, fqfile, detail] end end end diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb index 51026ea1b..2c5f66e5a 100644 --- a/lib/puppet/parser/lexer.rb +++ b/lib/puppet/parser/lexer.rb @@ -131,7 +131,7 @@ class Puppet::Parser::Lexer TOKENS.add_tokens "Whatever" => :DQTEXT, "Nomatter" => :SQTEXT, "alsonomatter" => :BOOLEAN - TOKENS.add_token :NAME, %r{[a-z][-\w]*} do |lexer, value| + TOKENS.add_token :NAME, %r{[a-z0-9][-\w]*} do |lexer, value| string_token = self # we're looking for keywords here if tmp = KEYWORDS.lookup(value) diff --git a/lib/puppet/parser/resource/param.rb b/lib/puppet/parser/resource/param.rb index 9dd3f26d2..c8dd78a26 100644 --- a/lib/puppet/parser/resource/param.rb +++ b/lib/puppet/parser/resource/param.rb @@ -66,6 +66,14 @@ class Puppet::Parser::Resource::Param def to_s "%s => %s" % [self.name, self.value] end + + def compare(v,db_value) + if (v.is_a?(Puppet::Parser::Resource::Reference)) + return v.to_s == db_value.to_s + else + return v == db_value + end + end def values_to_remove(db_values) values = munge_for_rails(value) @@ -73,7 +81,7 @@ class Puppet::Parser::Resource::Param db_values.collect do |db| db unless (db.line == line_number && values.find { |v| - v == db.value + compare(v,db.value) } ) end.compact end @@ -82,7 +90,7 @@ class Puppet::Parser::Resource::Param values = munge_for_rails(value) line_number = line_to_i() values.collect do |v| - v unless db_values.find { |db| (v == db.value && + v unless db_values.find { |db| (compare(v,db.value) && line_number == db.line) } end.compact end diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb index a6e43e7b3..32b127a6b 100644 --- a/lib/puppet/parser/scope.rb +++ b/lib/puppet/parser/scope.rb @@ -183,6 +183,25 @@ class Puppet::Parser::Scope end end + # Return a hash containing our variables and their values, optionally (and + # by default) including the values defined in our parent. Local values + # shadow parent values. + def to_hash(recursive = true) + if recursive and parent then + target = parent.to_hash(recursive) + end + target ||= Hash.new + @symtable.keys.each { |name| + value = @symtable[name] + if value == :undef then + target.delete(name) + else + target[name] = value + end + } + return target + end + def namespaces @namespaces.dup end diff --git a/lib/puppet/parser/templatewrapper.rb b/lib/puppet/parser/templatewrapper.rb index 4790cea30..3b74e62d4 100644 --- a/lib/puppet/parser/templatewrapper.rb +++ b/lib/puppet/parser/templatewrapper.rb @@ -5,50 +5,76 @@ class Puppet::Parser::TemplateWrapper include Puppet::Util Puppet::Util.logmethods(self) - def initialize(scope, file) - @scope = scope - @file = Puppet::Module::find_template(file, @scope.compiler.environment) + def initialize(scope, filename) + @__scope__ = scope + @__file__ = Puppet::Module::find_template(filename, scope.compiler.environment) - unless FileTest.exists?(@file) + unless FileTest.exists?(file) raise Puppet::ParseError, "Could not find template %s" % file end # We'll only ever not have a parser in testing, but, eh. - if @scope.parser - @scope.parser.watch_file(@file) + if scope.parser + scope.parser.watch_file(file) end end + def scope + @__scope__ + end + + def file + @__file__ + end + # Should return true if a variable is defined, false if it is not def has_variable?(name) - if @scope.lookupvar(name.to_s, false) != :undefined + if scope.lookupvar(name.to_s, false) != :undefined true else false end end - # Ruby treats variables like methods, so we can cheat here and - # trap missing vars like they were missing methods. + # Ruby treats variables like methods, so we used to expose variables + # within scope to the ERB code via method_missing. As per RedMine #1427, + # though, this means that conflicts between methods in our inheritance + # tree (Kernel#fork) and variable names (fork => "yes/no") could arise. + # + # Worse, /new/ conflicts could pop up when a new kernel or object method + # was added to Ruby, causing templates to suddenly fail mysteriously when + # Ruby was upgraded. + # + # To ensure that legacy templates using unqualified names work we retain + # the missing_method definition here until we declare the syntax finally + # dead. def method_missing(name, *args) # We have to tell lookupvar to return :undefined to us when # appropriate; otherwise it converts to "". - value = @scope.lookupvar(name.to_s, false) + value = scope.lookupvar(name.to_s, false) if value != :undefined return value else # Just throw an error immediately, instead of searching for # other missingmethod things or whatever. - raise Puppet::ParseError, - "Could not find value for '%s'" % name + raise Puppet::ParseError, "Could not find value for '%s'" % name end end def result + # Expose all the variables in our scope as instance variables of the + # current object, making it possible to access them without conflict + # to the regular methods. + benchmark(:debug, "Bound template variables for #{file}") do + scope.to_hash.each { |name, value| + instance_variable_set("@#{name}", value) + } + end + result = nil - benchmark(:debug, "Interpolated template #{@file}") do - template = ERB.new(File.read(@file), 0, "-") + benchmark(:debug, "Interpolated template #{file}") do + template = ERB.new(File.read(file), 0, "-") result = template.result(binding) end @@ -56,7 +82,7 @@ class Puppet::Parser::TemplateWrapper end def to_s - "template[%s]" % @file + "template[%s]" % file end end diff --git a/lib/puppet/provider/confine.rb b/lib/puppet/provider/confine.rb index 35b80fdcf..e15adcd0e 100644 --- a/lib/puppet/provider/confine.rb +++ b/lib/puppet/provider/confine.rb @@ -25,7 +25,7 @@ class Puppet::Provider::Confine begin require "puppet/provider/confine/%s" % name rescue LoadError => detail - unless detail.to_s.include?("no such file") + unless detail.to_s.include?("No such file") warn "Could not load confine test '%s': %s" % [name, detail] end # Could not find file diff --git a/lib/puppet/provider/package/dpkg.rb b/lib/puppet/provider/package/dpkg.rb index b67cd2b76..ae79f714c 100755 --- a/lib/puppet/provider/package/dpkg.rb +++ b/lib/puppet/provider/package/dpkg.rb @@ -121,7 +121,7 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package end if hash[:error] != "ok" - raise Puppet::PackageError.new( + raise Puppet::Error.new( "Package %s, version %s is in error state: %s" % [hash[:name], hash[:ensure], hash[:error]] ) diff --git a/lib/puppet/provider/package/ports.rb b/lib/puppet/provider/package/ports.rb index 99e26ef23..96ef3f042 100755 --- a/lib/puppet/provider/package/ports.rb +++ b/lib/puppet/provider/package/ports.rb @@ -33,7 +33,7 @@ Puppet::Type.type(:package).provide :ports, :parent => :freebsd, :source => :fre begin output = portversion(*cmd) rescue Puppet::ExecutionFailure - raise Puppet::PackageError.new(output) + raise Puppet::Error.new(output) end line = output.split("\n").pop @@ -47,7 +47,7 @@ Puppet::Type.type(:package).provide :ports, :parent => :freebsd, :source => :fre info = $3 unless pkgstuff =~ /^(\S+)-([^-\s]+)$/ - raise Puppet::PackageError, + raise Puppet::Error, "Could not match package info '%s'" % pkgstuff end @@ -61,7 +61,7 @@ Puppet::Type.type(:package).provide :ports, :parent => :freebsd, :source => :fre # Else, we need to be updated; we need to pull out the new version unless info =~ /\((\w+) has (.+)\)/ - raise Puppet::PackageError, + raise Puppet::Error, "Could not match version info '%s'" % info end diff --git a/lib/puppet/provider/service/redhat.rb b/lib/puppet/provider/service/redhat.rb index 3fad8bcfe..d26f76ebd 100755 --- a/lib/puppet/provider/service/redhat.rb +++ b/lib/puppet/provider/service/redhat.rb @@ -61,6 +61,7 @@ Puppet::Type.type(:service).provide :redhat, :parent => :init do if @resource[:hasstatus] == :true begin service(@resource[:name], "status") + return :running rescue return :stopped end diff --git a/lib/puppet/provider/ssh_authorized_key/parsed.rb b/lib/puppet/provider/ssh_authorized_key/parsed.rb index 3bd22c06b..602e6dd1b 100644 --- a/lib/puppet/provider/ssh_authorized_key/parsed.rb +++ b/lib/puppet/provider/ssh_authorized_key/parsed.rb @@ -14,7 +14,7 @@ Puppet::Type.type(:ssh_authorized_key).provide(:parsed, :fields => %w{options type key name}, :optional => %w{options}, :rts => /^\s+/, - :match => /^(?:([^ ]+) )?(ssh-dss|ssh-rsa) ([^ ]+)(?: (.+))?$/, + :match => /^(?:(.+) )?(ssh-dss|ssh-rsa) ([^ ]+)(?: (.+))?$/, :post_parse => proc { |record| if record[:options].nil? record[:options] = [:absent] diff --git a/lib/puppet/rails/resource.rb b/lib/puppet/rails/resource.rb index 0053dc28d..255b0e788 100644 --- a/lib/puppet/rails/resource.rb +++ b/lib/puppet/rails/resource.rb @@ -6,12 +6,12 @@ require 'puppet/util/rails/collection_merger' class Puppet::Rails::Resource < ActiveRecord::Base include Puppet::Util::CollectionMerger - has_many :param_values, :dependent => :destroy - has_many :param_names, :through => :param_values + has_many :param_values, :dependent => :destroy, :class_name => "Puppet::Rails::ParamValue" + has_many :param_names, :through => :param_values, :class_name => "Puppet::Rails::ParamName" + + has_many :resource_tags, :dependent => :destroy, :class_name => "Puppet::Rails::ResourceTag" + has_many :puppet_tags, :through => :resource_tags, :class_name => "Puppet::Rails::PuppetTag" - has_many :resource_tags, :dependent => :destroy - has_many :puppet_tags, :through => :resource_tags - belongs_to :source_file belongs_to :host @@ -82,7 +82,7 @@ class Puppet::Rails::Resource < ActiveRecord::Base end def ref - "%s[%s]" % [self[:restype].capitalize, self[:title]] + "%s[%s]" % [self[:restype].split("::").collect { |s| s.capitalize }.join("::"), self[:title]] end # Convert our object to a resource. Do not retain whether the object diff --git a/lib/puppet/reports/rrdgraph.rb b/lib/puppet/reports/rrdgraph.rb index 03d8a5bdd..5889750dd 100644 --- a/lib/puppet/reports/rrdgraph.rb +++ b/lib/puppet/reports/rrdgraph.rb @@ -90,8 +90,9 @@ Puppet::Reports.register_report(:rrdgraph) do of.puts "<html><head><title>Report graphs for %s</title></head><body>" % host files.each do |file| - of.puts "<a href='#{File.basename(file)}'>%s</a><br/>" % - File.basename(file).sub(".html",'').capitalize + of.puts "<a href='%s'>%s</a><br/>" % + [File.basename(file), + File.basename(file).sub(".html",'').capitalize] end of.puts "</body></html>" end diff --git a/lib/puppet/sslcertificates/inventory.rb b/lib/puppet/sslcertificates/inventory.rb index da959aa3b..295c416cb 100644 --- a/lib/puppet/sslcertificates/inventory.rb +++ b/lib/puppet/sslcertificates/inventory.rb @@ -7,8 +7,9 @@ module Puppet::SSLCertificates # If no inventory exists yet, build an inventory and list all the # certificates that have been signed so far def self.add(cert) - unless FileTest.exists?(Puppet[:cert_inventory]) - inited = false + inited = false + if FileTest.exists?(Puppet[:cert_inventory]) + inited = true end Puppet.settings.write(:cert_inventory, "a") do |f| diff --git a/lib/puppet/transaction/report.rb b/lib/puppet/transaction/report.rb index bd62ebbe6..89da7ed9c 100644 --- a/lib/puppet/transaction/report.rb +++ b/lib/puppet/transaction/report.rb @@ -25,13 +25,7 @@ class Puppet::Transaction::Report hash[key] = [] end - domain = Facter.value("domain") - hostname = Facter.value("hostname") - if !domain || domain.empty? then - @host = hostname - else - @host = [hostname, domain].join(".") - end + @host = Puppet[:certname] end def name diff --git a/lib/puppet/transportable.rb b/lib/puppet/transportable.rb index 3ad084b3b..d203b5928 100644 --- a/lib/puppet/transportable.rb +++ b/lib/puppet/transportable.rb @@ -65,13 +65,16 @@ module Puppet end def to_manifest - "#{self.type.to_s} { \'#{self.name}\':\n%s\n}" % @params.collect { |p, v| - if v.is_a? Array - " #{p} => [\'#{v.join("','")}\']" - else - " #{p} => \'#{v}\'" - end - }.join(",\n") + "%s { '%s':\n%s\n}" % + [self.type.to_s, self.name, + @params.collect { |p, v| + if v.is_a? Array + " #{p} => [\'#{v.join("','")}\']" + else + " #{p} => \'#{v}\'" + end + }.join(",\n") + ] end def to_yaml_properties diff --git a/lib/puppet/type/yumrepo.rb b/lib/puppet/type/yumrepo.rb index cb7c7401b..1e917793b 100644 --- a/lib/puppet/type/yumrepo.rb +++ b/lib/puppet/type/yumrepo.rb @@ -347,7 +347,23 @@ module Puppet newvalue(%r{[1-9][0-9]?}) { } end - - + newproperty(:proxy, :parent => Puppet::IniProperty) do + desc "URL to the proxy server for this repository.\n#{ABSENT_DOC}" + newvalue(:absent) { self.should = :absent } + # Should really check that it's a valid URL + newvalue(/.*/) { } + end + + newproperty(:proxy_username, :parent => Puppet::IniProperty) do + desc "Username for this proxy.\n#{ABSENT_DOC}" + newvalue(:absent) { self.should = :absent } + newvalue(/.*/) { } + end + + newproperty(:proxy_password, :parent => Puppet::IniProperty) do + desc "Password for this proxy.\n#{ABSENT_DOC}" + newvalue(:absent) { self.should = :absent } + newvalue(/.*/) { } + end end end diff --git a/lib/puppet/util/ldap/manager.rb b/lib/puppet/util/ldap/manager.rb index 9761fc753..8d444195e 100644 --- a/lib/puppet/util/ldap/manager.rb +++ b/lib/puppet/util/ldap/manager.rb @@ -80,7 +80,7 @@ class Puppet::Util::Ldap::Manager # Calculate the dn for a given resource. def dn(name) - ["#{rdn.to_s}=%s" % name, base].join(",") + ["%s=%s" % [rdn, name], base].join(",") end # Convert an ldap-style entry hash to a provider-style hash. diff --git a/lib/puppet/util/log.rb b/lib/puppet/util/log.rb index 22f4f3233..8824a8b50 100644 --- a/lib/puppet/util/log.rb +++ b/lib/puppet/util/log.rb @@ -244,23 +244,31 @@ class Puppet::Util::Log newdesttype :console do - PINK = {:console => "[0;31m", :html => "FFA0A0"} - GREEN = {:console => "[0;32m", :html => "00CD00"} - YELLOW = {:console => "[0;33m", :html => "FFFF60"} - SLATE = {:console => "[0;34m", :html => "80A0FF"} - ORANGE = {:console => "[0;35m", :html => "FFA500"} - BLUE = {:console => "[0;36m", :html => "40FFFF"} - RESET = {:console => "[0m", :html => ""} + RED = {:console => "[0;31m", :html => "FFA0A0"} + GREEN = {:console => "[0;32m", :html => "00CD00"} + YELLOW = {:console => "[0;33m", :html => "FFFF60"} + BLUE = {:console => "[0;34m", :html => "80A0FF"} + PURPLE = {:console => "[0;35m", :html => "FFA500"} + CYAN = {:console => "[0;36m", :html => "40FFFF"} + WHITE = {:console => "[0;37m", :html => "FFFFFF"} + HRED = {:console => "[1;31m", :html => "FFA0A0"} + HGREEN = {:console => "[1;32m", :html => "00CD00"} + HYELLOW = {:console => "[1;33m", :html => "FFFF60"} + HBLUE = {:console => "[1;34m", :html => "80A0FF"} + HPURPLE = {:console => "[1;35m", :html => "FFA500"} + HCYAN = {:console => "[1;36m", :html => "40FFFF"} + HWHITE = {:console => "[1;37m", :html => "FFFFFF"} + RESET = {:console => "[0m", :html => ""} @@colormap = { - :debug => SLATE, + :debug => WHITE, :info => GREEN, - :notice => PINK, - :warning => ORANGE, - :err => YELLOW, - :alert => BLUE, - :emerg => RESET, - :crit => RESET + :notice => CYAN, + :warning => YELLOW, + :err => HPURPLE, + :alert => RED, + :emerg => HRED, + :crit => HRED } def colorize(level, str) diff --git a/lib/puppet/util/posix.rb b/lib/puppet/util/posix.rb index 8228734ef..aff797485 100755 --- a/lib/puppet/util/posix.rb +++ b/lib/puppet/util/posix.rb @@ -3,23 +3,22 @@ module Puppet::Util::POSIX # Retrieve a field from a POSIX Etc object. The id can be either an integer # or a name. This only works for users and groups. It's also broken on - # some platforms, unfortunately. - def old_get_posix_field(space, field, id) + # some platforms, unfortunately, which is why we fall back to the other + # method search_posix_field in the gid and uid methods if a sanity check + # fails + def get_posix_field(space, field, id) unless id raise ArgumentError, "Did not get id" end - if id =~ /^\d+$/ - id = Integer(id) - end prefix = "get" + space.to_s if id.is_a?(Integer) if id > Puppet[:maximum_uid].to_i Puppet.err "Tried to get %s field for silly id %s" % [field, id] return nil end - method = (prefix + idfield(space).to_s).intern + method = methodbyid(space) else - method = (prefix + "nam").intern + method = methodbyname(space) end begin @@ -31,13 +30,11 @@ module Puppet::Util::POSIX end # A degenerate method of retrieving name/id mappings. The job of this method is - # to find a specific entry and then return a given field from that entry. - def get_posix_field(type, field, id) + # to retrieve all objects of a certain type, search for a specific entry + # and then return a given field from that entry. + def search_posix_field(type, field, id) idmethod = idfield(type) integer = false - if id =~ /^\d+$/ - id = Integer(id) - end if id.is_a?(Integer) integer = true if id > Puppet[:maximum_uid].to_i @@ -73,14 +70,70 @@ module Puppet::Util::POSIX end end + # Determine what the method is to get users and groups by id + def methodbyid(space) + case Puppet::Util.symbolize(space) + when :gr, :group: return :getgrgid + when :pw, :user, :passwd: return :getpwuid + else + raise ArgumentError.new("Can only handle users and groups") + end + end + + # Determine what the method is to get users and groups by name + def methodbyname(space) + case Puppet::Util.symbolize(space) + when :gr, :group: return :getgrnam + when :pw, :user, :passwd: return :getpwnam + else + raise ArgumentError.new("Can only handle users and groups") + end + end + # Get the GID of a given group, provided either a GID or a name def gid(group) - get_posix_field(:group, :gid, group) + begin + group = Integer(group) + rescue ArgumentError + # pass + end + if group.is_a?(Integer) + name = get_posix_field(:group, :name, group) + gid = get_posix_field(:group, :gid, name) + check_value = gid + else + gid = get_posix_field(:group, :gid, group) + name = get_posix_field(:group, :name, gid) + check_value = name + end + if check_value != group + return search_posix_field(:group, :gid, group) + else + return gid + end end # Get the UID of a given user, whether a UID or name is provided def uid(user) - get_posix_field(:passwd, :uid, user) + begin + user = Integer(user) + rescue ArgumentError + # pass + end + if user.is_a?(Integer) + name = get_posix_field(:passwd, :name, user) + uid = get_posix_field(:passwd, :uid, name) + check_value = uid + else + uid = get_posix_field(:passwd, :uid, user) + name = get_posix_field(:passwd, :name, uid) + check_value = name + end + if check_value != user + return search_posix_field(:passwd, :uid, user) + else + return uid + end end end diff --git a/spec/unit/indirector/ldap.rb b/spec/unit/indirector/ldap.rb index 52abd413a..2c4060c4d 100755 --- a/spec/unit/indirector/ldap.rb +++ b/spec/unit/indirector/ldap.rb @@ -113,15 +113,25 @@ describe Puppet::Indirector::Ldap do describe "when connecting to ldap" do confine "LDAP is not available" => Puppet.features.ldap? + it "should create and start a Util::Ldap::Connection instance" do + conn = mock 'connection', :connection => "myconn", :start => nil + Puppet::Util::Ldap::Connection.expects(:instance).returns conn + + @searcher.connection.should == "myconn" + end + it "should only create the ldap connection when asked for it the first time" do - @searcher.connection.should equal(@searcher.connection) + conn = mock 'connection', :connection => "myconn", :start => nil + Puppet::Util::Ldap::Connection.expects(:instance).returns conn + + @searcher.connection end - it "should create and start a Util::Ldap::Connection instance" do + it "should cache the connection" do conn = mock 'connection', :connection => "myconn", :start => nil Puppet::Util::Ldap::Connection.expects(:instance).returns conn - @searcher.connection.should == "myconn" + @searcher.connection.should equal(@searcher.connection) end end diff --git a/spec/unit/indirector/yaml.rb b/spec/unit/indirector/yaml.rb index 3875d70aa..081ae9666 100755 --- a/spec/unit/indirector/yaml.rb +++ b/spec/unit/indirector/yaml.rb @@ -106,4 +106,33 @@ describe Puppet::Indirector::Yaml, " when choosing file location" do proc { @store.find(@request) }.should raise_error(Puppet::Error) end end + + describe Puppet::Indirector::Yaml, " when searching" do + it "should return an array of fact instances with one instance for each file when globbing *" do + @request = stub 'request', :key => "*", :instance => @subject + @one = mock 'one' + @two = mock 'two' + @store.expects(:base).returns "/my/yaml/dir" + Dir.expects(:glob).with(File.join("/my/yaml/dir", @store.class.indirection_name.to_s, @request.key)).returns(%w{one.yaml two.yaml}) + YAML.expects(:load_file).with("one.yaml").returns @one; + YAML.expects(:load_file).with("two.yaml").returns @two; + @store.search(@request).should == [@one, @two] + end + + it "should return an array containing a single instance of fact when globbing 'one*'" do + @request = stub 'request', :key => "one*", :instance => @subject + @one = mock 'one' + @store.expects(:base).returns "/my/yaml/dir" + Dir.expects(:glob).with(File.join("/my/yaml/dir", @store.class.indirection_name.to_s, @request.key)).returns(%w{one.yaml}) + YAML.expects(:load_file).with("one.yaml").returns @one; + @store.search(@request).should == [@one] + end + + it "should return an empty array when the glob doesn't match anything" do + @request = stub 'request', :key => "f*ilglobcanfail*", :instance => @subject + @store.expects(:base).returns "/my/yaml/dir" + Dir.expects(:glob).with(File.join("/my/yaml/dir", @store.class.indirection_name.to_s, @request.key)).returns([]) + @store.search(@request).should == [] + end + end end diff --git a/spec/unit/parser/lexer.rb b/spec/unit/parser/lexer.rb index 9972f7268..fb666054d 100755 --- a/spec/unit/parser/lexer.rb +++ b/spec/unit/parser/lexer.rb @@ -378,6 +378,15 @@ describe "Puppet::Parser::Lexer in the old tests" do } end + it "should correctly parse names with numerals" do + string = %w{1name name1 11names names11} + + string.each { |t| + @lexer.string = t + @lexer.fullscan.should == [[:NAME,t],[false,false]] + } + end + it "should correctly parse empty strings" do bit = '$var = ""' diff --git a/spec/unit/parser/templatewrapper.rb b/spec/unit/parser/templatewrapper.rb index 40465f955..2d4bd141b 100755 --- a/spec/unit/parser/templatewrapper.rb +++ b/spec/unit/parser/templatewrapper.rb @@ -6,7 +6,7 @@ describe Puppet::Parser::TemplateWrapper do before(:each) do compiler = stub('compiler', :environment => "foo") parser = stub('parser', :watch_file => true) - @scope = stub('scope', :compiler => compiler, :parser => parser) + @scope = stub('scope', :compiler => compiler, :parser => parser, :to_hash => {}) @file = "fake_template" Puppet::Module.stubs(:find_template).returns("/tmp/fake_template") FileTest.stubs(:exists?).returns("true") @@ -54,4 +54,15 @@ describe Puppet::Parser::TemplateWrapper do tw = Puppet::Parser::TemplateWrapper.new(@scope, @file) tw.has_variable?("chicken").should eql(false) end + + it "should set all of the scope's variables as instance variables" do + template_mock = mock("template", :result => "woot!") + File.expects(:read).with("/tmp/fake_template").returns("template contents") + ERB.expects(:new).with("template contents", 0, "-").returns(template_mock) + + @scope.expects(:to_hash).returns("one" => "foo") + @tw.result + + @tw.instance_variable_get("@one").should == "foo" + end end diff --git a/test/language/functions.rb b/test/language/functions.rb index a5d52d7ac..97429802b 100755 --- a/test/language/functions.rb +++ b/test/language/functions.rb @@ -96,11 +96,12 @@ class TestLangFunctions < Test::Unit::TestCase twop = File.join(Puppet[:templatedir], "two") File.open(onep, "w") do |f| - f.puts "template <%= one %>" + f.puts "<%- if @one.nil? then raise '@one undefined' end -%>" + + "template <%= @one %>" end File.open(twop, "w") do |f| - f.puts "template <%= two %>" + f.puts "template <%= @two %>" end func = nil assert_nothing_raised do @@ -116,15 +117,27 @@ class TestLangFunctions < Test::Unit::TestCase ast = varobj("output", func) scope = mkscope + + # Test that our manual exception throw fails the parse assert_raise(Puppet::ParseError) do ast.evaluate(scope) end + # Test that our use of an undefined instance variable does not throw + # an exception, but only safely continues. scope.setvar("one", "One") - assert_raise(Puppet::ParseError) do + assert_nothing_raised do ast.evaluate(scope) end + + # Ensure that we got the output we expected from that evaluation. + assert_equal("template One\ntemplate \n", scope.lookupvar("output"), + "Undefined template variables do not raise exceptions") + + # Now, fill in the last variable and make sure the whole thing + # evaluates correctly. scope.setvar("two", "Two") + scope.unsetvar("output") assert_nothing_raised do ast.evaluate(scope) end @@ -138,7 +151,7 @@ class TestLangFunctions < Test::Unit::TestCase template = tempfile() File.open(template, "w") do |f| - f.puts "template <%= yayness %>" + f.puts "template <%= @yay.nil?() ? raise('yay undefined') : @yay %>" end func = nil @@ -158,17 +171,77 @@ class TestLangFunctions < Test::Unit::TestCase ast.evaluate(scope) end - scope.setvar("yayness", "this is yayness") + scope.setvar("yay", "this is yay") assert_nothing_raised do ast.evaluate(scope) end - assert_equal("template this is yayness\n", scope.lookupvar("output"), + assert_equal("template this is yay\n", scope.lookupvar("output"), "Templates were not handled correctly") end + # Make sure that legacy template variable access works as expected. + def test_legacyvariables + template = tempfile() + + File.open(template, "w") do |f| + f.puts "template <%= deprecated %>" + end + + func = nil + assert_nothing_raised do + func = Puppet::Parser::AST::Function.new( + :name => "template", + :ftype => :rvalue, + :arguments => AST::ASTArray.new( + :children => [stringobj(template)] + ) + ) + end + ast = varobj("output", func) + + # Verify that we get an exception using old-style accessors. + scope = mkscope + assert_raise(Puppet::ParseError) do + ast.evaluate(scope) + end + + # Verify that we evaluate and return their value correctly. + scope.setvar("deprecated", "deprecated value") + assert_nothing_raised do + ast.evaluate(scope) + end + + assert_equal("template deprecated value\n", scope.lookupvar("output"), + "Deprecated template variables were not handled correctly") + end + + # Make sure that problems with kernel method visibility still exist. + def test_kernel_module_shadows_deprecated_var_lookup + template = tempfile() + File.open(template, "w").puts("<%= binding %>") + + func = nil + assert_nothing_raised do + func = Puppet::Parser::AST::Function.new( + :name => "template", + :ftype => :rvalue, + :arguments => AST::ASTArray.new( + :children => [stringobj(template)] + ) + ) + end + ast = varobj("output", func) + + # Verify that Kernel methods still shadow deprecated variable lookups. + scope = mkscope + assert_nothing_raised("No exception for Kernel shadowed variable names") do + ast.evaluate(scope) + end + end + def test_tempatefunction_cannot_see_scopes template = tempfile() @@ -243,7 +316,7 @@ class TestLangFunctions < Test::Unit::TestCase template = tempfile() File.open(template, "w") do |f| - f.puts "template <%= yayness %>" + f.puts "template <%= @yayness %>" end func = nil @@ -263,10 +336,6 @@ class TestLangFunctions < Test::Unit::TestCase false => "false", }.each do |string, value| scope = mkscope - assert_raise(Puppet::ParseError) do - ast.evaluate(scope) - end - scope.setvar("yayness", string) assert_equal(string, scope.lookupvar("yayness", false)) diff --git a/test/language/scope.rb b/test/language/scope.rb index c96581a23..0fa211fc3 100755 --- a/test/language/scope.rb +++ b/test/language/scope.rb @@ -53,6 +53,34 @@ class TestScope < Test::Unit::TestCase assert_equal(:undefined, scopes[name].lookupvar("third", false), "Found child var in top scope") end assert_equal("botval", scopes[:bot].lookupvar("third", false), "Could not find var in bottom scope") + + + # Test that the scopes convert to hash structures correctly. + # For topscope recursive vs non-recursive should be identical + assert_equal(topscope.to_hash(false), topscope.to_hash(true), + "Recursive and non-recursive hash is identical for topscope") + + # Check the variable we expect is present. + assert_equal({"first" => "topval"}, topscope.to_hash(), + "topscope returns the expected hash of variables") + + # Now, check that midscope does the right thing in all cases. + assert_equal({"second" => "midval"}, + midscope.to_hash(false), + "midscope non-recursive hash contains only midscope variable") + assert_equal({"first" => "topval", "second" => "midval"}, + midscope.to_hash(true), + "midscope recursive hash contains topscope variable also") + + # Finally, check the ability to shadow symbols by adding a shadow to + # bottomscope, then checking that we see the right stuff. + botscope.setvar("first", "shadowval") + assert_equal({"third" => "botval", "first" => "shadowval"}, + botscope.to_hash(false), + "botscope has the right non-recursive hash") + assert_equal({"third" => "botval", "first" => "shadowval", "second" => "midval"}, + botscope.to_hash(true), + "botscope values shadow parent scope values") end def test_lookupvar diff --git a/test/ral/type/yumrepo.rb b/test/ral/type/yumrepo.rb index 273179bc4..a42fa9058 100755 --- a/test/ral/type/yumrepo.rb +++ b/test/ral/type/yumrepo.rb @@ -48,7 +48,10 @@ class TestYumRepo < Test::Unit::TestCase :enabled => "1", :gpgcheck => "1", :includepkgs => "absent", - :gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora" + :gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora", + :proxy => "http://proxy.example.com:80/", + :proxy_username => "username", + :proxy_password => "password" } repo = make_repo("base", values) @@ -102,6 +105,9 @@ baseurl=http://example.com/yum/$releasever/$basearch/os/ enabled=1 gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora +proxy=http://proxy.example.com:80/ +proxy_username=username +proxy_password=password EOF end diff --git a/test/util/posixtest.rb b/test/util/posixtest.rb index 8fd11b086..f64a95d18 100755 --- a/test/util/posixtest.rb +++ b/test/util/posixtest.rb @@ -25,16 +25,39 @@ class TestPosixUtil < Test::Unit::TestCase def test_get_posix_field {:group => nonrootgroup, :passwd => nonrootuser}.each do |space, obj| id = Puppet::Util.idfield(space) - [obj.name, obj.send(id), obj.send(id).to_s].each do |test| + [obj.name, obj.send(id)].each do |test| value = nil assert_nothing_raised do value = get_posix_field(space, :name, test) end - assert_equal(obj.name, value, "did not get correct value from get_posix_field") + assert_equal(obj.name, value, "did not get correct value from get_posix_field (known to be broken on some platforms)") end end end + def test_search_posix_field + {:group => nonrootgroup, :passwd => nonrootuser}.each do |space, obj| + id = Puppet::Util.idfield(space) + [obj.name, obj.send(id)].each do |test| + value = nil + assert_nothing_raised do + value = search_posix_field(space, :name, test) + end + assert_equal(obj.name, value, "did not get correct value from search_posix_field") + end + end + end + + def test_get_provider_value + user = nonrootuser + obj = mk_posix_resource(:user, user) + + assert_nothing_raised do + assert_equal(user.uid, get_provider_value(:user, :uid, user.uid)) + assert_equal(user.name, get_provider_value(:user, :name, user.name)) + end + end + def test_gid_and_uid {:user => nonrootuser, :group => nonrootgroup}.each do |type, obj| method = idfield(type) |