summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG45
-rw-r--r--Rakefile2
-rw-r--r--ext/puppetstoredconfigclean.rb2
-rw-r--r--lib/puppet/application/agent.rb2
-rw-r--r--lib/puppet/application/apply.rb23
-rw-r--r--lib/puppet/configurer.rb23
-rwxr-xr-xlib/puppet/daemon.rb4
-rw-r--r--lib/puppet/defaults.rb19
-rw-r--r--lib/puppet/external/pson/pure/generator.rb23
-rw-r--r--lib/puppet/indirector/catalog/compiler.rb12
-rw-r--r--lib/puppet/indirector/report/yaml.rb11
-rwxr-xr-xlib/puppet/network/handler/fileserver.rb2
-rw-r--r--lib/puppet/network/server.rb4
-rw-r--r--lib/puppet/node/environment.rb4
-rw-r--r--lib/puppet/parser/ast/collection.rb85
-rw-r--r--lib/puppet/parser/ast/leaf.rb12
-rw-r--r--lib/puppet/parser/functions.rb6
-rw-r--r--lib/puppet/parser/parser_support.rb6
-rw-r--r--lib/puppet/parser/templatewrapper.rb1
-rw-r--r--lib/puppet/provider.rb4
-rw-r--r--lib/puppet/provider/confine/exists.rb5
-rw-r--r--lib/puppet/provider/host/parsed.rb76
-rwxr-xr-xlib/puppet/provider/maillist/mailman.rb11
-rw-r--r--lib/puppet/provider/mount.rb2
-rwxr-xr-xlib/puppet/provider/package/openbsd.rb16
-rwxr-xr-xlib/puppet/provider/package/yum.rb9
-rw-r--r--lib/puppet/provider/service/freebsd.rb5
-rw-r--r--lib/puppet/provider/user/user_role_add.rb4
-rw-r--r--lib/puppet/provider/user/useradd.rb4
-rw-r--r--lib/puppet/rails.rb8
-rw-r--r--lib/puppet/rails/host.rb72
-rw-r--r--lib/puppet/resource.rb12
-rw-r--r--lib/puppet/simple_graph.rb417
-rw-r--r--lib/puppet/transaction/report.rb39
-rwxr-xr-xlib/puppet/type/exec.rb8
-rwxr-xr-xlib/puppet/type/host.rb28
-rwxr-xr-xlib/puppet/type/schedule.rb10
-rw-r--r--lib/puppet/util.rb38
-rw-r--r--lib/puppet/util/command_line.rb2
-rw-r--r--lib/puppet/util/file_locking.rb9
-rw-r--r--lib/puppet/util/log.rb1
-rw-r--r--lib/puppet/util/log/destinations.rb14
-rw-r--r--lib/puppet/util/metric.rb10
-rw-r--r--lib/puppet/util/monkey_patches.rb15
-rw-r--r--lib/puppet/util/rdoc.rb9
-rw-r--r--lib/puppet/util/rdoc/generators/puppet_generator.rb6
-rw-r--r--lib/puppet/util/reference.rb9
-rw-r--r--lib/puppet/util/suidmanager.rb2
-rw-r--r--lib/puppet/util/zaml.rb5
-rwxr-xr-xspec/integration/configurer_spec.rb43
-rwxr-xr-xspec/integration/defaults_spec.rb1
-rw-r--r--spec/integration/parser/functions_spec.rb21
-rw-r--r--spec/integration/parser/ruby_manifest_spec.rb2
-rwxr-xr-xspec/integration/ssl/certificate_authority_spec.rb4
-rwxr-xr-xspec/integration/util/file_locking_spec.rb42
-rw-r--r--spec/spec_helper.rb2
-rwxr-xr-xspec/unit/application/agent_spec.rb7
-rwxr-xr-xspec/unit/application/apply_spec.rb31
-rw-r--r--spec/unit/application/filebucket_spec.rb1
-rwxr-xr-xspec/unit/application/queue_spec.rb1
-rwxr-xr-xspec/unit/configurer_spec.rb79
-rwxr-xr-xspec/unit/daemon_spec.rb12
-rwxr-xr-xspec/unit/indirector/active_record_spec.rb1
-rwxr-xr-xspec/unit/indirector/catalog/compiler_spec.rb17
-rwxr-xr-xspec/unit/indirector/facts/active_record_spec.rb1
-rw-r--r--spec/unit/indirector/report/yaml_spec.rb38
-rw-r--r--spec/unit/network/handler/fileserver_spec.rb6
-rwxr-xr-xspec/unit/network/http/rack/xmlrpc_spec.rb1
-rwxr-xr-xspec/unit/network/http/rack_spec.rb1
-rwxr-xr-xspec/unit/network/http/webrick_spec.rb1
-rwxr-xr-xspec/unit/network/server_spec.rb13
-rwxr-xr-xspec/unit/parser/ast/collection_spec.rb4
-rwxr-xr-xspec/unit/parser/ast/leaf_spec.rb44
-rwxr-xr-xspec/unit/parser/ast/resource_spec.rb4
-rwxr-xr-xspec/unit/parser/collector_spec.rb1
-rwxr-xr-xspec/unit/parser/parser_spec.rb53
-rwxr-xr-xspec/unit/parser/templatewrapper_spec.rb1
-rwxr-xr-xspec/unit/provider/confine/exists_spec.rb19
-rw-r--r--spec/unit/provider/host/parsed_spec.rb196
-rwxr-xr-xspec/unit/provider/mount_spec.rb9
-rw-r--r--spec/unit/provider/package/yum_spec.rb67
-rw-r--r--spec/unit/provider/service/freebsd_spec.rb50
-rw-r--r--spec/unit/provider/service/upstart.rb3
-rwxr-xr-xspec/unit/provider/ssh_authorized_key/parsed_spec.rb3
-rwxr-xr-xspec/unit/rails/param_value_spec.rb1
-rwxr-xr-xspec/unit/rails/resource_spec.rb1
-rwxr-xr-xspec/unit/rails_spec.rb104
-rwxr-xr-xspec/unit/resource/catalog_spec.rb6
-rwxr-xr-xspec/unit/simple_graph_spec.rb248
-rwxr-xr-xspec/unit/transaction/report_spec.rb15
-rwxr-xr-xspec/unit/type/host_spec.rb83
-rwxr-xr-xspec/unit/type/schedule_spec.rb70
-rw-r--r--spec/unit/util/command_line_spec.rb4
-rwxr-xr-xspec/unit/util/file_locking_spec.rb52
-rwxr-xr-xspec/unit/util/log_spec.rb4
-rw-r--r--spec/unit/util/monkey_patches_spec.rb26
-rwxr-xr-xspec/unit/util/pson_spec.rb15
-rwxr-xr-xspec/unit/util/rdoc_spec.rb10
-rwxr-xr-xspec/unit/util/storage_spec.rb5
-rwxr-xr-xspec/unit/util/zaml_spec.rb1
-rw-r--r--test/data/providers/host/parsed/valid_hosts19
-rwxr-xr-xtest/lib/puppettest.rb4
-rwxr-xr-xtest/other/provider.rb13
-rwxr-xr-xtest/puppet/tc_suidmanager.rb19
-rwxr-xr-xtest/ral/manager/type.rb2
-rwxr-xr-xtest/ral/providers/host/parsed.rb9
-rwxr-xr-xtest/ral/providers/provider.rb6
107 files changed, 1772 insertions, 860 deletions
diff --git a/CHANGELOG b/CHANGELOG
index e708b2b6b..78483351c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,50 @@
+2.6.3
+=====
+184733c [#5322] (#5322) Remove spec file that adds little value and causes failures
+178c2a6 Fix test failures that fixing #4726 exposed.
+74b6c09 (#4726) Fix RRD legacy support
+8662056 Fix for #4279 -- mount detection on HP-UX
+fbb096a Fix for #5055 -- adding to_sym to Puppet::Node::Environment
+b2ff6a5 Fix for #5298 -- Collections need to do type lookup
+1ce00dc Step towards [5298] -- cleanup indentation, etc. in AST::Collection
+722608b Fixed #5287 - Schedule documentation is incorrect
+c8b6fb5 Fixed #5296 - test warnings messages
+d221c05 (#5297) Fix schedule tests that were missing stubs for Time.now
+f2fd0d1 Fix for #5273 -- user resource constantly resetting password age
+544dcf8 Fix #5289 -- Bad copy/paste changes message on test failure
+
+2.6.3rc3
+========
+126681f Updated CHANGELOG for 2.6.3rc3
+b15231d Fix for #4299 -- Don't require which
+ea435a4 Fix #5020 - Prefer finding node name from REST uri over certname
+a097b93 Fix for #4894 -- retry tests if port is in use
+ee61b4e Fix for #4955 -- Race condition & memory leak in Puppet::Util
+f57425d Fix #4921 - race condition in Parser Functions creation
+9604f1c Fix #5252 - line number mis-attribution during parsing
+cc5224c Maint. fix for test broken by 00eedac5
+5f7d0fb Fix for #2568 -- Add a dbconnections option to set AR pool size
+ba4d22b Maint. Removing code for which no CLA has been signed
+4a3d5d7 Reimplementation of functionality removed by prior commit
+235d641 Refactor for CLA
+9ba0c8a Fix #4923 - close process race when truncating existing file
+cb16d3d Puppet-load: better and safer error reporting
+1d26742 Fix #5023 - puppet-load multiple nodes support
+00eedac capture stderr from exec resources
+4cbceab (#4573) FreeBSD service provider now supports versions <7 and >8
+06c8748 Fix #3808 - puppetdoc should use --force-update only if RDoc supports it
+6e6712b [#4813] Remove dead code from puppet/rails/host.rb
+956296a Fix #4911 - Do not generate doc for standard RDoc parser generated object
+4fa24bb Fix #5127 - error when accessing array elements
+abb8c66 (#5242) Fix schedule specs that fail near daylight savings
+ec667fd Kludge for #5206 -- port of fix for #3536 to yaml
+9a3b584 (#5062) Add envpuppet helper script to ext/
+aad7008 [#5225] Fix spec failure that depended on time change
+21db472 (#5233) Randomize tmp dir paths
+
2.6.3rc2
========
+244213c Updated CHANGELOG for 2.6.3rc2
76ac1f8 Fixed #5112 - Launchd Service broke in 2.6.2 with OS X 10.4 Clients.
776ea2a Fixed #5137 - Removed no longer required TOC references
31118fe Kludge for #5048 -- serialization compatibility with 0.25.x
diff --git a/Rakefile b/Rakefile
index 8e21cebd9..22d4a9aeb 100644
--- a/Rakefile
+++ b/Rakefile
@@ -43,7 +43,7 @@ desc "Create the tarball and the gem - use when releasing"
task :puppetpackages => [:create_gem, :package]
Spec::Rake::SpecTask.new do |t|
- t.spec_opts = ['--format','s', '--loadby','mtime','--color']
+ t.spec_opts = ['--format','s', '--loadby','mtime','--color', '--backtrace']
t.pattern ='spec/{unit,integration}/**/*.rb'
t.fail_on_error = false
end
diff --git a/ext/puppetstoredconfigclean.rb b/ext/puppetstoredconfigclean.rb
index 9b7b0c8a7..16f39efa1 100644
--- a/ext/puppetstoredconfigclean.rb
+++ b/ext/puppetstoredconfigclean.rb
@@ -70,8 +70,6 @@ case adapter
args[:port] = pm_conf[:dbport] unless pm_conf[:dbport].to_s.empty?
socket = pm_conf[:dbsocket]
args[:socket] = socket unless socket.to_s.empty?
- connections = pm_conf[:dbconnections].to_i
- args[:pool] = connections if connections > 0
else
raise ArgumentError, "Invalid db adapter #{adapter}"
end
diff --git a/lib/puppet/application/agent.rb b/lib/puppet/application/agent.rb
index 2b75505fd..c5ad72068 100644
--- a/lib/puppet/application/agent.rb
+++ b/lib/puppet/application/agent.rb
@@ -229,6 +229,8 @@ class Puppet::Application::Agent < Puppet::Application
Puppet::SSL::Host.ca_location = options[:fingerprint] ? :none : :remote
Puppet::Transaction::Report.terminus_class = :rest
+ # we want the last report to be persisted locally
+ Puppet::Transaction::Report.cache_class = :yaml
# Override the default; puppetd needs this, usually.
# You can still override this on the command-line with, e.g., :compiler.
diff --git a/lib/puppet/application/apply.rb b/lib/puppet/application/apply.rb
index 59a95d35a..8ec3fab6b 100644
--- a/lib/puppet/application/apply.rb
+++ b/lib/puppet/application/apply.rb
@@ -123,25 +123,9 @@ class Puppet::Application::Apply < Puppet::Application
require 'puppet/configurer'
configurer = Puppet::Configurer.new
- configurer.execute_prerun_command
+ report = configurer.run(:skip_plugin_download => true, :catalog => catalog)
- # And apply it
- if Puppet[:report]
- report = configurer.initialize_report
- Puppet::Util::Log.newdestination(report)
- end
- transaction = catalog.apply
-
- configurer.execute_postrun_command
-
- if Puppet[:report]
- Puppet::Util::Log.close(report)
- configurer.send_report(report, transaction)
- else
- transaction.generate_report
- end
-
- exit( Puppet[:noop] ? 0 : options[:detailed_exitcodes] ? transaction.report.exit_status : 0 )
+ exit( Puppet[:noop] ? 0 : options[:detailed_exitcodes] ? report.exit_status : 0 )
rescue => detail
puts detail.backtrace if Puppet[:trace]
$stderr.puts detail.message
@@ -164,6 +148,9 @@ class Puppet::Application::Apply < Puppet::Application
exit(1)
end
+ # we want the last report to be persisted locally
+ Puppet::Transaction::Report.cache_class = :yaml
+
if options[:debug]
Puppet::Util::Log.level = :debug
elsif options[:verbose]
diff --git a/lib/puppet/configurer.rb b/lib/puppet/configurer.rb
index 31d31c2d2..1c0639029 100644
--- a/lib/puppet/configurer.rb
+++ b/lib/puppet/configurer.rb
@@ -77,12 +77,12 @@ class Puppet::Configurer
end
# Prepare for catalog retrieval. Downloads everything necessary, etc.
- def prepare
+ def prepare(options)
dostorage
- download_plugins
+ download_plugins unless options[:skip_plugin_download]
- download_fact_plugins
+ download_fact_plugins unless options[:skip_plugin_download]
execute_prerun_command
end
@@ -126,7 +126,7 @@ class Puppet::Configurer
# which accepts :tags and :ignoreschedules.
def run(options = {})
begin
- prepare
+ prepare(options)
rescue SystemExit,NoMemoryError
raise
rescue Exception => detail
@@ -168,19 +168,30 @@ class Puppet::Configurer
execute_postrun_command
Puppet::Util::Log.close(report)
-
send_report(report, transaction)
end
def send_report(report, trans = nil)
trans.generate_report if trans
puts report.summary if Puppet[:summarize]
- report.save if Puppet[:report]
+ save_last_run_summary(report)
+ if Puppet[:report]
+ report.save
+ end
rescue => detail
puts detail.backtrace if Puppet[:trace]
Puppet.err "Could not send report: #{detail}"
end
+ def save_last_run_summary(report)
+ Puppet::Util::FileLocking.writelock(Puppet[:lastrunfile], 0660) do |file|
+ file.print YAML.dump(report.raw_summary)
+ end
+ rescue => detail
+ puts detail.backtrace if Puppet[:trace]
+ Puppet.err "Could not save last run local report: #{detail}"
+ end
+
private
def self.timeout
diff --git a/lib/puppet/daemon.rb b/lib/puppet/daemon.rb
index ad0edd3b9..c76d63a54 100755
--- a/lib/puppet/daemon.rb
+++ b/lib/puppet/daemon.rb
@@ -43,7 +43,7 @@ class Puppet::Daemon
# Create a pidfile for our daemon, so we can be stopped and others
# don't try to start.
def create_pidfile
- Puppet::Util.sync(Puppet[:name]).synchronize(Sync::EX) do
+ Puppet::Util.synchronize_on(Puppet[:name],Sync::EX) do
raise "Could not create PID file: #{pidfile}" unless Puppet::Util::Pidlock.new(pidfile).lock
end
end
@@ -73,7 +73,7 @@ class Puppet::Daemon
# Remove the pid file for our daemon.
def remove_pidfile
- Puppet::Util.sync(Puppet[:name]).synchronize(Sync::EX) do
+ Puppet::Util.synchronize_on(Puppet[:name],Sync::EX) do
locker = Puppet::Util::Pidlock.new(pidfile)
locker.unlock or Puppet.err "Could not remove PID file #{pidfile}" if locker.locked?
end
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index 7ae553827..8bf1cd84d 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -116,7 +116,7 @@ module Puppet
:catalog_terminus => ["compiler", "Where to get node catalogs. This is useful to change if, for instance,
you'd like to pre-compile catalogs and store them in memcached or some other easily-accessed store."],
:facts_terminus => {
- :default => Puppet.application_name.to_s == "master" ? 'yaml' : 'facter',
+ :default => Puppet.application_name.to_s == "master" ? 'yaml' : 'facter',
:desc => "The node facts terminus.",
:hook => proc do |value|
require 'puppet/node/facts'
@@ -599,9 +599,17 @@ module Puppet
:inventory_port => ["$masterport",
"The port to communicate with the inventory_server."
],
- :report => [false,
+ :report => [true,
"Whether to send reports after every transaction."
],
+ :lastrunfile => { :default => "$statedir/last_run_summary.yaml",
+ :mode => 0660,
+ :desc => "Where puppet agent stores the last run report summary in yaml format."
+ },
+ :lastrunreport => { :default => "$statedir/last_run_report.yaml",
+ :mode => 0660,
+ :desc => "Where puppet agent stores the last run report in yaml format."
+ },
:graph => [false, "Whether to create dot graph files for the different
configuration graphs. These dot files can be interpreted by tools
like OmniGraffle or dot (which is part of ImageMagick)."],
@@ -656,7 +664,7 @@ module Puppet
setdefaults(
:tagmail,
:tagmap => ["$confdir/tagmail.conf", "The mapping between reporting tags and email addresses."],
- :sendmail => [%x{which sendmail 2>/dev/null}.chomp, "Where to find the sendmail binary with which to send email."],
+ :sendmail => [which('sendmail') || '', "Where to find the sendmail binary with which to send email."],
:reportfrom => ["report@" + [Facter["hostname"].value, Facter["domain"].value].join("."), "The 'from' email address for the reports."],
:smtpserver => ["none", "The server through which to send email reports."]
@@ -682,11 +690,10 @@ module Puppet
used when networked databases are used."],
:dbpassword => [ "puppet", "The database password for caching. Only
used when networked databases are used."],
+ :dbconnections => [ '', "The number of database connections for networked
+ databases. Will be ignored unless the value is a positive integer."],
:dbsocket => [ "", "The database socket location. Only used when networked
databases are used. Will be ignored if the value is an empty string."],
- :dbconnections => [ 0, "The number of database connections. Only used when
- networked databases are used. Will be ignored if the value is an empty
- string or is less than 1."],
:railslog => {:default => "$logdir/rails.log",
:mode => 0600,
:owner => "service",
diff --git a/lib/puppet/external/pson/pure/generator.rb b/lib/puppet/external/pson/pure/generator.rb
index 4180be57d..89a0c62e0 100644
--- a/lib/puppet/external/pson/pure/generator.rb
+++ b/lib/puppet/external/pson/pure/generator.rb
@@ -44,34 +44,13 @@ module PSON
string << '' # XXX workaround: avoid buffer sharing
string.force_encoding(Encoding::ASCII_8BIT)
string.gsub!(/["\\\x0-\x1f]/) { MAP[$MATCH] }
- string.gsub!(/(
- (?:
- [\xc2-\xdf][\x80-\xbf] |
- [\xe0-\xef][\x80-\xbf]{2} |
- [\xf0-\xf4][\x80-\xbf]{3}
- )+ |
- [\x80-\xc1\xf5-\xff] # invalid
- )/nx) { |c|
- c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
- s = PSON::UTF8toUTF16.iconv(c).unpack('H*')[0]
- s.gsub!(/.{4}/n, '\\\\u\&')
- }
- string.force_encoding(Encoding::UTF_8)
string
rescue Iconv::Failure => e
raise GeneratorError, "Caught #{e.class}: #{e}"
end
else
def utf8_to_pson(string) # :nodoc:
- string.
- gsub(/["\\\x0-\x1f]/n) { MAP[$MATCH] }.
- gsub(/((?:
- [\xc2-\xdf][\x80-\xbf] |
- [\xe0-\xef][\x80-\xbf]{2} |
- [\xf0-\xf4][\x80-\xbf]{3}
- )+)/nx) { |c|
- PSON::UTF8toUTF16.iconv(c).unpack('H*')[0].gsub(/.{4}/n, '\\\\u\&')
- }
+ string.gsub(/["\\\x0-\x1f]/n) { MAP[$MATCH] }
end
end
module_function :utf8_to_pson
diff --git a/lib/puppet/indirector/catalog/compiler.rb b/lib/puppet/indirector/catalog/compiler.rb
index 1e1ae12b1..78be4caf7 100644
--- a/lib/puppet/indirector/catalog/compiler.rb
+++ b/lib/puppet/indirector/catalog/compiler.rb
@@ -108,10 +108,14 @@ class Puppet::Resource::Catalog::Compiler < Puppet::Indirector::Code
return node
end
- # If the request is authenticated, then the 'node' info will
- # be available; if not, then we use the passed-in key. We rely
- # on our authorization system to determine whether this is allowed.
- name = request.node || request.key
+ # We rely on our authorization system to determine whether the connected
+ # node is allowed to compile the catalog's node referenced by key.
+ # By default the REST authorization system makes sure only the connected node
+ # can compile his catalog.
+ # This allows for instance monitoring systems or puppet-load to check several
+ # node's catalog with only one certificate and a modification to auth.conf
+ # If no key is provided we can only compile the currently connected node.
+ name = request.key || request.node
if node = find_node(name)
return node
end
diff --git a/lib/puppet/indirector/report/yaml.rb b/lib/puppet/indirector/report/yaml.rb
new file mode 100644
index 000000000..bf7bf4fe5
--- /dev/null
+++ b/lib/puppet/indirector/report/yaml.rb
@@ -0,0 +1,11 @@
+require 'puppet/transaction/report'
+require 'puppet/indirector/yaml'
+
+class Puppet::Transaction::Report::Yaml < Puppet::Indirector::Yaml
+ desc "Store last report as a flat file, serialized using YAML."
+
+ # Force report to be saved there
+ def path(name,ext='.yaml')
+ Puppet[:lastrunreport]
+ end
+end
diff --git a/lib/puppet/network/handler/fileserver.rb b/lib/puppet/network/handler/fileserver.rb
index 8844ab990..9abc7ee1a 100755
--- a/lib/puppet/network/handler/fileserver.rb
+++ b/lib/puppet/network/handler/fileserver.rb
@@ -6,6 +6,8 @@ require 'delegate'
require 'sync'
require 'xmlrpc/server'
+require 'puppet/network/handler'
+require 'puppet/network/xmlrpc/server'
require 'puppet/file_serving'
require 'puppet/file_serving/metadata'
require 'puppet/network/handler'
diff --git a/lib/puppet/network/server.rb b/lib/puppet/network/server.rb
index d424b9c4a..e4de07dea 100644
--- a/lib/puppet/network/server.rb
+++ b/lib/puppet/network/server.rb
@@ -32,14 +32,14 @@ class Puppet::Network::Server
# Create a pidfile for our daemon, so we can be stopped and others
# don't try to start.
def create_pidfile
- Puppet::Util.sync(Puppet[:name]).synchronize(Sync::EX) do
+ Puppet::Util.synchronize_on(Puppet[:name],Sync::EX) do
raise "Could not create PID file: #{pidfile}" unless Puppet::Util::Pidlock.new(pidfile).lock
end
end
# Remove the pid file for our daemon.
def remove_pidfile
- Puppet::Util.sync(Puppet[:name]).synchronize(Sync::EX) do
+ Puppet::Util.synchronize_on(Puppet[:name],Sync::EX) do
locker = Puppet::Util::Pidlock.new(pidfile)
locker.unlock or Puppet.err "Could not remove PID file #{pidfile}" if locker.locked?
end
diff --git a/lib/puppet/node/environment.rb b/lib/puppet/node/environment.rb
index 3d55ac1a0..7877b7f73 100644
--- a/lib/puppet/node/environment.rb
+++ b/lib/puppet/node/environment.rb
@@ -124,6 +124,10 @@ class Puppet::Node::Environment
name.to_s
end
+ def to_sym
+ to_s.to_sym
+ end
+
# The only thing we care about when serializing an environment is its
# identity; everything else is ephemeral and should not be stored or
# transmitted.
diff --git a/lib/puppet/parser/ast/collection.rb b/lib/puppet/parser/ast/collection.rb
index 09d5b4eb3..ef36b7143 100644
--- a/lib/puppet/parser/ast/collection.rb
+++ b/lib/puppet/parser/ast/collection.rb
@@ -5,61 +5,44 @@ require 'puppet/parser/collector'
# An object that collects stored objects from the central cache and returns
# them to the current host, yo.
class Puppet::Parser::AST
-class Collection < AST::Branch
- attr_accessor :type, :query, :form
- attr_reader :override
-
- associates_doc
-
- # We return an object that does a late-binding evaluation.
- def evaluate(scope)
- if self.query
- str, code = self.query.safeevaluate scope
- else
- str = code = nil
- end
-
- newcoll = Puppet::Parser::Collector.new(scope, @type, str, code, self.form)
-
- scope.compiler.add_collection(newcoll)
-
- # overrides if any
- # Evaluate all of the specified params.
- if @override
- params = @override.collect do |param|
- param.safeevaluate(scope)
+ class Collection < AST::Branch
+ attr_accessor :type, :query, :form
+ attr_reader :override
+
+ associates_doc
+
+ # We return an object that does a late-binding evaluation.
+ def evaluate(scope)
+ str, code = query && query.safeevaluate(scope)
+
+ resource_type = scope.find_resource_type(@type)
+ newcoll = Puppet::Parser::Collector.new(scope, resource_type.name, str, code, self.form)
+
+ scope.compiler.add_collection(newcoll)
+
+ # overrides if any
+ # Evaluate all of the specified params.
+ if @override
+ params = @override.collect { |param| param.safeevaluate(scope) }
+ newcoll.add_override(
+ :parameters => params,
+ :file => @file,
+ :line => @line,
+ :source => scope.source,
+ :scope => scope
+ )
end
-
- newcoll.add_override(
-
- :parameters => params,
- :file => @file,
- :line => @line,
- :source => scope.source,
-
- :scope => scope
- )
+ newcoll
end
- newcoll
- end
-
- # Handle our parameter ourselves
- def override=(override)
- if override.is_a?(AST::ASTArray)
- @override = override
- else
-
- @override = AST::ASTArray.new(
-
- :line => override.line,
- :file => override.file,
-
- :children => [override]
- )
+ # Handle our parameter ourselves
+ def override=(override)
+ @override = if override.is_a?(AST::ASTArray)
+ override
+ else
+ AST::ASTArray.new(:line => override.line,:file => override.file,:children => [override])
+ end
end
end
-
-end
end
diff --git a/lib/puppet/parser/ast/leaf.rb b/lib/puppet/parser/ast/leaf.rb
index 090d75c4e..fcdd219d7 100644
--- a/lib/puppet/parser/ast/leaf.rb
+++ b/lib/puppet/parser/ast/leaf.rb
@@ -148,12 +148,20 @@ class Puppet::Parser::AST
key.respond_to?(:evaluate) ? key.safeevaluate(scope) : key
end
+ def array_index_or_key(object, key)
+ if object.is_a?(Array)
+ raise Puppet::ParserError, "#{key} is not an integer, but is used as an index of an array" unless key = Puppet::Parser::Scope.number?(key)
+ end
+ key
+ end
+
def evaluate(scope)
object = evaluate_container(scope)
+ accesskey = evaluate_key(scope)
raise Puppet::ParseError, "#{variable} is not an hash or array when accessing it with #{accesskey}" unless object.is_a?(Hash) or object.is_a?(Array)
- object[evaluate_key(scope)]
+ object[array_index_or_key(object, accesskey)]
end
# Assign value to this hashkey or array index
@@ -166,7 +174,7 @@ class Puppet::Parser::AST
end
# assign to hash or array
- object[accesskey] = value
+ object[array_index_or_key(object, accesskey)] = value
end
def to_s
diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb
index b0deac5bc..5807c0bbe 100644
--- a/lib/puppet/parser/functions.rb
+++ b/lib/puppet/parser/functions.rb
@@ -73,8 +73,10 @@ module Puppet::Parser::Functions
def self.function(name)
name = symbolize(name)
- unless functions.include?(name) or functions(Puppet::Node::Environment.root).include?(name)
- autoloader.load(name,Environment.current || Environment.root)
+ @functions.synchronize do
+ unless functions.include?(name) or functions(Puppet::Node::Environment.root).include?(name)
+ autoloader.load(name,Environment.current || Environment.root)
+ end
end
( functions(Environment.root)[name] || functions[name] || {:name => false} )[:name]
diff --git a/lib/puppet/parser/parser_support.rb b/lib/puppet/parser/parser_support.rb
index 16cd0ee0f..746aa0f90 100644
--- a/lib/puppet/parser/parser_support.rb
+++ b/lib/puppet/parser/parser_support.rb
@@ -37,12 +37,12 @@ class Puppet::Parser::Parser
# Create an AST object, and automatically add the file and line information if
# available.
def ast(klass, hash = {})
- klass.new ast_context(klass.use_docs).merge(hash)
+ klass.new ast_context(klass.use_docs, hash[:line]).merge(hash)
end
- def ast_context(include_docs = false)
+ def ast_context(include_docs = false, ast_line = nil)
result = {
- :line => lexer.line,
+ :line => ast_line || lexer.line,
:file => lexer.file
}
result[:doc] = lexer.getcomment(result[:line]) if include_docs
diff --git a/lib/puppet/parser/templatewrapper.rb b/lib/puppet/parser/templatewrapper.rb
index 73a4ad8aa..6864aa1a9 100644
--- a/lib/puppet/parser/templatewrapper.rb
+++ b/lib/puppet/parser/templatewrapper.rb
@@ -1,6 +1,7 @@
# A simple wrapper for templates, so they don't have full access to
# the scope objects.
require 'puppet/parser/files'
+require 'erb'
class Puppet::Parser::TemplateWrapper
attr_writer :scope
diff --git a/lib/puppet/provider.rb b/lib/puppet/provider.rb
index af792b623..4456feb4e 100644
--- a/lib/puppet/provider.rb
+++ b/lib/puppet/provider.rb
@@ -12,7 +12,7 @@ class Puppet::Provider
Puppet::Util.logmethods(self, true)
class << self
- # Include the util module so we have access to things like 'binary'
+ # Include the util module so we have access to things like 'which'
include Puppet::Util, Puppet::Util::Docs
include Puppet::Util::Logging
attr_accessor :name
@@ -43,7 +43,7 @@ class Puppet::Provider
raise Puppet::DevError, "No command #{name} defined for provider #{self.name}"
end
- binary(command)
+ which(command)
end
# Define commands that are not optional.
diff --git a/lib/puppet/provider/confine/exists.rb b/lib/puppet/provider/confine/exists.rb
index 085118b2a..09f94dfd9 100644
--- a/lib/puppet/provider/confine/exists.rb
+++ b/lib/puppet/provider/confine/exists.rb
@@ -6,10 +6,7 @@ class Puppet::Provider::Confine::Exists < Puppet::Provider::Confine
end
def pass?(value)
- if for_binary?
- return false unless value = binary(value)
- end
- value and FileTest.exist?(value)
+ value && (for_binary? ? which(value) : FileTest.exist?(value))
end
def message(value)
diff --git a/lib/puppet/provider/host/parsed.rb b/lib/puppet/provider/host/parsed.rb
index 4f15eff3f..a303c4bcf 100644
--- a/lib/puppet/provider/host/parsed.rb
+++ b/lib/puppet/provider/host/parsed.rb
@@ -8,66 +8,36 @@ else
end
- Puppet::Type.type(:host).provide(
- :parsed,
- :parent => Puppet::Provider::ParsedFile,
- :default_target => hosts,
-
- :filetype => :flat
-) do
+Puppet::Type.type(:host).provide(:parsed,:parent => Puppet::Provider::ParsedFile,
+ :default_target => hosts,:filetype => :flat) do
confine :exists => hosts
text_line :comment, :match => /^#/
text_line :blank, :match => /^\s*$/
- record_line :parsed, :fields => %w{ip name host_aliases},
- :optional => %w{host_aliases},
- :rts => true do |line|
- hash = {}
- if line.sub!(/^(\S+)\s+(\S+)\s*/, '')
- hash[:ip] = $1
- hash[:name] = $2
-
- if line.empty?
- hash[:host_aliases] = []
+ record_line :parsed, :fields => %w{ip name host_aliases comment},
+ :optional => %w{host_aliases comment},
+ :match => /^(\S+)\s+(\S+)\s*(.*?)?(?:\s*#\s*(.*))?$/,
+ :post_parse => proc { |hash|
+ # An absent comment should match "comment => ''"
+ hash[:comment] = '' if hash[:comment].nil? or hash[:comment] == :absent
+ unless hash[:host_aliases].nil? or hash[:host_aliases] == :absent
+ hash[:host_aliases] = hash[:host_aliases].split(/\s+/)
else
- line.sub!(/\s*/, '')
- line.sub!(/^([^#]+)\s*/) do |value|
- aliases = $1
- unless aliases =~ /^\s*$/
- hash[:host_aliases] = aliases.split(/\s+/)
- end
-
- ""
- end
+ hash[:host_aliases] = []
end
- else
- raise Puppet::Error, "Could not match '#{line}'"
- end
-
- hash[:host_aliases] = [] if hash[:host_aliases] == ""
-
- return hash
- end
-
- # Convert the current object into a host-style string.
- def self.to_line(hash)
- return super unless hash[:record_type] == :parsed
- [:ip, :name].each do |n|
- raise ArgumentError, "#{n} is a required attribute for hosts" unless hash[n] and hash[n] != :absent
- end
-
- str = "#{hash[:ip]}\t#{hash[:name]}"
-
- if hash.include? :host_aliases and !hash[:host_aliases].empty?
- if hash[:host_aliases].is_a? Array
+ },
+ :to_line => proc { |hash|
+ [:ip, :name].each do |n|
+ raise ArgumentError, "#{n} is a required attribute for hosts" unless hash[n] and hash[n] != :absent
+ end
+ str = "#{hash[:ip]}\t#{hash[:name]}"
+ if hash.include? :host_aliases and !hash[:host_aliases].empty?
str += "\t#{hash[:host_aliases].join("\t")}"
- else
- raise ArgumentError, "Host aliases must be specified as an array"
end
- end
-
- str
- end
+ if hash.include? :comment and !hash[:comment].empty?
+ str += "\t# #{hash[:comment]}"
+ end
+ str
+ }
end
-
diff --git a/lib/puppet/provider/maillist/mailman.rb b/lib/puppet/provider/maillist/mailman.rb
index 4fdc20a69..633642af7 100755
--- a/lib/puppet/provider/maillist/mailman.rb
+++ b/lib/puppet/provider/maillist/mailman.rb
@@ -2,11 +2,11 @@ require 'puppet/provider/parsedfile'
Puppet::Type.type(:maillist).provide(:mailman) do
if [ "CentOS", "RedHat", "Fedora" ].any? { |os| Facter.value(:operatingsystem) == os }
- commands :list_lists => "/usr/lib/mailman/bin/list_lists", :rmlist => "/usr/lib/mailman/bin/rmlist", :newlist => "/usr/lib/mailman/bin/newlist"
+ commands :list_lists => "/usr/lib/mailman/bin/list_lists --bare", :rmlist => "/usr/lib/mailman/bin/rmlist", :newlist => "/usr/lib/mailman/bin/newlist"
commands :mailman => "/usr/lib/mailman/mail/mailman"
else
# This probably won't work for non-Debian installs, but this path is sure not to be in the PATH.
- commands :list_lists => "list_lists", :rmlist => "rmlist", :newlist => "newlist"
+ commands :list_lists => "list_lists --bare", :rmlist => "rmlist", :newlist => "newlist"
commands :mailman => "/var/lib/mailman/mail/mailman"
end
@@ -14,10 +14,9 @@ Puppet::Type.type(:maillist).provide(:mailman) do
# Return a list of existing mailman instances.
def self.instances
- list_lists.split("\n").reject { |line| line.include?("matching mailing lists") }.collect do |line|
- name, description = line.sub(/^\s+/, '').sub(/\s+$/, '').split(/\s+-\s+/)
- description = :absent if description.include?("no description available")
- new(:ensure => :present, :name => name, :description => description)
+ list_lists.split("\n").collect do |line|
+ name = line.strip
+ new(:ensure => :present, :name => name)
end
end
diff --git a/lib/puppet/provider/mount.rb b/lib/puppet/provider/mount.rb
index 393ae56c9..8c7b24bd4 100644
--- a/lib/puppet/provider/mount.rb
+++ b/lib/puppet/provider/mount.rb
@@ -41,7 +41,7 @@ module Puppet::Provider::Mount
case platform
when "Darwin"
line =~ / on #{name} / or line =~ %r{ on /private/var/automount#{name}}
- when "Solaris"
+ when "Solaris", "HP-UX"
line =~ /^#{name} on /
else
line =~ / on #{name} /
diff --git a/lib/puppet/provider/package/openbsd.rb b/lib/puppet/provider/package/openbsd.rb
index 22df14d62..bb07d894a 100755
--- a/lib/puppet/provider/package/openbsd.rb
+++ b/lib/puppet/provider/package/openbsd.rb
@@ -2,7 +2,6 @@ require 'puppet/provider/package'
# Packaging on OpenBSD. Doesn't work anywhere else that I know of.
Puppet::Type.type(:package).provide :openbsd, :parent => Puppet::Provider::Package do
- include Puppet::Util::Execution
desc "OpenBSD's form of `pkg_add` support."
commands :pkginfo => "pkg_info", :pkgadd => "pkg_add", :pkgdelete => "pkg_delete"
@@ -61,18 +60,15 @@ Puppet::Type.type(:package).provide :openbsd, :parent => Puppet::Provider::Packa
"You must specify a package source for BSD packages"
end
- old_ensure = @resource[:ensure]
-
- if @resource[:source] =~ /\/$/
- withenv :PKG_PATH => @resource[:source] do
- @resource[:ensure] = old_ensure if (@resource[:ensure] = get_version) == nil
- full_name = [ @resource[:name], @resource[:ensure], @resource[:flavor] ]
- pkgadd full_name.join('-').chomp('-')
- end
+ if @resource[:source][-1,1] == ::File::PATH_SEPARATOR
+ e_vars = { :PKG_PATH => @resource[:source] }
+ full_name = [ @resource[:name], get_version || @resource[:ensure], @resource[:flavor] ].join('-').chomp('-')
else
- pkgadd @resource[:source]
+ e_vars = {}
+ full_name = @resource[:source]
end
+ Puppet::Util::Execution::withenv(e_vars) { pkgadd full_name }
end
def get_version
diff --git a/lib/puppet/provider/package/yum.rb b/lib/puppet/provider/package/yum.rb
index fcda5ba8c..6ed966fbd 100755
--- a/lib/puppet/provider/package/yum.rb
+++ b/lib/puppet/provider/package/yum.rb
@@ -1,3 +1,4 @@
+require 'puppet/util/package'
Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
desc "Support via `yum`."
@@ -52,6 +53,7 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
should = @resource.should(:ensure)
self.debug "Ensuring => #{should}"
wanted = @resource[:name]
+ operation = :install
# XXX: We don't actually deal with epochs here.
case should
@@ -61,9 +63,14 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
else
# Add the package version
wanted += "-#{should}"
+ is = self.query
+ if is && Puppet::Util::Package.versioncmp(should, is[:ensure]) < 0
+ self.debug "Downgrading package #{@resource[:name]} from version #{is[:ensure]} to #{should}"
+ operation = :downgrade
+ end
end
- output = yum "-d", "0", "-e", "0", "-y", :install, wanted
+ output = yum "-d", "0", "-e", "0", "-y", operation, wanted
is = self.query
raise Puppet::Error, "Could not find package #{self.name}" unless is
diff --git a/lib/puppet/provider/service/freebsd.rb b/lib/puppet/provider/service/freebsd.rb
index c75c3c9ab..f8c7134f0 100644
--- a/lib/puppet/provider/service/freebsd.rb
+++ b/lib/puppet/provider/service/freebsd.rb
@@ -18,6 +18,9 @@ Puppet::Type.type(:service).provide :freebsd, :parent => :init do
def rcvar
rcvar = execute([self.initscript, :rcvar], :failonfail => true, :squelch => false)
rcvar = rcvar.split("\n")
+ rcvar.delete_if {|str| str =~ /^#\s*$/}
+ rcvar[1] = rcvar[1].gsub(/^\$/, '')
+ rcvar
end
# Extract service name
@@ -44,7 +47,7 @@ Puppet::Type.type(:service).provide :freebsd, :parent => :init do
def rcvar_value
value = self.rcvar[1]
self.error("No rcvar value found in rcvar") if value.nil?
- value = value.gsub!(/(.*)_enable=\"?(.*)\"?/, '\2')
+ value = value.gsub!(/(.*)_enable="?(\w+)"?/, '\2')
self.error("rcvar value is empty") if value.nil?
self.debug("rcvar value is #{value}")
value
diff --git a/lib/puppet/provider/user/user_role_add.rb b/lib/puppet/provider/user/user_role_add.rb
index caca1ef88..2377f9e65 100644
--- a/lib/puppet/provider/user/user_role_add.rb
+++ b/lib/puppet/provider/user/user_role_add.rb
@@ -156,11 +156,11 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd, :source =>
shadow_entry[1] if shadow_entry
end
- def min_age
+ def password_min_age
shadow_entry ? shadow_entry[3] : :absent
end
- def max_age
+ def password_max_age
shadow_entry ? shadow_entry[4] : :absent
end
diff --git a/lib/puppet/provider/user/useradd.rb b/lib/puppet/provider/user/useradd.rb
index 5a163f35a..ba406cc63 100644
--- a/lib/puppet/provider/user/useradd.rb
+++ b/lib/puppet/provider/user/useradd.rb
@@ -78,7 +78,7 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
end
end
- def min_age
+ def password_min_age
if Puppet.features.libshadow?
if ent = Shadow::Passwd.getspnam(@resource.name)
return ent.sp_min
@@ -87,7 +87,7 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
:absent
end
- def max_age
+ def password_max_age
if Puppet.features.libshadow?
if ent = Shadow::Passwd.getspnam(@resource.name)
return ent.sp_max
diff --git a/lib/puppet/rails.rb b/lib/puppet/rails.rb
index c2d492fdd..74805bb6f 100644
--- a/lib/puppet/rails.rb
+++ b/lib/puppet/rails.rb
@@ -52,21 +52,17 @@ module Puppet::Rails
args[:port] = Puppet[:dbport] unless Puppet[:dbport].to_s.empty?
args[:username] = Puppet[:dbuser] unless Puppet[:dbuser].to_s.empty?
args[:password] = Puppet[:dbpassword] unless Puppet[:dbpassword].to_s.empty?
+ args[:pool] = Puppet[:dbconnections].to_i unless Puppet[:dbconnections].to_i <= 0
args[:database] = Puppet[:dbname]
args[:reconnect]= true
socket = Puppet[:dbsocket]
args[:socket] = socket unless socket.to_s.empty?
-
- connections = Puppet[:dbconnections].to_i
- args[:pool] = connections if connections > 0
when "oracle_enhanced":
args[:database] = Puppet[:dbname] unless Puppet[:dbname].to_s.empty?
args[:username] = Puppet[:dbuser] unless Puppet[:dbuser].to_s.empty?
args[:password] = Puppet[:dbpassword] unless Puppet[:dbpassword].to_s.empty?
-
- connections = Puppet[:dbconnections].to_i
- args[:pool] = connections if connections > 0
+ args[:pool] = Puppet[:dbconnections].to_i unless Puppet[:dbconnections].to_i <= 0
else
raise ArgumentError, "Invalid db adapter #{adapter}"
end
diff --git a/lib/puppet/rails/host.rb b/lib/puppet/rails/host.rb
index 986cebd0a..b9dea2a3d 100644
--- a/lib/puppet/rails/host.rb
+++ b/lib/puppet/rails/host.rb
@@ -16,16 +16,6 @@ class Puppet::Rails::Host < ActiveRecord::Base
belongs_to :source_file
has_many :resources, :dependent => :destroy, :class_name => "Puppet::Rails::Resource"
- # If the host already exists, get rid of its objects
- def self.clean(host)
- if obj = self.find_by_name(host)
- obj.rails_objects.clear
- return obj
- else
- return nil
- end
- end
-
def self.from_puppet(node)
host = find_by_name(node.name) || new(:name => node.name)
@@ -38,63 +28,6 @@ class Puppet::Rails::Host < ActiveRecord::Base
host
end
- # Store our host in the database.
- def self.store(node, resources)
- args = {}
-
- host = nil
- railsmark "Stored node" do
- transaction do
- #unless host = find_by_name(name)
-
- debug_benchmark("Searched for host")do
- unless host = find_by_name(node.name)
- host = new(:name => node.name)
- end
- end
- if ip = node.parameters["ipaddress"]
- host.ip = ip
- end
-
- if env = node.environment
- host.environment = env
- end
-
- # Store the facts into the database.
- host.merge_facts(node.parameters)
-
- debug_benchmark("Handled resources") {
- host.merge_resources(resources)
- }
-
- host.last_compile = Time.now
-
- debug_benchmark("Saved host") {
- host.save
- }
- end
-
- end
-
- # This only runs if time debugging is enabled.
- write_benchmarks
-
- host
- end
-
- # Return the value of a fact.
- def fact(name)
-
- if fv = self.fact_values.find(
- :all, :include => :fact_name,
-
- :conditions => "fact_names.name = '#{name}'")
- return fv
- else
- return nil
- end
- end
-
# returns a hash of fact_names.name => [ fact_values ] for this host.
# Note that 'fact_values' is actually a list of the value instances, not
# just actual values.
@@ -305,11 +238,6 @@ class Puppet::Rails::Host < ActiveRecord::Base
end
end
- def update_connect_time
- self.last_connect = Time.now
- save
- end
-
def to_puppet
node = Puppet::Node.new(self.name)
{"ip" => "ipaddress", "environment" => "environment"}.each do |myparam, itsparam|
diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb
index 7dea270e8..4f0d50750 100644
--- a/lib/puppet/resource.rb
+++ b/lib/puppet/resource.rb
@@ -80,6 +80,18 @@ class Puppet::Resource
end
end
+ def yaml_property_munge(x)
+ case x
+ when Hash
+ x.inject({}) { |h,kv|
+ k,v = kv
+ h[k] = self.class.value_to_pson_data(v)
+ h
+ }
+ else self.class.value_to_pson_data(x)
+ end
+ end
+
def to_pson(*args)
to_pson_data_hash.to_pson(*args)
end
diff --git a/lib/puppet/simple_graph.rb b/lib/puppet/simple_graph.rb
index 55b39fadf..6d153b46d 100644
--- a/lib/puppet/simple_graph.rb
+++ b/lib/puppet/simple_graph.rb
@@ -7,123 +7,45 @@ require 'set'
# A hopefully-faster graph class to replace the use of GRATR.
class Puppet::SimpleGraph
- # An internal class for handling a vertex's edges.
- class VertexWrapper
- attr_accessor :in, :out, :vertex
-
- # Remove all references to everything.
- def clear
- @adjacencies[:in].clear
- @adjacencies[:out].clear
- @vertex = nil
- end
-
- def initialize(vertex)
- @vertex = vertex
- @adjacencies = {:in => {}, :out => {}}
- end
-
- # Find adjacent vertices or edges.
- def adjacent(options)
- direction = options[:direction] || :out
- options[:type] ||= :vertices
-
- return send(direction.to_s + "_edges") if options[:type] == :edges
-
- @adjacencies[direction].keys.reject { |vertex| @adjacencies[direction][vertex].empty? }
- end
-
- # Add an edge to our list.
- def add_edge(direction, edge)
- opposite_adjacencies(direction, edge) << edge
- end
-
- # Return all known edges.
- def edges
- in_edges + out_edges
- end
-
- # Test whether we share an edge with a given vertex.
- def has_edge?(direction, vertex)
- return(vertex_adjacencies(direction, vertex).length > 0 ? true : false)
- end
-
- # Create methods for returning the degree and edges.
- [:in, :out].each do |direction|
- # LAK:NOTE If you decide to create methods for directly
- # testing the degree, you'll have to get the values and flatten
- # the results -- you might have duplicate edges, which can give
- # a false impression of what the degree is. That's just
- # as expensive as just getting the edge list, so I've decided
- # to only add this method.
- define_method("#{direction}_edges") do
- @adjacencies[direction].values.inject([]) { |total, adjacent| total += adjacent.to_a; total }
- end
- end
-
- # The other vertex in the edge.
- def other_vertex(direction, edge)
- case direction
- when :in; edge.source
- else
- edge.target
- end
- end
-
- # Remove an edge from our list. Assumes that we've already checked
- # that the edge is valid.
- def remove_edge(direction, edge)
- opposite_adjacencies(direction, edge).delete(edge)
- end
-
- def to_s
- vertex.to_s
- end
-
- private
-
- # These methods exist so we don't need a Hash with a default proc.
-
- # Look up the adjacencies for a vertex at the other end of an
- # edge.
- def opposite_adjacencies(direction, edge)
- opposite_vertex = other_vertex(direction, edge)
- vertex_adjacencies(direction, opposite_vertex)
- end
-
- # Look up the adjacencies for a given vertex.
- def vertex_adjacencies(direction, vertex)
- @adjacencies[direction][vertex] ||= Set.new
- @adjacencies[direction][vertex]
- end
- end
-
+ #
+ # All public methods of this class must maintain (assume ^ ensure) the following invariants, where "=~=" means
+ # equiv. up to order:
+ #
+ # @in_to.keys =~= @out_to.keys =~= all vertices
+ # @in_to.values.collect { |x| x.values }.flatten =~= @out_from.values.collect { |x| x.values }.flatten =~= all edges
+ # @in_to[v1][v2] =~= @out_from[v2][v1] =~= all edges from v1 to v2
+ # @in_to [v].keys =~= vertices with edges leading to v
+ # @out_from[v].keys =~= vertices with edges leading from v
+ # no operation may shed reference loops (for gc)
+ # recursive operation must scale with the depth of the spanning trees, or better (e.g. no recursion over the set
+ # of all vertices, etc.)
+ #
+ # This class is intended to be used with DAGs. However, if the
+ # graph has a cycle, it will not cause non-termination of any of the
+ # algorithms. The topsort method detects and reports cycles.
+ #
def initialize
- @vertices = {}
- @edges = []
+ @in_to = {}
+ @out_from = {}
+ @upstream_from = {}
+ @downstream_from = {}
end
# Clear our graph.
def clear
- @vertices.each { |vertex, wrapper| wrapper.clear }
- @vertices.clear
- @edges.clear
- end
-
- # Which resources a given resource depends upon.
- def dependents(resource)
- tree_from_vertex(resource).keys
+ @in_to.clear
+ @out_from.clear
+ @upstream_from.clear
+ @downstream_from.clear
end
# Which resources depend upon the given resource.
def dependencies(resource)
- # Cache the reversal graph, because it's somewhat expensive
- # to create.
- @reversal ||= reversal
- # Strangely, it's significantly faster to search a reversed
- # tree in the :out direction than to search a normal tree
- # in the :in direction.
- @reversal.tree_from_vertex(resource, :out).keys
+ vertex?(resource) ? upstream_from_vertex(resource).keys : []
+ end
+
+ def dependents(resource)
+ vertex?(resource) ? downstream_from_vertex(resource).keys : []
end
# Whether our graph is directed. Always true. Used to produce dot files.
@@ -133,8 +55,7 @@ class Puppet::SimpleGraph
# Determine all of the leaf nodes below a given vertex.
def leaves(vertex, direction = :out)
- tree = tree_from_vertex(vertex, direction)
- l = tree.keys.find_all { |c| adjacent(c, :direction => direction).empty? }
+ tree_from_vertex(vertex, direction).keys.find_all { |c| adjacent(c, :direction => direction).empty? }
end
# Collect all of the edges that the passed events match. Returns
@@ -149,9 +70,7 @@ class Puppet::SimpleGraph
# Get all of the edges that this vertex should forward events
# to, which is the same thing as saying all edges directly below
# This vertex in the graph.
- adjacent(source, :direction => :out, :type => :edges).find_all do |edge|
- edge.match?(event.name)
- end
+ @out_from[source].values.flatten.find_all { |edge| edge.match?(event.name) }
end
# Return a reversed version of this graph.
@@ -159,20 +78,50 @@ class Puppet::SimpleGraph
result = self.class.new
vertices.each { |vertex| result.add_vertex(vertex) }
edges.each do |edge|
- newedge = edge.class.new(edge.target, edge.source, edge.label)
- result.add_edge(newedge)
+ result.add_edge edge.class.new(edge.target, edge.source, edge.label)
end
result
end
# Return the size of the graph.
def size
- @vertices.length
+ vertices.size
end
- # Return the graph as an array.
def to_a
- @vertices.keys
+ vertices
+ end
+
+ # Provide a topological sort with cycle reporting
+ def topsort_with_cycles
+ degree = {}
+ zeros = []
+ result = []
+
+ # Collect each of our vertices, with the number of in-edges each has.
+ vertices.each do |v|
+ edges = @in_to[v].dup
+ zeros << v if edges.empty?
+ degree[v] = edges
+ end
+
+ # Iterate over each 0-degree vertex, decrementing the degree of
+ # each of its out-edges.
+ while v = zeros.pop
+ result << v
+ @out_from[v].each { |v2,es|
+ degree[v2].delete(v)
+ zeros << v2 if degree[v2].empty?
+ }
+ end
+
+ # If we have any vertices left with non-zero in-degrees, then we've found a cycle.
+ if cycles = degree.values.reject { |ns| ns.empty? } and cycles.length > 0
+ message = cycles.collect { |edges| '('+edges.collect { |e| e.to_s }.join(", ")+')' }.join(", ")
+ raise Puppet::Error, "Found dependency cycles in the following relationships: #{message}; try using the '--graph' option and open the '.dot' files in OmniGraffle or GraphViz"
+ end
+
+ result
end
# Provide a topological sort.
@@ -182,26 +131,24 @@ class Puppet::SimpleGraph
result = []
# Collect each of our vertices, with the number of in-edges each has.
- @vertices.each do |name, wrapper|
- edges = wrapper.in_edges
- zeros << wrapper if edges.length == 0
- degree[wrapper.vertex] = edges
+ vertices.each do |v|
+ edges = @in_to[v]
+ zeros << v if edges.empty?
+ degree[v] = edges.length
end
# Iterate over each 0-degree vertex, decrementing the degree of
# each of its out-edges.
- while wrapper = zeros.pop
- result << wrapper.vertex
- wrapper.out_edges.each do |edge|
- degree[edge.target].delete(edge)
- zeros << @vertices[edge.target] if degree[edge.target].length == 0
- end
+ while v = zeros.pop
+ result << v
+ @out_from[v].each { |v2,es|
+ zeros << v2 if (degree[v2] -= 1) == 0
+ }
end
# If we have any vertices left with non-zero in-degrees, then we've found a cycle.
- if cycles = degree.find_all { |vertex, edges| edges.length > 0 } and cycles.length > 0
- message = cycles.collect { |vertex, edges| edges.collect { |e| e.to_s }.join(", ") }.join(", ")
- raise Puppet::Error, "Found dependency cycles in the following relationships: #{message}; try using the '--graph' option and open the '.dot' files in OmniGraffle or GraphViz"
+ if cycles = degree.values.reject { |ns| ns == 0 } and cycles.length > 0
+ topsort_with_cycles
end
result
@@ -209,103 +156,80 @@ class Puppet::SimpleGraph
# Add a new vertex to the graph.
def add_vertex(vertex)
- @reversal = nil
- return false if vertex?(vertex)
- setup_vertex(vertex)
- true # don't return the VertexWrapper instance.
+ @in_to[vertex] ||= {}
+ @out_from[vertex] ||= {}
end
# Remove a vertex from the graph.
- def remove_vertex!(vertex)
- return nil unless vertex?(vertex)
- @vertices[vertex].edges.each { |edge| remove_edge!(edge) }
- @edges -= @vertices[vertex].edges
- @vertices[vertex].clear
- @vertices.delete(vertex)
+ def remove_vertex!(v)
+ return unless vertex?(v)
+ @upstream_from.clear
+ @downstream_from.clear
+ (@in_to[v].values+@out_from[v].values).flatten.each { |e| remove_edge!(e) }
+ @in_to.delete(v)
+ @out_from.delete(v)
end
# Test whether a given vertex is in the graph.
- def vertex?(vertex)
- @vertices.include?(vertex)
+ def vertex?(v)
+ @in_to.include?(v)
end
# Return a list of all vertices.
def vertices
- @vertices.keys
+ @in_to.keys
end
# Add a new edge. The graph user has to create the edge instance,
# since they have to specify what kind of edge it is.
- def add_edge(source, target = nil, label = nil)
- @reversal = nil
- if target
- edge = Puppet::Relationship.new(source, target, label)
- else
- edge = source
- end
- [edge.source, edge.target].each { |vertex| setup_vertex(vertex) unless vertex?(vertex) }
- @vertices[edge.source].add_edge :out, edge
- @vertices[edge.target].add_edge :in, edge
- @edges << edge
- true
+ def add_edge(e,*a)
+ return add_relationship(e,*a) unless a.empty?
+ @upstream_from.clear
+ @downstream_from.clear
+ add_vertex(e.source)
+ add_vertex(e.target)
+ @in_to[ e.target][e.source] ||= []; @in_to[ e.target][e.source] |= [e]
+ @out_from[e.source][e.target] ||= []; @out_from[e.source][e.target] |= [e]
end
- # Find a matching edge. Note that this only finds the first edge,
- # not all of them or whatever.
- def edge(source, target)
- @edges.each_with_index { |test_edge, index| return test_edge if test_edge.source == source and test_edge.target == target }
+ def add_relationship(source, target, label = nil)
+ add_edge Puppet::Relationship.new(source, target, label)
end
- def edge_label(source, target)
- return nil unless edge = edge(source, target)
- edge.label
+ # Find all matching edges.
+ def edges_between(source, target)
+ (@out_from[source] || {})[target] || []
end
# Is there an edge between the two vertices?
def edge?(source, target)
- return false unless vertex?(source) and vertex?(target)
-
- @vertices[source].has_edge?(:out, target)
+ vertex?(source) and vertex?(target) and @out_from[source][target]
end
def edges
- @edges.dup
+ @in_to.values.collect { |x| x.values }.flatten
end
- # Remove an edge from our graph.
- def remove_edge!(edge)
- @vertices[edge.source].remove_edge(:out, edge)
- @vertices[edge.target].remove_edge(:in, edge)
-
- @edges.delete(edge)
- nil
+ def each_edge
+ @in_to.each { |t,ns| ns.each { |s,es| es.each { |e| yield e }}}
end
- # Find adjacent edges.
- def adjacent(vertex, options = {})
- return [] unless wrapper = @vertices[vertex]
- wrapper.adjacent(options)
+ # Remove an edge from our graph.
+ def remove_edge!(e)
+ if edge?(e.source,e.target)
+ @upstream_from.clear
+ @downstream_from.clear
+ @in_to [e.target].delete e.source if (@in_to [e.target][e.source] -= [e]).empty?
+ @out_from[e.source].delete e.target if (@out_from[e.source][e.target] -= [e]).empty?
+ end
end
- private
-
- # An internal method that skips the validation, so we don't have
- # duplicate validation calls.
- def setup_vertex(vertex)
- @vertices[vertex] = VertexWrapper.new(vertex)
+ # Find adjacent edges.
+ def adjacent(v, options = {})
+ return [] unless ns = (options[:direction] == :in) ? @in_to[v] : @out_from[v]
+ (options[:type] == :edges) ? ns.values.flatten : ns.keys
end
-
- public
-
-# # For some reason, unconnected vertices do not show up in
-# # this graph.
-# def to_jpg(path, name)
-# gv = vertices
-# Dir.chdir(path) do
-# induced_subgraph(gv).write_to_graphic_file('jpg', name)
-# end
-# end
-
+
# Take container information from another graph and use it
# to replace any container vertices with their respective leaves.
# This creates direct relationships where there were previously
@@ -381,6 +305,26 @@ class Puppet::SimpleGraph
predecessor
end
+ def downstream_from_vertex(v)
+ return @downstream_from[v] if @downstream_from[v]
+ result = @downstream_from[v] = {}
+ @out_from[v].keys.each do |node|
+ result[node] = 1
+ result.update(downstream_from_vertex(node))
+ end
+ result
+ end
+
+ def upstream_from_vertex(v)
+ return @upstream_from[v] if @upstream_from[v]
+ result = @upstream_from[v] = {}
+ @in_to[v].keys.each do |node|
+ result[node] = 1
+ result.update(upstream_from_vertex(node))
+ end
+ result
+ end
+
# LAK:FIXME This is just a paste of the GRATR code with slight modifications.
# Return a DOT::DOTDigraph for directed graphs or a DOT::DOTSubgraph for an
@@ -422,18 +366,6 @@ class Puppet::SimpleGraph
system('dotty', dotfile)
end
- # Use +dot+ to create a graphical representation of the graph. Returns the
- # filename of the graphics file.
- def write_to_graphic_file (fmt='png', dotfile='graph')
- src = dotfile + '.dot'
- dot = dotfile + '.' + fmt
-
- File.open(src, 'w') {|f| f << self.to_dot << "\n"}
-
- system( "dot -T#{fmt} #{src} -o #{dot}" )
- dot
- end
-
# Produce the graph files if requested.
def write_graph(name)
return unless Puppet[:graph]
@@ -445,4 +377,73 @@ class Puppet::SimpleGraph
f.puts to_dot("name" => name.to_s.capitalize)
}
end
+
+ # This flag may be set to true to use the new YAML serialzation
+ # format (where @vertices is a simple list of vertices rather than a
+ # list of VertexWrapper objects). Deserialization supports both
+ # formats regardless of the setting of this flag.
+ class << self
+ attr_accessor :use_new_yaml_format
+ end
+ self.use_new_yaml_format = false
+
+ # Stub class to allow graphs to be represented in YAML using the old
+ # (version 2.6) format.
+ class VertexWrapper
+ attr_reader :vertex, :adjacencies
+ def initialize(vertex, adjacencies)
+ @vertex = vertex
+ @adjacencies = adjacencies
+ end
+ end
+
+ # instance_variable_get is used by Object.to_zaml to get instance
+ # variables. Override it so that we can simulate the presence of
+ # instance variables @edges and @vertices for serialization.
+ def instance_variable_get(v)
+ case v.to_s
+ when '@edges' then
+ edges
+ when '@vertices' then
+ if self.class.use_new_yaml_format
+ vertices
+ else
+ result = {}
+ vertices.each do |vertex|
+ adjacencies = {}
+ [:in, :out].each do |direction|
+ adjacencies[direction] = {}
+ adjacent(vertex, :direction => direction, :type => :edges).each do |edge|
+ other_vertex = direction == :in ? edge.source : edge.target
+ (adjacencies[direction][other_vertex] ||= Set.new).add(edge)
+ end
+ end
+ result[vertex] = Puppet::SimpleGraph::VertexWrapper.new(vertex, adjacencies)
+ end
+ result
+ end
+ else
+ super(v)
+ end
+ end
+
+ def to_yaml_properties
+ other_vars = instance_variables.reject { |v| %w{@in_to @out_from @upstream_from @downstream_from}.include?(v) }
+ (other_vars + %w{@vertices @edges}).sort.uniq
+ end
+
+ def yaml_initialize(tag, var)
+ initialize()
+ vertices = var.delete('vertices')
+ edges = var.delete('edges')
+ if vertices.is_a?(Hash)
+ # Support old (2.6) format
+ vertices = vertices.keys
+ end
+ vertices.each { |v| add_vertex(v) }
+ edges.each { |e| add_edge(e) }
+ var.each do |varname, value|
+ instance_variable_set("@#{varname}", value)
+ end
+ end
end
diff --git a/lib/puppet/transaction/report.rb b/lib/puppet/transaction/report.rb
index e6d1e0528..1d3091428 100644
--- a/lib/puppet/transaction/report.rb
+++ b/lib/puppet/transaction/report.rb
@@ -62,30 +62,49 @@ class Puppet::Transaction::Report
host
end
- # Provide a summary of this report.
+ # Provide a human readable textual summary of this report.
def summary
+ report = raw_summary
+
ret = ""
+ report.keys.sort { |a,b| a.to_s <=> b.to_s }.each do |key|
+ ret += "#{Puppet::Util::Metric.labelize(key)}:\n"
- @metrics.sort { |a,b| a[1].label <=> b[1].label }.each do |name, metric|
- ret += "#{metric.label}:\n"
- metric.values.sort { |a,b|
+ report[key].keys.sort { |a,b|
# sort by label
- if a[0] == :total
+ if a == :total
1
- elsif b[0] == :total
+ elsif b == :total
-1
else
- a[1] <=> b[1]
+ report[key][a].to_s <=> report[key][b].to_s
end
- }.each do |name, label, value|
+ }.each do |label|
+ value = report[key][label]
next if value == 0
value = "%0.2f" % value if value.is_a?(Float)
- ret += " %15s %s\n" % [label + ":", value]
+ ret += " %15s %s\n" % [Puppet::Util::Metric.labelize(label) + ":", value]
end
end
ret
end
+ # Provide a raw hash summary of this report.
+ def raw_summary
+ report = {}
+
+ @metrics.each do |name, metric|
+ key = metric.name.to_s
+ report[key] = {}
+ metric.values.each do |name, label, value|
+ report[key][name.to_s] = value
+ end
+ report[key]["total"] = 0 unless key == "time" or report[key].include?("total")
+ end
+ (report["time"] ||= {})["last_run"] = Time.now.tv_sec
+ report
+ end
+
# Based on the contents of this report's metrics, compute a single number
# that represents the report. The resulting number is a bitmask where
# individual bits represent the presence of different metrics.
@@ -103,7 +122,6 @@ class Puppet::Transaction::Report
resource_statuses.each do |name, status|
metrics[:total] += status.change_count if status.change_count
end
-
add_metric(:changes, metrics)
end
@@ -124,7 +142,6 @@ class Puppet::Transaction::Report
metrics[:total] = resource_statuses.length
resource_statuses.each do |name, status|
-
Puppet::Resource::Status::STATES.each do |state|
metrics[state] += 1 if status.send(state)
end
diff --git a/lib/puppet/type/exec.rb b/lib/puppet/type/exec.rb
index dd57ec231..606888c75 100755
--- a/lib/puppet/type/exec.rb
+++ b/lib/puppet/type/exec.rb
@@ -553,13 +553,7 @@ module Puppet
if self[:path]
if Puppet.features.posix? and !File.exists?(exe)
withenv :PATH => self[:path].join(File::PATH_SEPARATOR) do
- path = %x{which #{exe}}.chomp
- if path == ""
- raise ArgumentError,
- "Could not find command '#{exe}'"
- else
- exe = path
- end
+ exe = which(exe) || raise(ArgumentError,"Could not find command '#{exe}'")
end
elsif Puppet.features.microsoft_windows? and !File.exists?(exe)
self[:path].each do |path|
diff --git a/lib/puppet/type/host.rb b/lib/puppet/type/host.rb
index 8ab750459..1af74d886 100755
--- a/lib/puppet/type/host.rb
+++ b/lib/puppet/type/host.rb
@@ -5,11 +5,11 @@ module Puppet
newproperty(:ip) do
desc "The host's IP address, IPv4 or IPv6."
- validate do |value|
- unless value =~ /((([0-9a-fA-F]+:){7}[0-9a-fA-F]+)|(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?::(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?)|((25[0-5]|2[0-4][\d]|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})/
- raise Puppet::Error, "Invalid IP address"
+ validate do |value|
+ unless value =~ /^((([0-9a-fA-F]+:){7}[0-9a-fA-F]+)|(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?::(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?)|((25[0-5]|2[0-4][\d]|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})$/
+ raise Puppet::Error, "Invalid IP address"
+ end
end
- end
end
@@ -26,21 +26,6 @@ module Puppet
currentvalue.join(" ")
end
- def retrieve
- is = super
- case is
- when String
- is = is.split(/\s*,\s*/)
- when Symbol
- is = [is]
- when Array
- # nothing
- else
- raise Puppet::DevError, "Invalid @is type #{is.class}"
- end
- is
- end
-
# We actually want to return the whole array here, not just the first
# value.
def should
@@ -61,9 +46,14 @@ module Puppet
validate do |value|
raise Puppet::Error, "Host aliases cannot include whitespace" if value =~ /\s/
+ raise Puppet::Error, "Host alias cannot be an empty string. Use an empty array to delete all host_aliases " if value =~ /^\s*$/
end
end
+ newproperty(:comment) do
+ desc "A comment that will be attached to the line with a # character"
+ end
+
newproperty(:target) do
desc "The file in which to store service information. Only used by
those providers that write to disk."
diff --git a/lib/puppet/type/schedule.rb b/lib/puppet/type/schedule.rb
index ff3fba8eb..82f17e533 100755
--- a/lib/puppet/type/schedule.rb
+++ b/lib/puppet/type/schedule.rb
@@ -16,7 +16,7 @@ module Puppet
Thus, it behooves you to use wider scheduling (e.g., over a couple of
hours) combined with periods and repetitions. For instance, if you
wanted to restrict certain resources to only running once, between
- the hours of two and 4 AM, then you would use this schedule::
+ the hours of two and 4 AM, then you would use this schedule:
schedule { maint:
range => \"2 - 4\",
@@ -33,7 +33,7 @@ module Puppet
Puppet automatically creates a schedule for each valid period with the
same name as that period (e.g., hourly and daily). Additionally,
a schedule named *puppet* is created and used as the default,
- with the following attributes::
+ with the following attributes:
schedule { puppet:
period => hourly,
@@ -45,11 +45,11 @@ module Puppet
newparam(:name) do
desc "The name of the schedule. This name is used to retrieve the
- schedule when assigning it to an object::
+ schedule when assigning it to an object:
schedule { daily:
period => daily,
- range => [2, 4]
+ range => \"2 - 4\",
}
exec { \"/usr/bin/apt-get update\":
@@ -65,7 +65,7 @@ module Puppet
is always a range within a 24 hour period, and hours must be
specified in numbers between 0 and 23, inclusive. Minutes and
seconds can be provided, using the normal colon as a separator.
- For instance::
+ For instance:
schedule { maintenance:
range => \"1:30 - 4:30\"
diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb
index f2eaf0d06..850d147e2 100644
--- a/lib/puppet/util.rb
+++ b/lib/puppet/util.rb
@@ -3,6 +3,7 @@
require 'puppet/util/monkey_patches'
require 'sync'
require 'puppet/external/lock'
+require 'monitor'
module Puppet
# A command failed to execute.
@@ -17,8 +18,7 @@ module Util
require 'puppet/util/posix'
extend Puppet::Util::POSIX
- # Create a hash to store the different sync objects.
- @@syncresources = {}
+ @@sync_objects = {}.extend MonitorMixin
def self.activerecord_version
if (defined?(::ActiveRecord) and defined?(::ActiveRecord::VERSION) and defined?(::ActiveRecord::VERSION::MAJOR) and defined?(::ActiveRecord::VERSION::MINOR))
@@ -28,10 +28,19 @@ module Util
end
end
- # Return the sync object associated with a given resource.
- def self.sync(resource)
- @@syncresources[resource] ||= Sync.new
- @@syncresources[resource]
+
+ def self.synchronize_on(x,type)
+ sync_object,users = 0,1
+ begin
+ @@sync_objects.synchronize {
+ (@@sync_objects[x] ||= [Sync.new,0])[users] += 1
+ }
+ @@sync_objects[x][sync_object].synchronize(type) { yield }
+ ensure
+ @@sync_objects.synchronize {
+ @@sync_objects.delete(x) unless (@@sync_objects[x][users] -= 1) > 0
+ }
+ end
end
# Change the process to a different user
@@ -189,7 +198,7 @@ module Util
end
end
- def binary(bin)
+ def which(bin)
if bin =~ /^\//
return bin if FileTest.file? bin and FileTest.executable? bin
else
@@ -200,7 +209,7 @@ module Util
end
nil
end
- module_function :binary
+ module_function :which
# Execute the provided command in a pipe, yielding the pipe object.
def execpipe(command, failonfail = true)
@@ -359,9 +368,7 @@ module Util
# Create an exclusive lock.
def threadlock(resource, type = Sync::EX)
- Puppet::Util.sync(resource).synchronize(type) do
- yield
- end
+ Puppet::Util.synchronize_on(resource,type) { yield }
end
# Because some modules provide their own version of this method.
@@ -371,15 +378,10 @@ module Util
def memory
unless defined?(@pmap)
- pmap = %x{which pmap 2>/dev/null}.chomp
- if $CHILD_STATUS != 0 or pmap =~ /^no/
- @pmap = nil
- else
- @pmap = pmap
- end
+ @pmap = which('pmap')
end
if @pmap
- return %x{pmap #{Process.pid}| grep total}.chomp.sub(/^\s*total\s+/, '').sub(/K$/, '').to_i
+ %x{#{@pmap} #{Process.pid}| grep total}.chomp.sub(/^\s*total\s+/, '').sub(/K$/, '').to_i
else
0
end
diff --git a/lib/puppet/util/command_line.rb b/lib/puppet/util/command_line.rb
index 2a97ee069..3562a3dc0 100644
--- a/lib/puppet/util/command_line.rb
+++ b/lib/puppet/util/command_line.rb
@@ -62,7 +62,7 @@ module Puppet
external_command = "puppet-#{subcommand_name}"
require 'puppet/util'
- path_to_subcommand = Puppet::Util.binary( external_command )
+ path_to_subcommand = Puppet::Util.which( external_command )
return false unless path_to_subcommand
system( path_to_subcommand, *args )
diff --git a/lib/puppet/util/file_locking.rb b/lib/puppet/util/file_locking.rb
index 8b194ed83..18744cab7 100644
--- a/lib/puppet/util/file_locking.rb
+++ b/lib/puppet/util/file_locking.rb
@@ -6,7 +6,7 @@ module Puppet::Util::FileLocking
# Create a shared lock for reading
def readlock(file)
raise ArgumentError, "#{file} is not a file" unless !File.exists?(file) or File.file?(file)
- Puppet::Util.sync(file).synchronize(Sync::SH) do
+ Puppet::Util.synchronize_on(file,Sync::SH) do
File.open(file) { |f|
f.lock_shared { |lf| yield lf }
}
@@ -33,9 +33,12 @@ module Puppet::Util::FileLocking
end
end
- Puppet::Util.sync(file).synchronize(Sync::EX) do
- File.open(file, "w", mode) do |rf|
+ Puppet::Util.synchronize_on(file,Sync::EX) do
+ File.open(file, File::Constants::CREAT | File::Constants::WRONLY, mode) do |rf|
rf.lock_exclusive do |lrf|
+ # poor's man open(2) O_EXLOCK|O_TRUNC
+ lrf.seek(0, IO::SEEK_SET)
+ lrf.truncate(0)
yield lrf
end
end
diff --git a/lib/puppet/util/log.rb b/lib/puppet/util/log.rb
index 36a765c61..a5aacc265 100644
--- a/lib/puppet/util/log.rb
+++ b/lib/puppet/util/log.rb
@@ -57,6 +57,7 @@ class Puppet::Util::Log
destinations.keys.each { |dest|
close(dest)
}
+ raise Puppet::DevError.new("Log.close_all failed to close #{@destinations.keys.inspect}") if !@destinations.empty?
end
# Flush any log destinations that support such operations.
diff --git a/lib/puppet/util/log/destinations.rb b/lib/puppet/util/log/destinations.rb
index 22b3dedb2..2e2f9a5b7 100644
--- a/lib/puppet/util/log/destinations.rb
+++ b/lib/puppet/util/log/destinations.rb
@@ -203,8 +203,20 @@ Puppet::Util::Log.newdesttype :report do
end
# Log to an array, just for testing.
+module Puppet::Test
+ class LogCollector
+ def initialize(logs)
+ @logs = logs
+ end
+
+ def <<(value)
+ @logs << value
+ end
+ end
+end
+
Puppet::Util::Log.newdesttype :array do
- match "Array"
+ match "Puppet::Test::LogCollector"
def initialize(messages)
@messages = messages
diff --git a/lib/puppet/util/metric.rb b/lib/puppet/util/metric.rb
index 90a244836..7fdc6951f 100644
--- a/lib/puppet/util/metric.rb
+++ b/lib/puppet/util/metric.rb
@@ -64,7 +64,7 @@ class Puppet::Util::Metric
end
def graph(range = nil)
- unless Puppet.features.rrd?
+ unless Puppet.features.rrd? || Puppet.features.rrd_legacy?
Puppet.warning "RRD library is missing; cannot graph metrics"
return
end
@@ -122,7 +122,7 @@ class Puppet::Util::Metric
def initialize(name,label = nil)
@name = name.to_s
- @label = label || labelize(name)
+ @label = label || self.class.labelize(name)
@values = []
end
@@ -132,7 +132,7 @@ class Puppet::Util::Metric
end
def newvalue(name,value,label = nil)
- label ||= labelize(name)
+ label ||= self.class.labelize(name)
@values.push [name,label,value]
end
@@ -173,10 +173,8 @@ class Puppet::Util::Metric
@values.sort { |a, b| a[1] <=> b[1] }
end
- private
-
# Convert a name into a label.
- def labelize(name)
+ def self.labelize(name)
name.to_s.capitalize.gsub("_", " ")
end
end
diff --git a/lib/puppet/util/monkey_patches.rb b/lib/puppet/util/monkey_patches.rb
index bdce5ec1d..1c35ae523 100644
--- a/lib/puppet/util/monkey_patches.rb
+++ b/lib/puppet/util/monkey_patches.rb
@@ -48,6 +48,7 @@ if RUBY_VERSION == '1.8.7'
end
end
+
class Object
# ActiveSupport 2.3.x mixes in a dangerous method
# that can cause rspec to fork bomb
@@ -56,3 +57,17 @@ class Object
raise NotImplementedError, "Kernel.daemonize is too dangerous, please don't try to use it."
end
end
+
+# Workaround for yaml_initialize, which isn't supported before Ruby
+# 1.8.3.
+if RUBY_VERSION == '1.8.1' || RUBY_VERSION == '1.8.2'
+ YAML.add_ruby_type( /^object/ ) { |tag, val|
+ type, obj_class = YAML.read_type_class( tag, Object )
+ r = YAML.object_maker( obj_class, val )
+ if r.respond_to? :yaml_initialize
+ r.instance_eval { instance_variables.each { |name| remove_instance_variable name } }
+ r.yaml_initialize(tag, val)
+ end
+ r
+ }
+end
diff --git a/lib/puppet/util/rdoc.rb b/lib/puppet/util/rdoc.rb
index 085d8ec93..bdac579d6 100644
--- a/lib/puppet/util/rdoc.rb
+++ b/lib/puppet/util/rdoc.rb
@@ -10,24 +10,25 @@ module Puppet::Util::RDoc
# then rdoc
require 'rdoc/rdoc'
+ require 'rdoc/options'
# load our parser
require 'puppet/util/rdoc/parser'
r = RDoc::RDoc.new
- RDoc::RDoc::GENERATORS["puppet"] = RDoc::RDoc::Generator.new(
+ RDoc::RDoc::GENERATORS["puppet"] = RDoc::RDoc::Generator.new(
"puppet/util/rdoc/generators/puppet_generator.rb",
- "PuppetGenerator".intern,
+ "PuppetGenerator".intern,
+ "puppet")
- "puppet")
# specify our own format & where to output
options = [ "--fmt", "puppet",
"--quiet",
- "--force-update",
"--exclude", "/modules/[^/]*/files/.*\.pp$",
"--op", outputdir ]
+ options << "--force-update" if Options::OptionList.options.any? { |o| o[0] == "--force-update" }
options += [ "--charset", charset] if charset
options += files
diff --git a/lib/puppet/util/rdoc/generators/puppet_generator.rb b/lib/puppet/util/rdoc/generators/puppet_generator.rb
index 9caeacd5e..e6bbb2e1e 100644
--- a/lib/puppet/util/rdoc/generators/puppet_generator.rb
+++ b/lib/puppet/util/rdoc/generators/puppet_generator.rb
@@ -88,6 +88,12 @@ module Generators
@modules = {}
@allclasses = {}
+ # remove unknown toplevels
+ # it can happen that RDoc triggers a different parser for some files (ie .c, .cc or .h)
+ # in this case RDoc generates a RDoc::TopLevel which we do not support in this generator
+ # So let's make sure we don't generate html for those.
+ @toplevels = @toplevels.select { |tl| tl.is_a? RDoc::PuppetTopLevel }
+
# build the modules, classes and per modules classes and define list
@toplevels.each do |toplevel|
next unless toplevel.document_self
diff --git a/lib/puppet/util/reference.rb b/lib/puppet/util/reference.rb
index ab201cde4..95efeb1c1 100644
--- a/lib/puppet/util/reference.rb
+++ b/lib/puppet/util/reference.rb
@@ -39,14 +39,7 @@ class Puppet::Util::Reference
Puppet::Util.secure_open("/tmp/puppetdoc.txt", "w") do |f|
f.puts text
end
- rst2latex = %x{which rst2latex}
- if $CHILD_STATUS != 0 or rst2latex =~ /no /
- rst2latex = %x{which rst2latex.py}
- end
- if $CHILD_STATUS != 0 or rst2latex =~ /no /
- raise "Could not find rst2latex"
- end
- rst2latex.chomp!
+ rst2latex = which('rst2latex') || which('rst2latex.py') || raise("Could not find rst2latex")
cmd = %{#{rst2latex} /tmp/puppetdoc.txt > /tmp/puppetdoc.tex}
Puppet::Util.secure_open("/tmp/puppetdoc.tex","w") do |f|
# If we get here without an error, /tmp/puppetdoc.tex isn't a tricky cracker's symlink
diff --git a/lib/puppet/util/suidmanager.rb b/lib/puppet/util/suidmanager.rb
index 4d2c32217..6633de002 100644
--- a/lib/puppet/util/suidmanager.rb
+++ b/lib/puppet/util/suidmanager.rb
@@ -88,7 +88,7 @@ module Puppet::Util::SUIDManager
module_function :initgroups
def run_and_capture(command, new_uid=nil, new_gid=nil)
- output = Puppet::Util.execute(command, :failonfail => false, :uid => new_uid, :gid => new_gid)
+ output = Puppet::Util.execute(command, :failonfail => false, :combine => true, :uid => new_uid, :gid => new_gid)
[output, $CHILD_STATUS.dup]
end
module_function :run_and_capture
diff --git a/lib/puppet/util/zaml.rb b/lib/puppet/util/zaml.rb
index ae4da8612..2155e989c 100644
--- a/lib/puppet/util/zaml.rb
+++ b/lib/puppet/util/zaml.rb
@@ -119,6 +119,9 @@ class Object
def to_yaml_properties
instance_variables.sort # Default YAML behavior
end
+ def yaml_property_munge(x)
+ x
+ end
def zamlized_class_name(root)
cls = self.class
"!ruby/#{root.name.downcase}#{cls == root ? '' : ":#{cls.respond_to?(:name) ? cls.name : cls}"}"
@@ -135,7 +138,7 @@ class Object
z.nl
v[1..-1].to_zaml(z) # Remove leading '@'
z.emit(': ')
- instance_variable_get(v).to_zaml(z)
+ yaml_property_munge(instance_variable_get(v)).to_zaml(z)
}
end
}
diff --git a/spec/integration/configurer_spec.rb b/spec/integration/configurer_spec.rb
index 9a8b66fe4..cb7d3d779 100755
--- a/spec/integration/configurer_spec.rb
+++ b/spec/integration/configurer_spec.rb
@@ -5,6 +5,8 @@ require File.dirname(__FILE__) + '/../spec_helper'
require 'puppet/configurer'
describe Puppet::Configurer do
+ include PuppetSpec::Files
+
describe "when downloading plugins" do
it "should use the :pluginsignore setting, split on whitespace, for ignoring remote files" do
resource = Puppet::Type.type(:notify).new :name => "yay"
@@ -17,19 +19,50 @@ describe Puppet::Configurer do
end
describe "when running" do
- it "should send a transaction report with valid data" do
- catalog = Puppet::Resource::Catalog.new
- catalog.add_resource(Puppet::Type.type(:notify).new(:title => "testing"))
+ before(:each) do
+ @catalog = Puppet::Resource::Catalog.new
+ @catalog.add_resource(Puppet::Type.type(:notify).new(:title => "testing"))
- configurer = Puppet::Configurer.new
+ # Make sure we don't try to persist the local state after the transaction ran,
+ # because it will fail during test (the state file is in an not existing directory)
+ # and we need the transaction to be successful to be able to produce a summary report
+ @catalog.host_config = false
+
+ @configurer = Puppet::Configurer.new
+ end
+
+ it "should send a transaction report with valid data" do
+ @configurer.stubs(:save_last_run_summary)
Puppet::Transaction::Report.indirection.expects(:save).with do |x, report|
report.time.class == Time and report.logs.length > 0
end
Puppet[:report] = true
- configurer.run :catalog => catalog
+ @configurer.run :catalog => @catalog
+ end
+
+ it "should save a correct last run summary" do
+ report = Puppet::Transaction::Report.new
+ report.stubs(:save)
+
+ Puppet[:lastrunfile] = tmpfile("lastrunfile")
+ Puppet[:report] = true
+
+ @configurer.run :catalog => @catalog, :report => report
+
+ summary = nil
+ File.open(Puppet[:lastrunfile], "r") do |fd|
+ summary = YAML.load(fd.read)
+ end
+
+ summary.should be_a(Hash)
+ %w{time changes events resources}.each do |key|
+ summary.should be_key(key)
+ end
+ summary["time"].should be_key("notify")
+ summary["time"]["last_run"].should >= Time.now.tv_sec
end
end
end
diff --git a/spec/integration/defaults_spec.rb b/spec/integration/defaults_spec.rb
index 1f90c7cbc..2f30014e8 100755
--- a/spec/integration/defaults_spec.rb
+++ b/spec/integration/defaults_spec.rb
@@ -3,6 +3,7 @@
require File.dirname(__FILE__) + '/../spec_helper'
require 'puppet/defaults'
+require 'puppet/rails'
describe "Puppet defaults" do
include Puppet::Util::Execution
diff --git a/spec/integration/parser/functions_spec.rb b/spec/integration/parser/functions_spec.rb
new file mode 100644
index 000000000..cbfb4ac88
--- /dev/null
+++ b/spec/integration/parser/functions_spec.rb
@@ -0,0 +1,21 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Parser::Functions do
+ before :each do
+ Puppet::Parser::Functions.rmfunction("template") if Puppet::Parser::Functions.function("template")
+ end
+
+ it "should support multiple threads autoloading the same function" do
+ threads = []
+ lambda {
+ 10.times { |a|
+ threads << Thread.new {
+ Puppet::Parser::Functions.function("template")
+ }
+ }
+ }.should_not raise_error
+ threads.each { |t| t.join }
+ end
+end \ No newline at end of file
diff --git a/spec/integration/parser/ruby_manifest_spec.rb b/spec/integration/parser/ruby_manifest_spec.rb
index af110d3b3..de6f4628c 100644
--- a/spec/integration/parser/ruby_manifest_spec.rb
+++ b/spec/integration/parser/ruby_manifest_spec.rb
@@ -69,7 +69,7 @@ describe "Pure ruby manifests" do
write_file('foo.rb', "hostclass 'bar' do file 'test_file', :owner => 'root', :mode => '644' end")
catalog = compile("import 'foo'\ninclude bar")
file = catalog.resource("File[test_file]")
- file.should be_a Puppet::Resource
+ file.should be_a(Puppet::Resource)
file.type.should == 'File'
file.title.should == 'test_file'
file.exported.should_not be
diff --git a/spec/integration/ssl/certificate_authority_spec.rb b/spec/integration/ssl/certificate_authority_spec.rb
index fca17b405..67ff6f215 100755
--- a/spec/integration/ssl/certificate_authority_spec.rb
+++ b/spec/integration/ssl/certificate_authority_spec.rb
@@ -121,9 +121,7 @@ describe Puppet::SSL::CertificateAuthority do
it "should save valid certificates" do
@ca.sign("luke.madstop.com")
- ssl = %x{which openssl}
-
- unless ssl
+ unless ssl = Puppet::Util::which('openssl')
pending "No ssl available"
else
ca_cert = Puppet[:cacert]
diff --git a/spec/integration/util/file_locking_spec.rb b/spec/integration/util/file_locking_spec.rb
index 20c61d3d5..50613448b 100755
--- a/spec/integration/util/file_locking_spec.rb
+++ b/spec/integration/util/file_locking_spec.rb
@@ -5,28 +5,30 @@ Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f
require 'puppet/util/file_locking'
describe Puppet::Util::FileLocking do
- it "should be able to keep file corruption from happening when there are multiple writers" do
- file = Tempfile.new("puppetspec")
- filepath = file.path
- file.close!()
- file = filepath
- data = {:a => :b, :c => "A string", :d => "another string", :e => %w{an array of strings}}
- File.open(file, "w") { |f| f.puts YAML.dump(data) }
+ before :each do
+ @file = Tempfile.new("puppetspec")
+ filepath = @file.path
+ @file.close!()
+ @file = filepath
+ @data = {:a => :b, :c => "A string", :d => "another string", :e => %w{an array of strings}}
+ File.open(@file, "w") { |f| f.puts YAML.dump(@data) }
+ end
+ it "should be able to keep file corruption from happening when there are multiple writers threads" do
threads = []
sync = Sync.new
9.times { |a|
threads << Thread.new {
9.times { |b|
sync.synchronize(Sync::SH) {
- Puppet::Util::FileLocking.readlock(file) { |f|
- YAML.load(f.read).should == data
+ Puppet::Util::FileLocking.readlock(@file) { |f|
+ YAML.load(f.read).should == @data
}
}
sleep 0.01
sync.synchronize(Sync::EX) {
- Puppet::Util::FileLocking.writelock(file) { |f|
- f.puts YAML.dump(data)
+ Puppet::Util::FileLocking.writelock(@file) { |f|
+ f.puts YAML.dump(@data)
}
}
}
@@ -34,4 +36,22 @@ describe Puppet::Util::FileLocking do
}
threads.each { |th| th.join }
end
+
+ it "should be able to keep file corruption from happening when there are multiple writers processes" do
+ unless Process.fork
+ 50.times { |b|
+ Puppet::Util::FileLocking.writelock(@file) { |f|
+ f.puts YAML.dump(@data)
+ }
+ sleep 0.01
+ }
+ Kernel.exit!
+ end
+
+ 50.times { |c|
+ Puppet::Util::FileLocking.readlock(@file) { |f|
+ YAML.load(f.read).should == @data
+ }
+ }
+ end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index ed4e2c2fb..0c4b076f4 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -72,7 +72,7 @@ Spec::Runner.configure do |config|
Puppet.settings[:bindaddress] = "127.0.0.1"
@logs = []
- Puppet::Util::Log.newdestination(@logs)
+ Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(@logs))
end
end
diff --git a/spec/unit/application/agent_spec.rb b/spec/unit/application/agent_spec.rb
index 8fc98b8c1..50ef00c57 100755
--- a/spec/unit/application/agent_spec.rb
+++ b/spec/unit/application/agent_spec.rb
@@ -180,6 +180,7 @@ describe Puppet::Application::Agent do
Puppet[:libdir] = "/dev/null/lib"
Puppet::SSL::Host.stubs(:ca_location=)
Puppet::Transaction::Report.stubs(:terminus_class=)
+ Puppet::Transaction::Report.stubs(:cache_class=)
Puppet::Resource::Catalog.stubs(:terminus_class=)
Puppet::Resource::Catalog.stubs(:cache_class=)
Puppet::Node::Facts.stubs(:terminus_class=)
@@ -311,6 +312,12 @@ describe Puppet::Application::Agent do
@puppetd.setup
end
+ it "should tell the report handler to cache locally as yaml" do
+ Puppet::Transaction::Report.expects(:cache_class=).with(:yaml)
+
+ @puppetd.setup
+ end
+
it "should change the catalog_terminus setting to 'rest'" do
Puppet[:catalog_terminus] = :foo
@puppetd.setup
diff --git a/spec/unit/application/apply_spec.rb b/spec/unit/application/apply_spec.rb
index edb41b5c3..f07416378 100755
--- a/spec/unit/application/apply_spec.rb
+++ b/spec/unit/application/apply_spec.rb
@@ -4,6 +4,7 @@ require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/application/apply'
require 'puppet/file_bucket/dipper'
+require 'puppet/configurer'
describe Puppet::Application::Apply do
before :each do
@@ -56,6 +57,7 @@ describe Puppet::Application::Apply do
Puppet.stubs(:parse_config)
Puppet::FileBucket::Dipper.stubs(:new)
STDIN.stubs(:read)
+ Puppet::Transaction::Report.stubs(:cache_class=)
@apply.options.stubs(:[]).with(any_parameters)
end
@@ -113,6 +115,11 @@ describe Puppet::Application::Apply do
lambda { @apply.setup }.should raise_error(SystemExit)
end
+ it "should tell the report handler to cache locally as yaml" do
+ Puppet::Transaction::Report.expects(:cache_class=).with(:yaml)
+
+ @apply.setup
+ end
end
describe "when executing" do
@@ -193,6 +200,9 @@ describe Puppet::Application::Apply do
@catalog.stubs(:apply).returns(@transaction)
@apply.stubs(:exit)
+
+ Puppet::Util::Storage.stubs(:load)
+ Puppet::Configurer.any_instance.stubs(:save_last_run_summary) # to prevent it from trying to write files
end
it "should set the code to run from --code" do
@@ -301,27 +311,32 @@ describe Puppet::Application::Apply do
end
it "should call the prerun and postrun commands on a Configurer instance" do
- configurer = stub 'configurer'
-
- Puppet::Configurer.expects(:new).returns configurer
- configurer.expects(:execute_prerun_command)
- configurer.expects(:execute_postrun_command)
+ Puppet::Configurer.any_instance.expects(:execute_prerun_command)
+ Puppet::Configurer.any_instance.expects(:execute_postrun_command)
@apply.main
end
it "should apply the catalog" do
- @catalog.expects(:apply).returns(stub_everything 'transaction')
+ @catalog.expects(:apply).returns(stub_everything('transaction'))
@apply.main
end
+ it "should save the last run summary" do
+ Puppet.stubs(:[]).with(:noop).returns(false)
+ report = stub 'report'
+ Puppet::Configurer.any_instance.stubs(:initialize_report).returns(report)
+
+ Puppet::Configurer.any_instance.expects(:save_last_run_summary).with(report)
+ @apply.main
+ end
+
describe "with detailed_exitcodes" do
it "should exit with report's computed exit status" do
Puppet.stubs(:[]).with(:noop).returns(false)
@apply.options.stubs(:[]).with(:detailed_exitcodes).returns(true)
- report = stub 'report', :exit_status => 666
- @transaction.stubs(:report).returns(report)
+ Puppet::Transaction::Report.any_instance.stubs(:exit_status).returns(666)
@apply.expects(:exit).with(666)
@apply.main
diff --git a/spec/unit/application/filebucket_spec.rb b/spec/unit/application/filebucket_spec.rb
index 6e7a7b819..e6272f179 100644
--- a/spec/unit/application/filebucket_spec.rb
+++ b/spec/unit/application/filebucket_spec.rb
@@ -3,6 +3,7 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/application/filebucket'
+require 'puppet/file_bucket/dipper'
describe Puppet::Application::Filebucket do
before :each do
diff --git a/spec/unit/application/queue_spec.rb b/spec/unit/application/queue_spec.rb
index 87c96dfff..bd0d53ab1 100755
--- a/spec/unit/application/queue_spec.rb
+++ b/spec/unit/application/queue_spec.rb
@@ -3,6 +3,7 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/application/queue'
+require 'puppet/indirector/catalog/queue'
describe Puppet::Application::Queue do
before :each do
diff --git a/spec/unit/configurer_spec.rb b/spec/unit/configurer_spec.rb
index 0c9d06362..e34e6fffb 100755
--- a/spec/unit/configurer_spec.rb
+++ b/spec/unit/configurer_spec.rb
@@ -89,9 +89,7 @@ describe Puppet::Configurer, "when executing a catalog run" do
@catalog = Puppet::Resource::Catalog.new
@catalog.stubs(:apply)
@agent.stubs(:retrieve_catalog).returns @catalog
-
- Puppet::Util::Log.stubs(:newdestination)
- Puppet::Util::Log.stubs(:close)
+ @agent.stubs(:save_last_run_summary)
end
it "should prepare for the run" do
@@ -101,14 +99,14 @@ describe Puppet::Configurer, "when executing a catalog run" do
end
it "should initialize a transaction report if one is not provided" do
- report = stub 'report'
+ report = Puppet::Transaction::Report.new
@agent.expects(:initialize_report).returns report
@agent.run
end
it "should pass the new report to the catalog" do
- report = stub 'report'
+ report = Puppet::Transaction::Report.new
@agent.stubs(:initialize_report).returns report
@catalog.expects(:apply).with{|options| options[:report] == report}
@@ -116,7 +114,7 @@ describe Puppet::Configurer, "when executing a catalog run" do
end
it "should use the provided report if it was passed one" do
- report = stub 'report'
+ report = Puppet::Transaction::Report.new
@agent.expects(:initialize_report).never
@catalog.expects(:apply).with{|options| options[:report] == report}
@@ -176,7 +174,7 @@ describe Puppet::Configurer, "when executing a catalog run" do
end
it "should send the report" do
- report = stub 'report'
+ report = Puppet::Transaction::Report.new
@agent.expects(:initialize_report).returns report
@agent.expects(:send_report).with { |r, trans| r == report }
@@ -184,7 +182,7 @@ describe Puppet::Configurer, "when executing a catalog run" do
end
it "should send the transaction report with a reference to the transaction if a run was actually made" do
- report = stub 'report'
+ report = Puppet::Transaction::Report.new
@agent.expects(:initialize_report).returns report
trans = stub 'transaction'
@@ -198,7 +196,7 @@ describe Puppet::Configurer, "when executing a catalog run" do
it "should send the transaction report even if the catalog could not be retrieved" do
@agent.expects(:retrieve_catalog).returns nil
- report = stub 'report'
+ report = Puppet::Transaction::Report.new
@agent.expects(:initialize_report).returns report
@agent.expects(:send_report)
@@ -208,7 +206,7 @@ describe Puppet::Configurer, "when executing a catalog run" do
it "should send the transaction report even if there is a failure" do
@agent.expects(:retrieve_catalog).raises "whatever"
- report = stub 'report'
+ report = Puppet::Transaction::Report.new
@agent.expects(:initialize_report).returns report
@agent.expects(:send_report)
@@ -216,16 +214,16 @@ describe Puppet::Configurer, "when executing a catalog run" do
end
it "should remove the report as a log destination when the run is finished" do
- report = stub 'report'
+ report = Puppet::Transaction::Report.new
@agent.expects(:initialize_report).returns report
-
- Puppet::Util::Log.expects(:close).with(report)
+ report.expects(:<<).at_least_once
@agent.run
+ Puppet::Util::Log.destinations.should_not include(report)
end
it "should return the report as the result of the run" do
- report = stub 'report'
+ report = Puppet::Transaction::Report.new
@agent.expects(:initialize_report).returns report
@agent.run.should equal(report)
@@ -236,6 +234,7 @@ describe Puppet::Configurer, "when sending a report" do
before do
Puppet.settings.stubs(:use).returns(true)
@configurer = Puppet::Configurer.new
+ @configurer.stubs(:save_last_run_summary)
@report = stub 'report'
@trans = stub 'transaction'
@@ -284,6 +283,20 @@ describe Puppet::Configurer, "when sending a report" do
@configurer.send_report(@report)
end
+ it "should save the last run summary if reporting is enabled" do
+ Puppet.settings[:report] = true
+
+ @configurer.expects(:save_last_run_summary).with(@report)
+ @configurer.send_report(@report)
+ end
+
+ it "should not save the last run summary if reporting is disabled" do
+ Puppet.settings[:report] = false
+
+ @configurer.expects(:save_last_run_summary).never
+ @configurer.send_report(@report)
+ end
+
it "should log but not fail if saving the report fails" do
Puppet.settings[:report] = true
@@ -294,6 +307,36 @@ describe Puppet::Configurer, "when sending a report" do
end
end
+describe Puppet::Configurer, "when saving the summary report file" do
+ before do
+ Puppet.settings.stubs(:use).returns(true)
+ @configurer = Puppet::Configurer.new
+
+ @report = stub 'report'
+ @trans = stub 'transaction'
+ @lastrunfd = stub 'lastrunfd'
+ Puppet::Util::FileLocking.stubs(:writelock).yields(@lastrunfd)
+ end
+
+ it "should write the raw summary to the lastrunfile setting value" do
+ Puppet::Util::FileLocking.expects(:writelock).with(Puppet[:lastrunfile], 0660)
+ @configurer.save_last_run_summary(@report)
+ end
+
+ it "should write the raw summary as yaml" do
+ @report.expects(:raw_summary).returns("summary")
+ @lastrunfd.expects(:print).with(YAML.dump("summary"))
+ @configurer.save_last_run_summary(@report)
+ end
+
+ it "should log but not fail if saving the last run summary fails" do
+ Puppet::Util::FileLocking.expects(:writelock).raises "exception"
+ Puppet.expects(:err)
+ lambda { @configurer.save_last_run_summary(@report) }.should_not raise_error
+ end
+
+end
+
describe Puppet::Configurer, "when retrieving a catalog" do
before do
Puppet.settings.stubs(:use).returns(true)
@@ -472,23 +515,23 @@ describe Puppet::Configurer, "when preparing for a run" do
it "should initialize the metadata store" do
@agent.class.stubs(:facts).returns(@facts)
@agent.expects(:dostorage)
- @agent.prepare
+ @agent.prepare({})
end
it "should download fact plugins" do
@agent.expects(:download_fact_plugins)
- @agent.prepare
+ @agent.prepare({})
end
it "should download plugins" do
@agent.expects(:download_plugins)
- @agent.prepare
+ @agent.prepare({})
end
it "should perform the pre-run commands" do
@agent.expects(:execute_prerun_command)
- @agent.prepare
+ @agent.prepare({})
end
end
diff --git a/spec/unit/daemon_spec.rb b/spec/unit/daemon_spec.rb
index 15320736c..e24db7881 100755
--- a/spec/unit/daemon_spec.rb
+++ b/spec/unit/daemon_spec.rb
@@ -1,4 +1,4 @@
-#!/usr/bin/env ruby"
+#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../spec_helper'
require 'puppet/daemon'
@@ -142,11 +142,7 @@ describe Puppet::Daemon do
describe "when creating its pidfile" do
it "should use an exclusive mutex" do
Puppet.settings.expects(:value).with(:name).returns "me"
-
- sync = mock 'sync'
- Puppet::Util.expects(:sync).with("me").returns sync
-
- sync.expects(:synchronize).with(Sync::EX)
+ Puppet::Util.expects(:synchronize_on).with("me",Sync::EX)
@daemon.create_pidfile
end
@@ -180,10 +176,8 @@ describe Puppet::Daemon do
it "should use an exclusive mutex" do
Puppet.settings.expects(:value).with(:name).returns "me"
- sync = mock 'sync'
- Puppet::Util.expects(:sync).with("me").returns sync
+ Puppet::Util.expects(:synchronize_on).with("me",Sync::EX)
- sync.expects(:synchronize).with(Sync::EX)
@daemon.remove_pidfile
end
diff --git a/spec/unit/indirector/active_record_spec.rb b/spec/unit/indirector/active_record_spec.rb
index 258c4e793..40af146c8 100755
--- a/spec/unit/indirector/active_record_spec.rb
+++ b/spec/unit/indirector/active_record_spec.rb
@@ -2,6 +2,7 @@
require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/rails'
require 'puppet/indirector/active_record'
describe Puppet::Indirector::ActiveRecord do
diff --git a/spec/unit/indirector/catalog/compiler_spec.rb b/spec/unit/indirector/catalog/compiler_spec.rb
index f9980807a..49b8986eb 100755
--- a/spec/unit/indirector/catalog/compiler_spec.rb
+++ b/spec/unit/indirector/catalog/compiler_spec.rb
@@ -6,6 +6,7 @@
require File.dirname(__FILE__) + '/../../../spec_helper'
require 'puppet/indirector/catalog/compiler'
+require 'puppet/rails'
describe Puppet::Resource::Catalog::Compiler do
before do
@@ -34,8 +35,8 @@ describe Puppet::Resource::Catalog::Compiler do
Puppet::Node.stubs(:find).with('node1').returns(node1)
Puppet::Node.stubs(:find).with('node2').returns(node2)
- compiler.find(stub('request', :node => 'node1', :options => {}))
- compiler.find(stub('node2request', :node => 'node2', :options => {}))
+ compiler.find(stub('request', :key => 'node1', :node => 'node1', :options => {}))
+ compiler.find(stub('node2request', :key => 'node2', :node => 'node2', :options => {}))
end
it "should provide a method for determining if the catalog is networked" do
@@ -71,7 +72,7 @@ describe Puppet::Resource::Catalog::Compiler do
@node = Puppet::Node.new @name
@node.stubs(:merge)
Puppet::Node.stubs(:find).returns @node
- @request = stub 'request', :key => "does not matter", :node => @name, :options => {}
+ @request = stub 'request', :key => @name, :node => @name, :options => {}
end
it "should directly use provided nodes" do
@@ -81,14 +82,14 @@ describe Puppet::Resource::Catalog::Compiler do
@compiler.find(@request)
end
- it "should use the request's node name if no explicit node is provided" do
+ it "should use the authenticated node name if no request key is provided" do
+ @request.stubs(:key).returns(nil)
Puppet::Node.expects(:find).with(@name).returns(@node)
@compiler.expects(:compile).with(@node)
@compiler.find(@request)
end
- it "should use the provided node name if no explicit node is provided and no authenticated node information is available" do
- @request.expects(:node).returns nil
+ it "should use the provided node name by default" do
@request.expects(:key).returns "my_node"
Puppet::Node.expects(:find).with("my_node").returns @node
@@ -205,7 +206,7 @@ describe Puppet::Resource::Catalog::Compiler do
@compiler = Puppet::Resource::Catalog::Compiler.new
@name = "me"
@node = mock 'node'
- @request = stub 'request', :node => @name, :options => {}
+ @request = stub 'request', :key => @name, :options => {}
@compiler.stubs(:compile)
end
@@ -224,7 +225,7 @@ describe Puppet::Resource::Catalog::Compiler do
@compiler = Puppet::Resource::Catalog::Compiler.new
@name = "me"
@node = mock 'node'
- @request = stub 'request', :node => @name, :options => {}
+ @request = stub 'request', :key => @name, :options => {}
@compiler.stubs(:compile)
Puppet::Node.stubs(:find).with(@name).returns(@node)
end
diff --git a/spec/unit/indirector/facts/active_record_spec.rb b/spec/unit/indirector/facts/active_record_spec.rb
index 0cdb70e01..0bdcfcb77 100755
--- a/spec/unit/indirector/facts/active_record_spec.rb
+++ b/spec/unit/indirector/facts/active_record_spec.rb
@@ -2,6 +2,7 @@
require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'puppet/rails'
require 'puppet/node/facts'
describe "Puppet::Node::Facts::ActiveRecord" do
diff --git a/spec/unit/indirector/report/yaml_spec.rb b/spec/unit/indirector/report/yaml_spec.rb
new file mode 100644
index 000000000..610c9ae43
--- /dev/null
+++ b/spec/unit/indirector/report/yaml_spec.rb
@@ -0,0 +1,38 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/transaction/report'
+require 'puppet/indirector/report/yaml'
+
+describe Puppet::Transaction::Report::Yaml do
+ it "should be a subclass of the Yaml terminus" do
+ Puppet::Transaction::Report::Yaml.superclass.should equal(Puppet::Indirector::Yaml)
+ end
+
+ it "should have documentation" do
+ Puppet::Transaction::Report::Yaml.doc.should_not be_nil
+ end
+
+ it "should be registered with the report indirection" do
+ indirection = Puppet::Indirector::Indirection.instance(:report)
+ Puppet::Transaction::Report::Yaml.indirection.should equal(indirection)
+ end
+
+ it "should have its name set to :yaml" do
+ Puppet::Transaction::Report::Yaml.name.should == :yaml
+ end
+
+ it "should inconditionnally save/load from the --lastrunreport setting" do
+ indirection = stub 'indirection', :name => :my_yaml, :register_terminus_type => nil
+ Puppet::Indirector::Indirection.stubs(:instance).with(:my_yaml).returns(indirection)
+ store_class = Class.new(Puppet::Transaction::Report::Yaml) do
+ def self.to_s
+ "MyYaml::MyType"
+ end
+ end
+ store = store_class.new
+
+ store.path(:me).should == Puppet[:lastrunreport]
+ end
+end
diff --git a/spec/unit/network/handler/fileserver_spec.rb b/spec/unit/network/handler/fileserver_spec.rb
index 40d1e57cd..b37d4f551 100644
--- a/spec/unit/network/handler/fileserver_spec.rb
+++ b/spec/unit/network/handler/fileserver_spec.rb
@@ -4,9 +4,8 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
require 'puppet/network/handler/fileserver'
-
describe Puppet::Network::Handler::FileServer do
- require 'tmpdir'
+ include PuppetSpec::Files
def create_file(filename)
File.open(filename, "w") { |f| f.puts filename}
@@ -20,8 +19,7 @@ describe Puppet::Network::Handler::FileServer do
end
before do
- @basedir = File.join(Dir.tmpdir, "test_network_handler")
- Dir.mkdir(@basedir)
+ @basedir = tmpdir("test_network_handler")
@file = File.join(@basedir, "aFile")
@link = File.join(@basedir, "aLink")
create_file(@file)
diff --git a/spec/unit/network/http/rack/xmlrpc_spec.rb b/spec/unit/network/http/rack/xmlrpc_spec.rb
index 63ba28bf2..870438f2c 100755
--- a/spec/unit/network/http/rack/xmlrpc_spec.rb
+++ b/spec/unit/network/http/rack/xmlrpc_spec.rb
@@ -1,6 +1,7 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../../../spec_helper'
+require 'puppet/network/handler'
require 'puppet/network/http/rack' if Puppet.features.rack?
require 'puppet/network/http/rack/xmlrpc' if Puppet.features.rack?
diff --git a/spec/unit/network/http/rack_spec.rb b/spec/unit/network/http/rack_spec.rb
index df42a1ffa..8be9ccb50 100755
--- a/spec/unit/network/http/rack_spec.rb
+++ b/spec/unit/network/http/rack_spec.rb
@@ -1,6 +1,7 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'puppet/network/handler'
require 'puppet/network/http/rack' if Puppet.features.rack?
describe "Puppet::Network::HTTP::Rack" do
diff --git a/spec/unit/network/http/webrick_spec.rb b/spec/unit/network/http/webrick_spec.rb
index 2a6ef2268..8e7c92b71 100755
--- a/spec/unit/network/http/webrick_spec.rb
+++ b/spec/unit/network/http/webrick_spec.rb
@@ -4,6 +4,7 @@
# Copyright (c) 2007. All rights reserved.
require File.dirname(__FILE__) + '/../../../spec_helper'
+require 'puppet/network/handler'
require 'puppet/network/http'
require 'puppet/network/http/webrick'
diff --git a/spec/unit/network/server_spec.rb b/spec/unit/network/server_spec.rb
index ccd9c082e..c2496dcca 100755
--- a/spec/unit/network/server_spec.rb
+++ b/spec/unit/network/server_spec.rb
@@ -5,6 +5,7 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require 'puppet/network/server'
+require 'puppet/network/handler'
describe Puppet::Network::Server do
before do
@@ -161,11 +162,7 @@ describe Puppet::Network::Server do
describe "when creating its pidfile" do
it "should use an exclusive mutex" do
Puppet.settings.expects(:value).with(:name).returns "me"
-
- sync = mock 'sync'
- Puppet::Util.expects(:sync).with("me").returns sync
-
- sync.expects(:synchronize).with(Sync::EX)
+ Puppet::Util.expects(:synchronize_on).with("me",Sync::EX)
@server.create_pidfile
end
@@ -198,11 +195,7 @@ describe Puppet::Network::Server do
describe "when removing its pidfile" do
it "should use an exclusive mutex" do
Puppet.settings.expects(:value).with(:name).returns "me"
-
- sync = mock 'sync'
- Puppet::Util.expects(:sync).with("me").returns sync
-
- sync.expects(:synchronize).with(Sync::EX)
+ Puppet::Util.expects(:synchronize_on).with("me",Sync::EX)
@server.remove_pidfile
end
diff --git a/spec/unit/parser/ast/collection_spec.rb b/spec/unit/parser/ast/collection_spec.rb
index 3f7878a99..392a2c0f0 100755
--- a/spec/unit/parser/ast/collection_spec.rb
+++ b/spec/unit/parser/ast/collection_spec.rb
@@ -5,6 +5,8 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
describe Puppet::Parser::AST::Collection do
before :each do
@scope = stub_everything 'scope'
+ @mytype = stub_everything('mytype')
+ @scope.stubs(:find_resource_type).returns @mytype
@compiler = stub_everything 'compile'
@scope.stubs(:compiler).returns(@compiler)
@@ -24,6 +26,8 @@ describe Puppet::Parser::AST::Collection do
it "should instantiate a Collector for this type" do
collection = Puppet::Parser::AST::Collection.new :form => :virtual, :type => "test"
+ @test_type = stub 'type', :name => 'test'
+ @scope.expects(:find_resource_type).with('test').returns @test_type
Puppet::Parser::Collector.expects(:new).with(@scope, "test", nil, nil, :virtual)
diff --git a/spec/unit/parser/ast/leaf_spec.rb b/spec/unit/parser/ast/leaf_spec.rb
index eb71f0d37..a19c24115 100755
--- a/spec/unit/parser/ast/leaf_spec.rb
+++ b/spec/unit/parser/ast/leaf_spec.rb
@@ -49,7 +49,7 @@ describe Puppet::Parser::AST::String do
end
it "should return a dup of its value" do
value = ""
- Puppet::Parser::AST::String.new( :value => value ).evaluate(stub 'scope').should_not be_equal(value)
+ Puppet::Parser::AST::String.new( :value => value ).evaluate(stub('scope')).should_not be_equal(value)
end
end
end
@@ -136,6 +136,22 @@ describe Puppet::Parser::AST::HashOrArrayAccess do
access.evaluate(@scope).should == "val2"
end
+ it "should be able to return an array member when index is a stringified number" do
+ @scope.stubs(:lookupvar).with("a").returns(["val1", "val2", "val3"])
+
+ access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "1" )
+
+ access.evaluate(@scope).should == "val2"
+ end
+
+ it "should raise an error when accessing an array with a key" do
+ @scope.stubs(:lookupvar).with("a").returns(["val1", "val2", "val3"])
+
+ access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "get_me_the_second_element_please" )
+
+ lambda { access.evaluate(@scope) }.should raise_error
+ end
+
it "should be able to return an hash value" do
@scope.stubs(:lookupvar).with("a").returns({ "key1" => "val1", "key2" => "val2", "key3" => "val3" })
@@ -144,6 +160,14 @@ describe Puppet::Parser::AST::HashOrArrayAccess do
access.evaluate(@scope).should == "val2"
end
+ it "should be able to return an hash value with a numerical key" do
+ @scope.stubs(:lookupvar).with("a").returns({ "key1" => "val1", "key2" => "val2", "45" => "45", "key3" => "val3" })
+
+ access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "45" )
+
+ access.evaluate(@scope).should == "45"
+ end
+
it "should raise an error if the variable lookup didn't return an hash or an array" do
@scope.stubs(:lookupvar).with("a").returns("I'm a string")
@@ -195,6 +219,24 @@ describe Puppet::Parser::AST::HashOrArrayAccess do
scope.lookupvar("a").should be_include("b")
end
+ it "should raise an error when assigning an array element with a key" do
+ @scope.stubs(:lookupvar).with("a").returns([])
+
+ access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "get_me_the_second_element_please" )
+
+ lambda { access.assign(@scope, "test") }.should raise_error
+ end
+
+ it "should be able to return an array member when index is a stringified number" do
+ scope = Puppet::Parser::Scope.new
+ scope.setvar("a", [])
+
+ access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "0" )
+
+ access.assign(scope, "val2")
+ scope.lookupvar("a").should == ["val2"]
+ end
+
it "should raise an error when trying to overwrite an hash value" do
@scope.stubs(:lookupvar).with("a").returns({ "key" => [ "a" , "b" ]})
access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "key")
diff --git a/spec/unit/parser/ast/resource_spec.rb b/spec/unit/parser/ast/resource_spec.rb
index 3ed7b3e08..3f7fa229a 100755
--- a/spec/unit/parser/ast/resource_spec.rb
+++ b/spec/unit/parser/ast/resource_spec.rb
@@ -164,7 +164,7 @@ describe Puppet::Parser::AST::Resource do
result = @resource.evaluate(@scope)
result.length.should == 1
result.first.ref.should == "Class[Classname]"
- @compiler.catalog.resource("Class[Classname]").should equal result.first
+ @compiler.catalog.resource("Class[Classname]").should equal(result.first)
end
it "should cause its parent to be evaluated" do
@@ -175,7 +175,7 @@ describe Puppet::Parser::AST::Resource do
result = @resource.evaluate(@scope)
result.length.should == 1
result.first.ref.should == "Class[Classname]"
- @compiler.catalog.resource("Class[Classname]").should equal result.first
+ @compiler.catalog.resource("Class[Classname]").should equal(result.first)
@compiler.catalog.resource("Class[Parentname]").should be_instance_of(Puppet::Parser::Resource)
end
diff --git a/spec/unit/parser/collector_spec.rb b/spec/unit/parser/collector_spec.rb
index 15808d6ff..908cda63a 100755
--- a/spec/unit/parser/collector_spec.rb
+++ b/spec/unit/parser/collector_spec.rb
@@ -2,6 +2,7 @@
require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/rails'
require 'puppet/parser/collector'
describe Puppet::Parser::Collector, "when initializing" do
diff --git a/spec/unit/parser/parser_spec.rb b/spec/unit/parser/parser_spec.rb
index b4e1518c4..ab43194e9 100755
--- a/spec/unit/parser/parser_spec.rb
+++ b/spec/unit/parser/parser_spec.rb
@@ -4,7 +4,7 @@ require File.dirname(__FILE__) + '/../../spec_helper'
describe Puppet::Parser do
- ast = Puppet::Parser::AST
+ Puppet::Parser::AST
before :each do
@known_resource_types = Puppet::Resource::TypeCollection.new("development")
@@ -80,21 +80,21 @@ describe Puppet::Parser do
describe "when parsing 'if'" do
it "not, it should create the correct ast objects" do
- ast::Not.expects(:new).with { |h| h[:value].is_a?(ast::Boolean) }
+ Puppet::Parser::AST::Not.expects(:new).with { |h| h[:value].is_a?(Puppet::Parser::AST::Boolean) }
@parser.parse("if ! true { $var = 1 }")
end
it "boolean operation, it should create the correct ast objects" do
- ast::BooleanOperator.expects(:new).with {
- |h| h[:rval].is_a?(ast::Boolean) and h[:lval].is_a?(ast::Boolean) and h[:operator]=="or"
+ Puppet::Parser::AST::BooleanOperator.expects(:new).with {
+ |h| h[:rval].is_a?(Puppet::Parser::AST::Boolean) and h[:lval].is_a?(Puppet::Parser::AST::Boolean) and h[:operator]=="or"
}
@parser.parse("if true or true { $var = 1 }")
end
it "comparison operation, it should create the correct ast objects" do
- ast::ComparisonOperator.expects(:new).with {
- |h| h[:lval].is_a?(ast::Name) and h[:rval].is_a?(ast::Name) and h[:operator]=="<"
+ Puppet::Parser::AST::ComparisonOperator.expects(:new).with {
+ |h| h[:lval].is_a?(Puppet::Parser::AST::Name) and h[:rval].is_a?(Puppet::Parser::AST::Name) and h[:operator]=="<"
}
@parser.parse("if 1 < 2 { $var = 1 }")
@@ -105,13 +105,13 @@ describe Puppet::Parser do
describe "when parsing if complex expressions" do
it "should create a correct ast tree" do
aststub = stub_everything 'ast'
- ast::ComparisonOperator.expects(:new).with {
- |h| h[:rval].is_a?(ast::Name) and h[:lval].is_a?(ast::Name) and h[:operator]==">"
+ Puppet::Parser::AST::ComparisonOperator.expects(:new).with {
+ |h| h[:rval].is_a?(Puppet::Parser::AST::Name) and h[:lval].is_a?(Puppet::Parser::AST::Name) and h[:operator]==">"
}.returns(aststub)
- ast::ComparisonOperator.expects(:new).with {
- |h| h[:rval].is_a?(ast::Name) and h[:lval].is_a?(ast::Name) and h[:operator]=="=="
+ Puppet::Parser::AST::ComparisonOperator.expects(:new).with {
+ |h| h[:rval].is_a?(Puppet::Parser::AST::Name) and h[:lval].is_a?(Puppet::Parser::AST::Name) and h[:operator]=="=="
}.returns(aststub)
- ast::BooleanOperator.expects(:new).with {
+ Puppet::Parser::AST::BooleanOperator.expects(:new).with {
|h| h[:rval]==aststub and h[:lval]==aststub and h[:operator]=="and"
}
@parser.parse("if (1 > 2) and (1 == 2) { $var = 1 }")
@@ -134,8 +134,8 @@ describe Puppet::Parser do
end
it "should create an ast::ResourceReference" do
- ast::ResourceReference.expects(:new).with { |arg|
- arg[:line]==1 and arg[:type]=="File" and arg[:title].is_a?(ast::ASTArray)
+ Puppet::Parser::AST::ResourceReference.expects(:new).with { |arg|
+ arg[:line]==1 and arg[:type]=="File" and arg[:title].is_a?(Puppet::Parser::AST::ASTArray)
}
@parser.parse('exec { test: command => File["a","b"] }')
end
@@ -152,14 +152,14 @@ describe Puppet::Parser do
end
it "should create an ast::ResourceOverride" do
- #ast::ResourceOverride.expects(:new).with { |arg|
- # arg[:line]==1 and arg[:object].is_a?(ast::ResourceReference) and arg[:parameters].is_a?(ast::ResourceParam)
+ #Puppet::Parser::AST::ResourceOverride.expects(:new).with { |arg|
+ # arg[:line]==1 and arg[:object].is_a?(Puppet::Parser::AST::ResourceReference) and arg[:parameters].is_a?(Puppet::Parser::AST::ResourceParam)
#}
ro = @parser.parse('Resource["title1","title2"] { param => value }').code[0]
- ro.should be_a(ast::ResourceOverride)
+ ro.should be_a(Puppet::Parser::AST::ResourceOverride)
ro.line.should == 1
- ro.object.should be_a(ast::ResourceReference)
- ro.parameters[0].should be_a(ast::ResourceParam)
+ ro.object.should be_a(Puppet::Parser::AST::ResourceReference)
+ ro.parameters[0].should be_a(Puppet::Parser::AST::ResourceParam)
end
end
@@ -179,17 +179,17 @@ describe Puppet::Parser do
end
it "should create a nop node for empty branch" do
- ast::Nop.expects(:new)
+ Puppet::Parser::AST::Nop.expects(:new)
@parser.parse("if true { }")
end
it "should create a nop node for empty else branch" do
- ast::Nop.expects(:new)
+ Puppet::Parser::AST::Nop.expects(:new)
@parser.parse("if true { notice('test') } else { }")
end
it "should build a chain of 'ifs' if there's an 'elsif'" do
- ast = @parser.parse(<<-PP)
+ lambda { @parser.parse(<<-PP) }.should_not raise_error
if true { notice('test') } elsif true {} else { }
PP
end
@@ -274,16 +274,23 @@ describe Puppet::Parser do
it "should prefer provided options over AST context" do
@class.expects(:new).with { |opts| opts[:file] == "/bar" }
- @parser.expects(:ast_context).returns :file => "/foo"
+ @lexer.expects(:file).returns "/foo"
@parser.ast(@class, :file => "/bar")
end
it "should include docs when the AST class uses them" do
@class.expects(:use_docs).returns true
@class.stubs(:new)
- @parser.expects(:ast_context).with(true).returns({})
+ @parser.expects(:ast_context).with{ |a| a[0] == true }.returns({})
@parser.ast(@class, :file => "/bar")
end
+
+ it "should get docs from lexer using the correct AST line number" do
+ @class.expects(:use_docs).returns true
+ @class.stubs(:new).with{ |a| a[:doc] == "doc" }
+ @lexer.expects(:getcomment).with(12).returns "doc"
+ @parser.ast(@class, :file => "/bar", :line => 12)
+ end
end
describe "when retrieving a specific node" do
diff --git a/spec/unit/parser/templatewrapper_spec.rb b/spec/unit/parser/templatewrapper_spec.rb
index d4d1d1b8e..68d90a1cc 100755
--- a/spec/unit/parser/templatewrapper_spec.rb
+++ b/spec/unit/parser/templatewrapper_spec.rb
@@ -1,6 +1,7 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/parser/templatewrapper'
describe Puppet::Parser::TemplateWrapper do
before(:each) do
diff --git a/spec/unit/provider/confine/exists_spec.rb b/spec/unit/provider/confine/exists_spec.rb
index c3958e317..f039208b8 100755
--- a/spec/unit/provider/confine/exists_spec.rb
+++ b/spec/unit/provider/confine/exists_spec.rb
@@ -39,25 +39,18 @@ describe Puppet::Provider::Confine::Exists do
describe "and the confine is for binaries" do
before { @confine.stubs(:for_binary).returns true }
- it "should use its 'binary' method to look up the full path of the file" do
- @confine.expects(:binary).returns nil
+ it "should use its 'which' method to look up the full path of the file" do
+ @confine.expects(:which).returns nil
@confine.pass?("/my/file")
end
- it "should return false if no binary can be found" do
- @confine.expects(:binary).with("/my/file").returns nil
+ it "should return false if no executable can be found" do
+ @confine.expects(:which).with("/my/file").returns nil
@confine.pass?("/my/file").should be_false
end
- it "should return true if the binary can be found and the file exists" do
- @confine.expects(:binary).with("/my/file").returns "/my/file"
- FileTest.expects(:exist?).with("/my/file").returns true
- @confine.pass?("/my/file").should be_true
- end
-
- it "should return false if the binary can be found but the file does not exist" do
- @confine.expects(:binary).with("/my/file").returns "/my/file"
- FileTest.expects(:exist?).with("/my/file").returns true
+ it "should return true if the executable can be found" do
+ @confine.expects(:which).with("/my/file").returns "/my/file"
@confine.pass?("/my/file").should be_true
end
end
diff --git a/spec/unit/provider/host/parsed_spec.rb b/spec/unit/provider/host/parsed_spec.rb
new file mode 100644
index 000000000..239e3bd86
--- /dev/null
+++ b/spec/unit/provider/host/parsed_spec.rb
@@ -0,0 +1,196 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet_spec/files'
+require 'puppettest/support/utils'
+require 'puppettest/fileparsing'
+
+provider_class = Puppet::Type.type(:host).provider(:parsed)
+
+describe provider_class do
+ include PuppetSpec::Files
+ extend PuppetTest::Support::Utils
+ include PuppetTest::FileParsing
+
+ before do
+ @host_class = Puppet::Type.type(:host)
+ @provider = @host_class.provider(:parsed)
+ @hostfile = tmpfile('hosts')
+ @provider.any_instance.stubs(:target).returns @hostfile
+ end
+
+ after :each do
+ @provider.initvars
+ end
+
+ def mkhost(args)
+ hostresource = Puppet::Type::Host.new(:name => args[:name])
+ hostresource.stubs(:should).with(:target).returns @hostfile
+
+ # Using setters of provider
+ host = @provider.new(hostresource)
+ args.each do |property,value|
+ host.send("#{property}=", value)
+ end
+ host
+ end
+
+ def genhost(host)
+ @provider.stubs(:filetype).returns(Puppet::Util::FileType::FileTypeRam)
+ File.stubs(:chown)
+ File.stubs(:chmod)
+ Puppet::Util::SUIDManager.stubs(:asuser).yields
+ host.flush
+ @provider.target_object(@hostfile).read
+ end
+
+ describe "when parsing a line with ip and hostname" do
+
+ it "should parse an ipv4 from the first field" do
+ @provider.parse_line("127.0.0.1 localhost")[:ip].should == "127.0.0.1"
+ end
+
+ it "should parse an ipv6 from the first field" do
+ @provider.parse_line("::1 localhost")[:ip].should == "::1"
+ end
+
+ it "should parse the name from the second field" do
+ @provider.parse_line("::1 localhost")[:name].should == "localhost"
+ end
+
+ it "should set an empty comment" do
+ @provider.parse_line("::1 localhost")[:comment].should == ""
+ end
+
+ end
+
+ describe "when parsing a line with ip, hostname and comment" do
+ before do
+ @testline = "127.0.0.1 localhost # A comment with a #-char"
+ end
+
+ it "should parse the ip from the first field" do
+ @provider.parse_line(@testline)[:ip].should == "127.0.0.1"
+ end
+
+ it "should parse the hostname from the second field" do
+ @provider.parse_line(@testline)[:name].should == "localhost"
+ end
+
+ it "should parse the comment after the first '#' character" do
+ @provider.parse_line(@testline)[:comment].should == 'A comment with a #-char'
+ end
+
+ end
+
+ describe "when parsing a line with ip, hostname and aliases" do
+
+ it "should parse alias from the third field" do
+ @provider.parse_line("127.0.0.1 localhost localhost.localdomain")[:host_aliases].should == ["localhost.localdomain"]
+ end
+
+ it "should parse multiple aliases" do
+ @provider.parse_line("127.0.0.1 host alias1 alias2")[:host_aliases].should == ['alias1', 'alias2']
+ @provider.parse_line("127.0.0.1 host alias1\talias2")[:host_aliases].should == ['alias1', 'alias2']
+ @provider.parse_line("127.0.0.1 host alias1\talias2 alias3")[:host_aliases].should == ['alias1', 'alias2', 'alias3']
+ end
+
+ end
+
+ describe "when parsing a line with ip, hostname, aliases and comment" do
+
+ before do
+ # Just playing with a few different delimiters
+ @testline = "127.0.0.1\t host alias1\talias2 alias3 # A comment with a #-char"
+ end
+
+ it "should parse the ip from the first field" do
+ @provider.parse_line(@testline)[:ip].should == "127.0.0.1"
+ end
+
+ it "should parse the hostname from the second field" do
+ @provider.parse_line(@testline)[:name].should == "host"
+ end
+
+ it "should parse all host_aliases from the third field" do
+ @provider.parse_line(@testline)[:host_aliases].should == ['alias1' ,'alias2', 'alias3']
+ end
+
+ it "should parse the comment after the first '#' character" do
+ @provider.parse_line(@testline)[:comment].should == 'A comment with a #-char'
+ end
+
+ end
+
+ describe "when operating on /etc/hosts like files" do
+ fakedata("data/providers/host/parsed","valid*").each do |file|
+ it "should be able to parse #{file}" do
+ fakedataparse(file)
+ end
+ end
+
+ it "should be able to generate a simple hostfile entry" do
+ host = mkhost(
+ :name => 'localhost',
+ :ip => '127.0.0.1',
+ :ensure => :present
+ )
+ genhost(host).should == "127.0.0.1\tlocalhost\n"
+ end
+
+ it "should be able to generate an entry with one alias" do
+ host = mkhost(
+ :name => 'localhost.localdomain',
+ :ip => '127.0.0.1',
+ :host_aliases => ['localhost'],
+ :ensure => :present
+ )
+ genhost(host).should == "127.0.0.1\tlocalhost.localdomain\tlocalhost\n"
+ end
+
+ it "should be able to generate an entry with more than one alias" do
+ host = mkhost(
+ :name => 'host',
+ :ip => '192.0.0.1',
+ :host_aliases => [ 'a1','a2','a3','a4' ],
+ :ensure => :present
+ )
+ genhost(host).should == "192.0.0.1\thost\ta1\ta2\ta3\ta4\n"
+ end
+
+ it "should be able to generate a simple hostfile entry with comments" do
+ host = mkhost(
+ :name => 'localhost',
+ :ip => '127.0.0.1',
+ :comment => 'Bazinga!',
+ :ensure => :present
+ )
+ genhost(host).should == "127.0.0.1\tlocalhost\t# Bazinga!\n"
+ end
+
+ it "should be able to generate an entry with one alias and a comment" do
+ host = mkhost(
+ :name => 'localhost.localdomain',
+ :ip => '127.0.0.1',
+ :host_aliases => ['localhost'],
+ :comment => 'Bazinga!',
+ :ensure => :present
+ )
+ genhost(host).should == "127.0.0.1\tlocalhost.localdomain\tlocalhost\t# Bazinga!\n"
+ end
+
+ it "should be able to generate an entry with more than one alias and a comment" do
+ host = mkhost(
+ :name => 'host',
+ :ip => '192.0.0.1',
+ :host_aliases => [ 'a1','a2','a3','a4' ],
+ :comment => 'Bazinga!',
+ :ensure => :present
+ )
+ genhost(host).should == "192.0.0.1\thost\ta1\ta2\ta3\ta4\t# Bazinga!\n"
+ end
+
+ end
+
+end
diff --git a/spec/unit/provider/mount_spec.rb b/spec/unit/provider/mount_spec.rb
index 55a52b44a..b034214ee 100755
--- a/spec/unit/provider/mount_spec.rb
+++ b/spec/unit/provider/mount_spec.rb
@@ -113,7 +113,14 @@ describe Puppet::Provider::Mount do
@mounter.should be_mounted
end
- it "should match ' on <name>' if the operating system is not Darwin or Solaris" do
+ it "should match '^<name> on' if the operating system is HP-UX" do
+ Facter.stubs(:value).with("operatingsystem").returns("HP-UX")
+ @mounter.expects(:mountcmd).returns("/ on /dev/dsk/whatever\n/var on /dev/dsk/other")
+
+ @mounter.should be_mounted
+ end
+
+ it "should match ' on <name>' if the operating system is not Darwin, Solaris, or HP-UX" do
Facter.stubs(:value).with("operatingsystem").returns("Debian")
@mounter.expects(:mountcmd).returns("/dev/dsk/whatever on / and stuff\n/dev/other/disk on /var and stuff")
diff --git a/spec/unit/provider/package/yum_spec.rb b/spec/unit/provider/package/yum_spec.rb
new file mode 100644
index 000000000..f6a99aa78
--- /dev/null
+++ b/spec/unit/provider/package/yum_spec.rb
@@ -0,0 +1,67 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+provider = Puppet::Type.type(:package).provider(:yum)
+
+describe provider do
+ before do
+ # Create a mock resource
+ @resource = stub 'resource'
+ @resource.stubs(:[]).with(:name).returns 'mypackage'
+ @provider = provider.new(@resource)
+ @provider.stubs(:resource).returns @resource
+ @provider.stubs(:yum).returns 'yum'
+ @provider.stubs(:rpm).returns 'rpm'
+ @provider.stubs(:get).with(:name).returns 'mypackage'
+ @provider.stubs(:get).with(:version).returns '1'
+ @provider.stubs(:get).with(:release).returns '1'
+ @provider.stubs(:get).with(:arch).returns 'i386'
+ end
+ # provider should repond to the following methods
+ [:install, :latest, :update, :purge].each do |method|
+ it "should have a(n) #{method}" do
+ @provider.should respond_to(method)
+ end
+ end
+
+ describe 'when installing' do
+ it 'should call yum install for :installed' do
+ @resource.stubs(:should).with(:ensure).returns :installed
+ @provider.expects(:yum).with('-d', '0', '-e', '0', '-y', :install, 'mypackage')
+ @provider.install
+ end
+ it 'should use :install to update' do
+ @provider.expects(:install)
+ @provider.update
+ end
+ it 'should be able to set version' do
+ @resource.stubs(:should).with(:ensure).returns '1.2'
+ @provider.expects(:yum).with('-d', '0', '-e', '0', '-y', :install, 'mypackage-1.2')
+ @provider.stubs(:query).returns :ensure => '1.2'
+ @provider.install
+ end
+ it 'should be able to downgrade' do
+ @resource.stubs(:should).with(:ensure).returns '1.0'
+ @provider.expects(:yum).with('-d', '0', '-e', '0', '-y', :downgrade, 'mypackage-1.0')
+ @provider.stubs(:query).returns(:ensure => '1.2').then.returns(:ensure => '1.0')
+ @provider.install
+ end
+ end
+
+ describe 'when uninstalling' do
+ it 'should use erase to purge' do
+ @provider.expects(:yum).with('-y', :erase, 'mypackage')
+ @provider.purge
+ end
+ it 'should use rpm to uninstall' do
+ @provider.expects(:rpm).with('-e', 'mypackage-1-1.i386')
+ @provider.uninstall
+ end
+ end
+
+ it 'should be versionable' do
+ provider.should be_versionable
+ end
+end
+
diff --git a/spec/unit/provider/service/freebsd_spec.rb b/spec/unit/provider/service/freebsd_spec.rb
new file mode 100644
index 000000000..0330adbed
--- /dev/null
+++ b/spec/unit/provider/service/freebsd_spec.rb
@@ -0,0 +1,50 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+provider_class = Puppet::Type.type(:service).provider(:freebsd)
+
+describe provider_class do
+ before :each do
+ @provider = provider_class.new
+ @provider.stubs(:initscript)
+ end
+
+ it "should correctly parse rcvar for FreeBSD < 7" do
+ @provider.stubs(:execute).returns <<OUTPUT
+# ntpd
+$ntpd_enable=YES
+OUTPUT
+ @provider.rcvar.should == ['# ntpd', 'ntpd_enable=YES']
+ end
+
+ it "should correctly parse rcvar for FreeBSD 7 to 8" do
+ @provider.stubs(:execute).returns <<OUTPUT
+# ntpd
+ntpd_enable=YES
+OUTPUT
+ @provider.rcvar.should == ['# ntpd', 'ntpd_enable=YES']
+ end
+
+ it "should correctly parse rcvar for FreeBSD >= 8.1" do
+ @provider.stubs(:execute).returns <<OUTPUT
+# ntpd
+#
+ntpd_enable="YES"
+# (default: "")
+OUTPUT
+ @provider.rcvar.should == ['# ntpd', 'ntpd_enable="YES"', '# (default: "")']
+ end
+
+ it "should find the right rcvar_value for FreeBSD < 7" do
+ @provider.stubs(:rcvar).returns(['# ntpd', 'ntpd_enable=YES'])
+
+ @provider.rcvar_value.should == "YES"
+ end
+
+ it "should find the right rcvar_value for FreeBSD >= 7" do
+ @provider.stubs(:rcvar).returns(['# ntpd', 'ntpd_enable="YES"', '# (default: "")'])
+
+ @provider.rcvar_value.should == "YES"
+ end
+end
diff --git a/spec/unit/provider/service/upstart.rb b/spec/unit/provider/service/upstart.rb
index 439fd2c79..9fde9e67f 100644
--- a/spec/unit/provider/service/upstart.rb
+++ b/spec/unit/provider/service/upstart.rb
@@ -24,8 +24,7 @@ describe provider_class do
resource = Puppet::Type.type(:service).new(:name => "foo", :provider => :upstart, :status => "/bin/foo")
provider = provider_class.new(resource)
- Process::Status.any_instance.stubs(:exitstatus).returns(0)
- provider.expects(:ucommand)
+ provider.expects(:ucommand).with { `true`; true }
provider.status.should == :running
end
diff --git a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb
index 648527924..11e9233e0 100755
--- a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb
+++ b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb
@@ -5,7 +5,6 @@ require File.dirname(__FILE__) + '/../../../spec_helper'
require 'puppet_spec/files'
require 'puppettest/support/utils'
require 'puppettest/fileparsing'
-require 'tmpdir'
require 'puppettest/fakes'
provider_class = Puppet::Type.type(:ssh_authorized_key).provider(:parsed)
@@ -19,7 +18,7 @@ describe provider_class do
before :each do
@sshauthkey_class = Puppet::Type.type(:ssh_authorized_key)
@provider = @sshauthkey_class.provider(:parsed)
- @keyfile = File.join(Dir.tmpdir, 'authorized_keys')
+ @keyfile = tmpfile('authorized_keys')
@provider.any_instance.stubs(:target).returns @keyfile
@user = 'random_bob'
Puppet::Util.stubs(:uid).with(@user).returns 12345
diff --git a/spec/unit/rails/param_value_spec.rb b/spec/unit/rails/param_value_spec.rb
index d6dc7d57b..243456e89 100755
--- a/spec/unit/rails/param_value_spec.rb
+++ b/spec/unit/rails/param_value_spec.rb
@@ -1,6 +1,7 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/rails'
describe "Puppet::Rails::ParamValue" do
confine "Cannot test without ActiveRecord" => Puppet.features.rails?
diff --git a/spec/unit/rails/resource_spec.rb b/spec/unit/rails/resource_spec.rb
index 73c7f7af4..6e23d2020 100755
--- a/spec/unit/rails/resource_spec.rb
+++ b/spec/unit/rails/resource_spec.rb
@@ -1,6 +1,7 @@
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../../spec_helper'
+require 'puppet/rails'
describe "Puppet::Rails::Resource" do
confine "Cannot test without ActiveRecord" => Puppet.features.rails?
diff --git a/spec/unit/rails_spec.rb b/spec/unit/rails_spec.rb
index 01e822ff3..24248e622 100755
--- a/spec/unit/rails_spec.rb
+++ b/spec/unit/rails_spec.rb
@@ -103,9 +103,9 @@ describe Puppet::Rails, "when initializing a mysql connection" do
Puppet.settings.stubs(:value).with(:dbport).returns("")
Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 45).to_s)
Puppet.settings.stubs(:value).with(:dbname).returns("testname")
Puppet.settings.stubs(:value).with(:dbsocket).returns("")
- Puppet.settings.stubs(:value).with(:dbconnections).returns(1)
Puppet::Rails.database_arguments.should == {
:adapter => "mysql",
@@ -113,9 +113,9 @@ describe Puppet::Rails, "when initializing a mysql connection" do
:host => "testserver",
:username => "testuser",
:password => "testpassword",
+ :pool => pool_size,
:database => "testname",
- :reconnect => true,
- :pool => 1
+ :reconnect => true
}
end
@@ -126,9 +126,9 @@ describe Puppet::Rails, "when initializing a mysql connection" do
Puppet.settings.stubs(:value).with(:dbport).returns("9999")
Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 12).to_s)
Puppet.settings.stubs(:value).with(:dbname).returns("testname")
Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
- Puppet.settings.stubs(:value).with(:dbconnections).returns(1)
Puppet::Rails.database_arguments.should == {
:adapter => "mysql",
@@ -137,10 +137,10 @@ describe Puppet::Rails, "when initializing a mysql connection" do
:port => "9999",
:username => "testuser",
:password => "testpassword",
+ :pool => pool_size,
:database => "testname",
:socket => "testsocket",
- :reconnect => true,
- :pool => 1
+ :reconnect => true
}
end
@@ -151,9 +151,9 @@ describe Puppet::Rails, "when initializing a mysql connection" do
Puppet.settings.stubs(:value).with(:dbport).returns("9999")
Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 23).to_s)
Puppet.settings.stubs(:value).with(:dbname).returns("testname")
Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
- Puppet.settings.stubs(:value).with(:dbconnections).returns(1)
Puppet::Rails.database_arguments.should == {
:adapter => "mysql",
@@ -162,12 +162,32 @@ describe Puppet::Rails, "when initializing a mysql connection" do
:port => "9999",
:username => "testuser",
:password => "testpassword",
+ :pool => pool_size,
:database => "testname",
:socket => "testsocket",
- :reconnect => true,
- :pool => 1
+ :reconnect => true
}
end
+
+ it "should not provide the pool if dbconnections is 0, '0', or ''" do
+ Puppet.settings.stubs(:value).with(:dbadapter).returns("mysql")
+ Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
+ Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
+ Puppet.settings.stubs(:value).with(:dbport).returns("9999")
+ Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
+ Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbname).returns("testname")
+ Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
+
+ Puppet.settings.stubs(:value).with(:dbconnections).returns(0)
+ Puppet::Rails.database_arguments.should_not be_include(:pool)
+
+ Puppet.settings.stubs(:value).with(:dbconnections).returns('0')
+ Puppet::Rails.database_arguments.should_not be_include(:pool)
+
+ Puppet.settings.stubs(:value).with(:dbconnections).returns('')
+ Puppet::Rails.database_arguments.should_not be_include(:pool)
+ end
end
describe Puppet::Rails, "when initializing a postgresql connection" do
@@ -180,9 +200,9 @@ describe Puppet::Rails, "when initializing a postgresql connection" do
Puppet.settings.stubs(:value).with(:dbport).returns("9999")
Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 200).to_s)
Puppet.settings.stubs(:value).with(:dbname).returns("testname")
Puppet.settings.stubs(:value).with(:dbsocket).returns("")
- Puppet.settings.stubs(:value).with(:dbconnections).returns(1)
Puppet::Rails.database_arguments.should == {
:adapter => "postgresql",
@@ -191,9 +211,9 @@ describe Puppet::Rails, "when initializing a postgresql connection" do
:port => "9999",
:username => "testuser",
:password => "testpassword",
+ :pool => pool_size,
:database => "testname",
- :reconnect => true,
- :pool => 1
+ :reconnect => true
}
end
@@ -204,9 +224,9 @@ describe Puppet::Rails, "when initializing a postgresql connection" do
Puppet.settings.stubs(:value).with(:dbport).returns("9999")
Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 122).to_s)
Puppet.settings.stubs(:value).with(:dbname).returns("testname")
Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
- Puppet.settings.stubs(:value).with(:dbconnections).returns(1)
Puppet::Rails.database_arguments.should == {
:adapter => "postgresql",
@@ -215,50 +235,90 @@ describe Puppet::Rails, "when initializing a postgresql connection" do
:port => "9999",
:username => "testuser",
:password => "testpassword",
+ :pool => pool_size,
:database => "testname",
:socket => "testsocket",
- :pool => 1,
:reconnect => true
}
end
+
+ it "should not provide the pool if dbconnections is 0, '0', or ''" do
+ Puppet.settings.stubs(:value).with(:dbadapter).returns("mysql")
+ Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
+ Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
+ Puppet.settings.stubs(:value).with(:dbport).returns("9999")
+ Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
+ Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbname).returns("testname")
+ Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
+
+ Puppet.settings.stubs(:value).with(:dbconnections).returns(0)
+ Puppet::Rails.database_arguments.should_not be_include(:pool)
+
+ Puppet.settings.stubs(:value).with(:dbconnections).returns('0')
+ Puppet::Rails.database_arguments.should_not be_include(:pool)
+
+ Puppet.settings.stubs(:value).with(:dbconnections).returns('')
+ Puppet::Rails.database_arguments.should_not be_include(:pool)
+ end
end
describe Puppet::Rails, "when initializing an Oracle connection" do
confine "Cannot test without ActiveRecord" => Puppet.features.rails?
- it "should provide the adapter, log_level, and username, password, dbconnections, and database arguments" do
+ it "should provide the adapter, log_level, and username, password, and database arguments" do
Puppet.settings.stubs(:value).with(:dbadapter).returns("oracle_enhanced")
Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 123).to_s)
Puppet.settings.stubs(:value).with(:dbname).returns("testname")
- Puppet.settings.stubs(:value).with(:dbconnections).returns(1)
Puppet::Rails.database_arguments.should == {
:adapter => "oracle_enhanced",
:log_level => "testlevel",
:username => "testuser",
:password => "testpassword",
- :database => "testname",
- :pool => 1
+ :pool => pool_size,
+ :database => "testname"
}
end
- it "should provide the adapter, log_level, and host, username, password, database, pool, and socket arguments" do
+ it "should provide the adapter, log_level, and host, username, password, database and socket arguments" do
Puppet.settings.stubs(:value).with(:dbadapter).returns("oracle_enhanced")
Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 124).to_s)
Puppet.settings.stubs(:value).with(:dbname).returns("testname")
- Puppet.settings.stubs(:value).with(:dbconnections).returns(1)
Puppet::Rails.database_arguments.should == {
:adapter => "oracle_enhanced",
:log_level => "testlevel",
:username => "testuser",
:password => "testpassword",
- :database => "testname",
- :pool => 1
+ :pool => pool_size,
+ :database => "testname"
}
end
+
+ it "should not provide the pool if dbconnections is 0, '0', or ''" do
+ Puppet.settings.stubs(:value).with(:dbadapter).returns("mysql")
+ Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
+ Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
+ Puppet.settings.stubs(:value).with(:dbport).returns("9999")
+ Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
+ Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbname).returns("testname")
+ Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
+
+ Puppet.settings.stubs(:value).with(:dbconnections).returns(0)
+ Puppet::Rails.database_arguments.should_not be_include(:pool)
+
+ Puppet.settings.stubs(:value).with(:dbconnections).returns('0')
+ Puppet::Rails.database_arguments.should_not be_include(:pool)
+
+ Puppet.settings.stubs(:value).with(:dbconnections).returns('')
+ Puppet::Rails.database_arguments.should_not be_include(:pool)
+ end
end
diff --git a/spec/unit/resource/catalog_spec.rb b/spec/unit/resource/catalog_spec.rb
index 2b6beb5e9..fbfe29ff3 100755
--- a/spec/unit/resource/catalog_spec.rb
+++ b/spec/unit/resource/catalog_spec.rb
@@ -374,7 +374,7 @@ describe Puppet::Resource::Catalog, "when compiling" do
@original.add_edge(@r1,@r2)
@original.filter do |r|
r == @r1
- end.edge(@r1,@r2).should be_empty
+ end.edge?(@r1,@r2).should_not be
end
end
@@ -933,8 +933,8 @@ describe Puppet::Resource::Catalog, "when converting to pson" do
@catalog.add_edge(one, two)
@catalog.add_edge(two, three)
- @catalog.edge(one, two ).expects(:to_pson_data_hash).returns "one_two_pson"
- @catalog.edge(two, three).expects(:to_pson_data_hash).returns "two_three_pson"
+ @catalog.edges_between(one, two )[0].expects(:to_pson_data_hash).returns "one_two_pson"
+ @catalog.edges_between(two, three)[0].expects(:to_pson_data_hash).returns "two_three_pson"
PSON.parse(@catalog.to_pson,:create_additions => false)['data']['edges'].sort.should == %w{one_two_pson two_three_pson}.sort
end
diff --git a/spec/unit/simple_graph_spec.rb b/spec/unit/simple_graph_spec.rb
index 2ca8888c5..fa0bcb06a 100755
--- a/spec/unit/simple_graph_spec.rb
+++ b/spec/unit/simple_graph_spec.rb
@@ -31,12 +31,6 @@ describe Puppet::SimpleGraph do
proc { @graph.to_dot_graph }.should_not raise_error
end
- it "should always put its edges first when printing yaml" do
- @graph = Puppet::SimpleGraph.new
- @graph.add_edge(:one, :two)
- @graph.to_yaml_properties[0].should == "@edges"
- end
-
describe "when managing vertices" do
before do
@graph = Puppet::SimpleGraph.new
@@ -117,16 +111,31 @@ describe Puppet::SimpleGraph do
@graph.edge?(:one, :two).should be_true
end
- it "should provide a method for retrieving an edge label" do
- edge = Puppet::Relationship.new(:one, :two, :callback => :awesome)
- @graph.add_edge(edge)
- @graph.edge_label(:one, :two).should == {:callback => :awesome}
- end
+ describe "when retrieving edges between two nodes" do
+ it "should handle the case of nodes not in the graph" do
+ @graph.edges_between(:one, :two).should == []
+ end
- it "should provide a method for retrieving an edge" do
- edge = Puppet::Relationship.new(:one, :two)
- @graph.add_edge(edge)
- @graph.edge(:one, :two).should equal(edge)
+ it "should handle the case of nodes with no edges between them" do
+ @graph.add_vertex(:one)
+ @graph.add_vertex(:two)
+ @graph.edges_between(:one, :two).should == []
+ end
+
+ it "should handle the case of nodes connected by a single edge" do
+ edge = Puppet::Relationship.new(:one, :two)
+ @graph.add_edge(edge)
+ @graph.edges_between(:one, :two).length.should == 1
+ @graph.edges_between(:one, :two)[0].should equal(edge)
+ end
+
+ it "should handle the case of nodes connected by multiple edges" do
+ edge1 = Puppet::Relationship.new(:one, :two, :callback => :foo)
+ edge2 = Puppet::Relationship.new(:one, :two, :callback => :bar)
+ @graph.add_edge(edge1)
+ @graph.add_edge(edge2)
+ Set.new(@graph.edges_between(:one, :two)).should == Set.new([edge1, edge2])
+ end
end
it "should add the edge source as a vertex if it is not already" do
@@ -253,7 +262,7 @@ describe Puppet::SimpleGraph do
it "should retain labels on edges" do
@graph.add_edge(:one, :two, :callback => :awesome)
- edge = @graph.reversal.edge(:two, :one)
+ edge = @graph.reversal.edges_between(:two, :one)[0]
edge.label.should == {:callback => :awesome}
end
end
@@ -522,14 +531,14 @@ describe Puppet::SimpleGraph do
it "should not add labels to edges that have none" do
@depgraph.add_edge(@two, @three)
splice
- @depgraph.edge_label("c", "i").should == {}
+ @depgraph.edges_between("c", "i")[0].label.should == {}
end
it "should copy labels over edges that have none" do
@depgraph.add_edge("c", @three, {:callback => :refresh})
splice
# And make sure the label got copied.
- @depgraph.edge_label("c", "i").should == {:callback => :refresh}
+ @depgraph.edges_between("c", "i")[0].label.should == {:callback => :refresh}
end
it "should not replace a label with a nil label" do
@@ -537,7 +546,7 @@ describe Puppet::SimpleGraph do
@depgraph.add_edge(@middle, @three)
@depgraph.add_edge("c", @three, {:callback => :refresh})
splice
- @depgraph.edge_label("c", "i").should == {:callback => :refresh}
+ @depgraph.edges_between("c", "i")[0].label.should == {:callback => :refresh}
end
it "should copy labels to all created edges" do
@@ -547,8 +556,207 @@ describe Puppet::SimpleGraph do
@three.each do |child|
edge = Puppet::Relationship.new("c", child)
@depgraph.should be_edge(edge.source, edge.target)
- @depgraph.edge_label(edge.source, edge.target).should == {:callback => :refresh}
+ @depgraph.edges_between(edge.source, edge.target)[0].label.should == {:callback => :refresh}
+ end
+ end
+ end
+
+ it "should serialize to YAML using the old format by default" do
+ Puppet::SimpleGraph.use_new_yaml_format.should == false
+ end
+
+ describe "(yaml tests)" do
+ def empty_graph(graph)
+ end
+
+ def one_vertex_graph(graph)
+ graph.add_vertex(:a)
+ end
+
+ def graph_without_edges(graph)
+ [:a, :b, :c].each { |x| graph.add_vertex(x) }
+ end
+
+ def one_edge_graph(graph)
+ graph.add_edge(:a, :b)
+ end
+
+ def many_edge_graph(graph)
+ graph.add_edge(:a, :b)
+ graph.add_edge(:a, :c)
+ graph.add_edge(:b, :d)
+ graph.add_edge(:c, :d)
+ end
+
+ def labeled_edge_graph(graph)
+ graph.add_edge(:a, :b, :callback => :foo, :event => :bar)
+ end
+
+ def overlapping_edge_graph(graph)
+ graph.add_edge(:a, :b, :callback => :foo, :event => :bar)
+ graph.add_edge(:a, :b, :callback => :biz, :event => :baz)
+ end
+
+ def self.all_test_graphs
+ [:empty_graph, :one_vertex_graph, :graph_without_edges, :one_edge_graph, :many_edge_graph, :labeled_edge_graph,
+ :overlapping_edge_graph]
+ end
+
+ def object_ids(enumerable)
+ # Return a sorted list of the object id's of the elements of an
+ # enumerable.
+ enumerable.collect { |x| x.object_id }.sort
+ end
+
+ def graph_to_yaml(graph, which_format)
+ previous_use_new_yaml_format = Puppet::SimpleGraph.use_new_yaml_format
+ Puppet::SimpleGraph.use_new_yaml_format = (which_format == :new)
+ ZAML.dump(graph)
+ ensure
+ Puppet::SimpleGraph.use_new_yaml_format = previous_use_new_yaml_format
+ end
+
+ # Test serialization of graph to YAML.
+ [:old, :new].each do |which_format|
+ all_test_graphs.each do |graph_to_test|
+ it "should be able to serialize #{graph_to_test} to YAML (#{which_format} format)" do
+ graph = Puppet::SimpleGraph.new
+ send(graph_to_test, graph)
+ yaml_form = graph_to_yaml(graph, which_format)
+
+ # Hack the YAML so that objects in the Puppet namespace get
+ # changed to YAML::DomainType objects. This lets us inspect
+ # the serialized objects easily without invoking any
+ # yaml_initialize hooks.
+ yaml_form.gsub!('!ruby/object:Puppet::', '!hack/object:Puppet::')
+ serialized_object = YAML.load(yaml_form)
+
+ # Check that the object contains instance variables @edges and
+ # @vertices only. @reversal is also permitted, but we don't
+ # check it, because it is going to be phased out.
+ serialized_object.type_id.should == 'object:Puppet::SimpleGraph'
+ serialized_object.value.keys.reject { |x| x == 'reversal' }.sort.should == ['edges', 'vertices']
+
+ # Check edges by forming a set of tuples (source, target,
+ # callback, event) based on the graph and the YAML and make sure
+ # they match.
+ edges = serialized_object.value['edges']
+ edges.should be_a(Array)
+ expected_edge_tuples = graph.edges.collect { |edge| [edge.source, edge.target, edge.callback, edge.event] }
+ actual_edge_tuples = edges.collect do |edge|
+ edge.type_id.should == 'object:Puppet::Relationship'
+ %w{source target}.each { |x| edge.value.keys.should include(x) }
+ edge.value.keys.each { |x| ['source', 'target', 'callback', 'event'].should include(x) }
+ %w{source target callback event}.collect { |x| edge.value[x] }
+ end
+ Set.new(actual_edge_tuples).should == Set.new(expected_edge_tuples)
+ actual_edge_tuples.length.should == expected_edge_tuples.length
+
+ # Check vertices one by one.
+ vertices = serialized_object.value['vertices']
+ if which_format == :old
+ vertices.should be_a(Hash)
+ Set.new(vertices.keys).should == Set.new(graph.vertices)
+ vertices.each do |key, value|
+ value.type_id.should == 'object:Puppet::SimpleGraph::VertexWrapper'
+ value.value.keys.sort.should == %w{adjacencies vertex}
+ value.value['vertex'].should equal(key)
+ adjacencies = value.value['adjacencies']
+ adjacencies.should be_a(Hash)
+ Set.new(adjacencies.keys).should == Set.new([:in, :out])
+ [:in, :out].each do |direction|
+ adjacencies[direction].should be_a(Hash)
+ expected_adjacent_vertices = Set.new(graph.adjacent(key, :direction => direction, :type => :vertices))
+ Set.new(adjacencies[direction].keys).should == expected_adjacent_vertices
+ adjacencies[direction].each do |adj_key, adj_value|
+ # Since we already checked edges, just check consistency
+ # with edges.
+ desired_source = direction == :in ? adj_key : key
+ desired_target = direction == :in ? key : adj_key
+ expected_edges = edges.select do |edge|
+ edge.value['source'] == desired_source && edge.value['target'] == desired_target
+ end
+ adj_value.should be_a(Set)
+ if object_ids(adj_value) != object_ids(expected_edges)
+ raise "For vertex #{key.inspect}, direction #{direction.inspect}: expected adjacencies #{expected_edges.inspect} but got #{adj_value.inspect}"
+ end
+ end
+ end
+ end
+ else
+ vertices.should be_a(Array)
+ Set.new(vertices).should == Set.new(graph.vertices)
+ vertices.length.should == graph.vertices.length
+ end
+ end
+ end
+
+ # Test deserialization of graph from YAML. This presumes the
+ # correctness of serialization to YAML, which has already been
+ # tested.
+ all_test_graphs.each do |graph_to_test|
+ it "should be able to deserialize #{graph_to_test} from YAML (#{which_format} format)" do
+ reference_graph = Puppet::SimpleGraph.new
+ send(graph_to_test, reference_graph)
+ yaml_form = graph_to_yaml(reference_graph, which_format)
+ recovered_graph = YAML.load(yaml_form)
+
+ # Test that the recovered vertices match the vertices in the
+ # reference graph.
+ expected_vertices = reference_graph.vertices.to_a
+ recovered_vertices = recovered_graph.vertices.to_a
+ Set.new(recovered_vertices).should == Set.new(expected_vertices)
+ recovered_vertices.length.should == expected_vertices.length
+
+ # Test that the recovered edges match the edges in the
+ # reference graph.
+ expected_edge_tuples = reference_graph.edges.collect do |edge|
+ [edge.source, edge.target, edge.callback, edge.event]
+ end
+ recovered_edge_tuples = recovered_graph.edges.collect do |edge|
+ [edge.source, edge.target, edge.callback, edge.event]
+ end
+ Set.new(recovered_edge_tuples).should == Set.new(expected_edge_tuples)
+ recovered_edge_tuples.length.should == expected_edge_tuples.length
+
+ # We ought to test that the recovered graph is self-consistent
+ # too. But we're not going to bother with that yet because
+ # the internal representation of the graph is about to change.
+ end
+ end
+
+ it "should be able to serialize a graph where the vertices contain backreferences to the graph (#{which_format} format)" do
+ reference_graph = Puppet::SimpleGraph.new
+ vertex = Object.new
+ vertex.instance_eval { @graph = reference_graph }
+ reference_graph.add_edge(vertex, :other_vertex)
+ yaml_form = graph_to_yaml(reference_graph, which_format)
+ recovered_graph = YAML.load(yaml_form)
+
+ recovered_graph.vertices.length.should == 2
+ recovered_vertex = recovered_graph.vertices.reject { |x| x.is_a?(Symbol) }[0]
+ recovered_vertex.instance_eval { @graph }.should equal(recovered_graph)
+ recovered_graph.edges.length.should == 1
+ recovered_edge = recovered_graph.edges[0]
+ recovered_edge.source.should equal(recovered_vertex)
+ recovered_edge.target.should == :other_vertex
+ end
+ end
+
+ it "should serialize properly when used as a base class" do
+ class Puppet::TestDerivedClass < Puppet::SimpleGraph
+ attr_accessor :foo
end
+ derived = Puppet::TestDerivedClass.new
+ derived.add_edge(:a, :b)
+ derived.foo = 1234
+ recovered_derived = YAML.load(YAML.dump(derived))
+ recovered_derived.class.should equal(Puppet::TestDerivedClass)
+ recovered_derived.edges.length.should == 1
+ recovered_derived.edges[0].source.should == :a
+ recovered_derived.edges[0].target.should == :b
+ recovered_derived.vertices.length.should == 2
+ recovered_derived.foo.should == 1234
end
end
end
diff --git a/spec/unit/transaction/report_spec.rb b/spec/unit/transaction/report_spec.rb
index 7e0b0554b..b310713d2 100755
--- a/spec/unit/transaction/report_spec.rb
+++ b/spec/unit/transaction/report_spec.rb
@@ -225,8 +225,19 @@ describe Puppet::Transaction::Report do
@report.calculate_metrics
end
- %w{Changes Total Resources}.each do |main|
- it "should include information on #{main} in the summary" do
+ %w{changes time resources events}.each do |main|
+ it "should include the key #{main} in the raw summary hash" do
+ @report.raw_summary.should be_key main
+ end
+ end
+
+ it "should include the last run time in the raw summary hash" do
+ Time.stubs(:now).returns(Time.utc(2010,11,10,12,0,24))
+ @report.raw_summary["time"]["last_run"].should == 1289390424
+ end
+
+ %w{Changes Total Resources Time Events}.each do |main|
+ it "should include information on #{main} in the textual summary" do
@report.summary.should be_include(main)
end
end
diff --git a/spec/unit/type/host_spec.rb b/spec/unit/type/host_spec.rb
new file mode 100755
index 000000000..12ae2af08
--- /dev/null
+++ b/spec/unit/type/host_spec.rb
@@ -0,0 +1,83 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+ssh_authorized_key = Puppet::Type.type(:ssh_authorized_key)
+
+describe Puppet::Type.type(:host) do
+ before do
+ @class = Puppet::Type.type(:host)
+ @catalog = Puppet::Resource::Catalog.new
+ end
+
+ it "should have :name be its namevar" do
+ @class.key_attributes.should == [:name]
+ end
+
+ describe "when validating attributes" do
+ [:name, :provider ].each do |param|
+ it "should have a #{param} parameter" do
+ @class.attrtype(param).should == :param
+ end
+ end
+
+ [:ip, :target, :host_aliases, :comment, :ensure].each do |property|
+ it "should have a #{property} property" do
+ @class.attrtype(property).should == :property
+ end
+ end
+ end
+
+ describe "when validating values" do
+ it "should support present as a value for ensure" do
+ proc { @class.new(:name => "foo", :ensure => :present) }.should_not raise_error
+ end
+
+ it "should support absent as a value for ensure" do
+ proc { @class.new(:name => "foo", :ensure => :absent) }.should_not raise_error
+ end
+
+ it "should accept IPv4 addresses" do
+ proc { @class.new(:name => "foo", :ip => '10.96.0.1') }.should_not raise_error
+ end
+
+ it "should accept long IPv6 addresses" do
+ # Taken from wikipedia article about ipv6
+ proc { @class.new(:name => "foo", :ip => '2001:0db8:85a3:08d3:1319:8a2e:0370:7344') }.should_not raise_error
+ end
+
+ it "should accept one host_alias" do
+ proc { @class.new(:name => "foo", :host_aliases => 'alias1') }.should_not raise_error
+ end
+
+ it "should accept multiple host_aliases" do
+ proc { @class.new(:name => "foo", :host_aliases => [ 'alias1', 'alias2' ]) }.should_not raise_error
+ end
+
+ it "should accept shortened IPv6 addresses" do
+ proc { @class.new(:name => "foo", :ip => '2001:db8:0:8d3:0:8a2e:70:7344') }.should_not raise_error
+ proc { @class.new(:name => "foo", :ip => '::ffff:192.0.2.128') }.should_not raise_error
+ proc { @class.new(:name => "foo", :ip => '::1') }.should_not raise_error
+ end
+
+ it "should not accept malformed IPv4 addresses like 192.168.0.300" do
+ proc { @class.new(:name => "foo", :ip => '192.168.0.300') }.should raise_error
+ end
+
+ it "should not accept malformed IP addresses like 2001:0dg8:85a3:08d3:1319:8a2e:0370:7344" do
+ proc { @class.new(:name => "foo", :ip => '2001:0dg8:85a3:08d3:1319:8a2e:0370:7344') }.should raise_error
+ end
+
+ it "should not accept spaces in resourcename" do
+ proc { @class.new(:name => "foo bar") }.should raise_error
+ end
+
+ it "should not accept host_aliases with spaces" do
+ proc { @class.new(:name => "foo", :host_aliases => [ 'well_formed', 'not wellformed' ]) }.should raise_error
+ end
+
+ it "should not accept empty host_aliases" do
+ proc { @class.new(:name => "foo", :host_aliases => ['alias1','']) }.should raise_error
+ end
+ end
+end
diff --git a/spec/unit/type/schedule_spec.rb b/spec/unit/type/schedule_spec.rb
index 420cffd44..8305431a6 100755
--- a/spec/unit/type/schedule_spec.rb
+++ b/spec/unit/type/schedule_spec.rb
@@ -13,14 +13,6 @@ module ScheduleTesting
Time.at(diff)
end
- def month(method, count)
- diff(:hour, 3600 * 24 * 30, method, count)
- end
-
- def week(method, count)
- diff(:hour, 3600 * 24 * 7, method, count)
- end
-
def day(method, count)
diff(:hour, 3600 * 24, method, count)
end
@@ -33,10 +25,6 @@ module ScheduleTesting
diff(:min, 60, method, count)
end
- def sec(method, count)
- diff(:sec, 1, method, count)
- end
-
end
describe Puppet::Type.type(:schedule) do
@@ -194,26 +182,18 @@ describe Puppet::Type.type(:schedule) do
end
it "should match if the times are one minute apart and the current minute is 0" do
- current = Time.now
+ current = Time.utc(2008, 1, 1, 0, 0, 0)
+ previous = Time.utc(2007, 12, 31, 23, 59, 0)
- # Subtract an hour, reset the minute to zero, then add 59 minutes, so we're the previous hour plus 59 minutes.
- previous = (current - 3600 - (current.min * 60) + (59 * 60))
-
- # Now set the "current" time to the zero minute of the current hour.
- now = (current - (current.min * 60))
- Time.stubs(:now).returns(now)
+ Time.stubs(:now).returns(current)
@schedule.match?(previous).should be_true
end
- it "should not match if the times are 58 minutes apart and the current minute is 59" do
- current = Time.now
+ it "should not match if the times are 59 minutes apart and the current minute is 59" do
+ current = Time.utc(2009, 2, 1, 12, 59, 0)
+ previous = Time.utc(2009, 2, 1, 12, 0, 0)
- # reset the minute to zero
- previous = current - (current.min * 60)
-
- # Now set the "current" time to the 59th minute of the current hour.
- now = (current - (current.min * 60) + (59 * 60))
- Time.stubs(:now).returns(now)
+ Time.stubs(:now).returns(current)
@schedule.match?(previous).should be_false
end
end
@@ -227,10 +207,7 @@ describe Puppet::Type.type(:schedule) do
end
it "should match if the times are one minute apart and the current minute and hour are 0" do
- zero = Time.now
-
- # Reset the current time to X:00:00
- current = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec
+ current = Time.utc(2010, "nov", 7, 0, 0, 0)
# Now set the previous time to one minute before that
previous = current - 60
@@ -240,10 +217,9 @@ describe Puppet::Type.type(:schedule) do
end
it "should not match if the times are 23 hours and 58 minutes apart and the current hour is 23 and the current minute is 59" do
- zero = Time.now
# Reset the previous time to 00:00:00
- previous = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec
+ previous = Time.utc(2010, "nov", 7, 0, 0, 0)
# Set the current time to 23:59
now = previous + (23 * 3600) + (59 * 60)
@@ -262,19 +238,17 @@ describe Puppet::Type.type(:schedule) do
end
it "should match if the previous time is prior to the most recent Sunday" do
- now = Time.now
-
- # Subtract the number days we've progressed into the week, plus one because we're zero-indexed.
- previous = now - (3600 * 24 * (now.wday + 1))
+ now = Time.utc(2010, "nov", 11, 0, 0, 0) # Thursday
+ Time.stubs(:now).returns(now)
+ previous = Time.utc(2010, "nov", 6, 23, 59, 59) # Sat
@schedule.match?(previous).should be_true
end
it "should not match if the previous time is after the most recent Saturday" do
- now = Time.now
-
- # Subtract the number days we've progressed into the week
- previous = now - (3600 * 24 * now.wday)
+ now = Time.utc(2010, "nov", 11, 0, 0, 0) # Thursday
+ Time.stubs(:now).returns(now)
+ previous = Time.utc(2010, "nov", 7, 0, 0, 0) # Sunday
@schedule.match?(previous).should be_false
end
@@ -289,19 +263,17 @@ describe Puppet::Type.type(:schedule) do
end
it "should match when the previous time is prior to the first day of this month" do
- now = Time.now
-
- # Subtract the number days we've progressed into the month
- previous = now - (3600 * 24 * now.day)
+ now = Time.utc(2010, "nov", 8, 00, 59, 59)
+ Time.stubs(:now).returns(now)
+ previous = Time.utc(2010, "oct", 31, 23, 59, 59)
@schedule.match?(previous).should be_true
end
it "should not match when the previous time is after the last day of last month" do
- now = Time.now
-
- # Subtract the number days we've progressed into the month, minus one
- previous = now - (3600 * 24 * (now.day - 1))
+ now = Time.utc(2010, "nov", 8, 00, 59, 59)
+ Time.stubs(:now).returns(now)
+ previous = Time.utc(2010, "nov", 1, 0, 0, 0)
@schedule.match?(previous).should be_false
end
diff --git a/spec/unit/util/command_line_spec.rb b/spec/unit/util/command_line_spec.rb
index a83ad968d..7ba965249 100644
--- a/spec/unit/util/command_line_spec.rb
+++ b/spec/unit/util/command_line_spec.rb
@@ -86,7 +86,7 @@ describe Puppet::Util::CommandLine do
describe "when the subcommand is not implemented" do
it "should find and invoke an executable with a hyphenated name" do
commandline = Puppet::Util::CommandLine.new("puppet", ['whatever', 'argument'], @tty)
- Puppet::Util.expects(:binary).with('puppet-whatever').returns('/dev/null/puppet-whatever')
+ Puppet::Util.expects(:which).with('puppet-whatever').returns('/dev/null/puppet-whatever')
commandline.expects(:system).with('/dev/null/puppet-whatever', 'argument')
commandline.execute
@@ -95,7 +95,7 @@ describe Puppet::Util::CommandLine do
describe "and an external implementation cannot be found" do
it "should abort and show the usage message" do
commandline = Puppet::Util::CommandLine.new("puppet", ['whatever', 'argument'], @tty)
- Puppet::Util.expects(:binary).with('puppet-whatever').returns(nil)
+ Puppet::Util.expects(:which).with('puppet-whatever').returns(nil)
commandline.expects(:system).never
commandline.expects(:usage_message).returns("the usage message")
diff --git a/spec/unit/util/file_locking_spec.rb b/spec/unit/util/file_locking_spec.rb
index 10051060c..8fafb1d52 100755
--- a/spec/unit/util/file_locking_spec.rb
+++ b/spec/unit/util/file_locking_spec.rb
@@ -32,17 +32,12 @@ describe Puppet::Util::FileLocking do
end
it "should use a global shared mutex" do
- @sync = mock 'sync'
- @sync.expects(:synchronize).with(Sync::SH).once
- Puppet::Util.expects(:sync).with('/file').returns @sync
-
+ Puppet::Util.expects(:synchronize_on).with('/file',Sync::SH).once
Puppet::Util::FileLocking.readlock '/file'
end
it "should use a shared lock on the file" do
- @sync = mock 'sync'
- @sync.stubs(:synchronize).yields
- Puppet::Util.expects(:sync).with('/file').returns @sync
+ Puppet::Util.expects(:synchronize_on).with('/file',Sync::SH).yields
fh = mock 'filehandle'
File.expects(:open).with("/file").yields fh
@@ -59,9 +54,7 @@ describe Puppet::Util::FileLocking do
end
it "should create missing files" do
- @sync = mock 'sync'
- @sync.stubs(:synchronize).yields
- Puppet::Util.expects(:sync).with('/file').returns @sync
+ Puppet::Util.expects(:synchronize_on).with('/file',Sync::SH).yields
File.expects(:exists?).with('/file').returns false
File.expects(:open).with('/file').once
@@ -72,9 +65,7 @@ describe Puppet::Util::FileLocking do
describe "when acquiring a write lock" do
before do
- @sync = mock 'sync'
- Puppet::Util.stubs(:sync).returns @sync
- @sync.stubs(:synchronize).yields
+ Puppet::Util.stubs(:synchronize_on).yields
File.stubs(:file?).with('/file').returns true
File.stubs(:exists?).with('/file').returns true
end
@@ -88,29 +79,26 @@ describe Puppet::Util::FileLocking do
end
it "should use a global exclusive mutex" do
- sync = mock 'sync'
- sync.expects(:synchronize).with(Sync::EX)
- Puppet::Util.expects(:sync).with("/file").returns sync
-
+ Puppet::Util.expects(:synchronize_on).with("/file",Sync::EX)
Puppet::Util::FileLocking.writelock '/file'
end
it "should use any specified mode when opening the file" do
- File.expects(:open).with("/file", "w", :mymode)
+ File.expects(:open).with("/file", File::Constants::CREAT | File::Constants::WRONLY , :mymode)
Puppet::Util::FileLocking.writelock('/file', :mymode)
end
it "should use the mode of the existing file if no mode is specified" do
File.expects(:stat).with("/file").returns(mock("stat", :mode => 0755))
- File.expects(:open).with("/file", "w", 0755)
+ File.expects(:open).with("/file", File::Constants::CREAT | File::Constants::WRONLY, 0755)
Puppet::Util::FileLocking.writelock('/file')
end
it "should use 0600 as the mode if no mode is specified and the file does not exist" do
File.expects(:stat).raises(Errno::ENOENT)
- File.expects(:open).with("/file", "w", 0600)
+ File.expects(:open).with("/file", File::Constants::CREAT | File::Constants::WRONLY, 0600)
Puppet::Util::FileLocking.writelock('/file')
end
@@ -130,6 +118,8 @@ describe Puppet::Util::FileLocking do
lfh = mock 'locked_filehandle'
fh.expects(:lock_exclusive).yields(lfh)
+ lfh.stubs(:seek)
+ lfh.stubs(:truncate)
lfh.expects(:print).with "foo"
Puppet::Util::FileLocking.writelock('/file') do |f|
@@ -137,18 +127,32 @@ describe Puppet::Util::FileLocking do
end
end
+ it "should truncate the file under an exclusive lock" do
+ fh = mock 'fh'
+ File.expects(:open).yields fh
+
+ lfh = mock 'locked_filehandle'
+ fh.expects(:lock_exclusive).yields(lfh)
+
+ lfh.expects(:seek).with(0, IO::SEEK_SET)
+ lfh.expects(:truncate).with(0)
+ lfh.stubs(:print)
+
+ Puppet::Util::FileLocking.writelock('/file') do |f|
+ f.print "foo"
+ end
+ end
+
it "should only work on regular files" do
File.expects(:file?).with('/file').returns false
proc { Puppet::Util::FileLocking.writelock('/file') }.should raise_error(ArgumentError)
end
it "should create missing files" do
- @sync = mock 'sync'
- @sync.stubs(:synchronize).yields
- Puppet::Util.expects(:sync).with('/file').returns @sync
+ Puppet::Util.expects(:synchronize_on).with('/file',Sync::EX).yields
File.expects(:exists?).with('/file').returns false
- File.expects(:open).with('/file', 'w', 0600).once
+ File.expects(:open).with('/file', File::Constants::CREAT | File::Constants::WRONLY, 0600).once
Puppet::Util::FileLocking.writelock('/file')
end
diff --git a/spec/unit/util/log_spec.rb b/spec/unit/util/log_spec.rb
index 7d96fe190..ea5d59859 100755
--- a/spec/unit/util/log_spec.rb
+++ b/spec/unit/util/log_spec.rb
@@ -7,7 +7,7 @@ require 'puppet/util/log'
describe Puppet::Util::Log do
it "should write a given message to the specified destination" do
arraydest = []
- Puppet::Util::Log.newdestination(arraydest)
+ Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(arraydest))
Puppet::Util::Log.new(:level => :notice, :message => "foo")
message = arraydest.last.message
message.should == "foo"
@@ -87,7 +87,7 @@ describe Puppet::Util::Log do
it "should flush the log queue when the first destination is specified" do
Puppet::Util::Log.close_all
Puppet::Util::Log.expects(:flushqueue)
- Puppet::Util::Log.newdestination([])
+ Puppet::Util::Log.newdestination(:console)
end
it "should convert the level to a symbol if it's passed in as a string" do
diff --git a/spec/unit/util/monkey_patches_spec.rb b/spec/unit/util/monkey_patches_spec.rb
index b0f61c808..049ed1044 100644
--- a/spec/unit/util/monkey_patches_spec.rb
+++ b/spec/unit/util/monkey_patches_spec.rb
@@ -5,3 +5,29 @@ Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f
require 'puppet/util/monkey_patches'
+
+describe "yaml deserialization" do
+ it "should call yaml_initialize when deserializing objects that have that method defined" do
+ class Puppet::TestYamlInitializeClass
+ attr_reader :foo
+
+ def yaml_initialize(tag, var)
+ var.should == {'foo' => 100}
+ instance_variables.should == []
+ @foo = 200
+ end
+ end
+
+ obj = YAML.load("--- !ruby/object:Puppet::TestYamlInitializeClass\n foo: 100")
+ obj.foo.should == 200
+ end
+
+ it "should not call yaml_initialize if not defined" do
+ class Puppet::TestYamlNonInitializeClass
+ attr_reader :foo
+ end
+
+ obj = YAML.load("--- !ruby/object:Puppet::TestYamlNonInitializeClass\n foo: 100")
+ obj.foo.should == 100
+ end
+end
diff --git a/spec/unit/util/pson_spec.rb b/spec/unit/util/pson_spec.rb
index d02d28517..474ddafa4 100755
--- a/spec/unit/util/pson_spec.rb
+++ b/spec/unit/util/pson_spec.rb
@@ -35,4 +35,19 @@ describe Puppet::Util::Pson do
bin_string = (1..20000).collect { |i| ((17*i+13*i*i) % 255).chr }.join
PSON.parse(%Q{{ "type": "foo", "data": #{bin_string.to_pson} }})["data"].should == bin_string
end
+
+ it "should be able to handle UTF8 that isn't a real unicode character" do
+ s = ["\355\274\267"]
+ PSON.parse( [s].to_pson ).should == [s]
+ end
+
+ it "should be able to handle UTF8 for \\xFF" do
+ s = ["\xc3\xbf"]
+ PSON.parse( [s].to_pson ).should == [s]
+ end
+
+ it "should be able to handle invalid UTF8 bytes" do
+ s = ["\xc3\xc3"]
+ PSON.parse( [s].to_pson ).should == [s]
+ end
end
diff --git a/spec/unit/util/rdoc_spec.rb b/spec/unit/util/rdoc_spec.rb
index 58c2034ee..41d4b9cd0 100755
--- a/spec/unit/util/rdoc_spec.rb
+++ b/spec/unit/util/rdoc_spec.rb
@@ -43,12 +43,20 @@ describe Puppet::Util::RDoc do
Puppet::Util::RDoc.rdoc("output", [], "utf-8")
end
- it "should tell RDoc to force updates of indices" do
+ it "should tell RDoc to force updates of indices when RDoc supports it" do
+ Options::OptionList.stubs(:options).returns([["--force-update", "-U", 0 ]])
@rdoc.expects(:document).with { |args| args.include?("--force-update") }
Puppet::Util::RDoc.rdoc("output", [])
end
+ it "should not tell RDoc to force updates of indices when RDoc doesn't support it" do
+ Options::OptionList.stubs(:options).returns([])
+ @rdoc.expects(:document).never.with { |args| args.include?("--force-update") }
+
+ Puppet::Util::RDoc.rdoc("output", [])
+ end
+
it "should tell RDoc to use the given outputdir" do
@rdoc.expects(:document).with { |args| args.include?("--op") and args.include?("myoutputdir") }
diff --git a/spec/unit/util/storage_spec.rb b/spec/unit/util/storage_spec.rb
index 6c8baba1f..ae3cbc2ae 100755
--- a/spec/unit/util/storage_spec.rb
+++ b/spec/unit/util/storage_spec.rb
@@ -3,15 +3,14 @@
require File.dirname(__FILE__) + '/../../spec_helper'
require 'yaml'
-require 'tempfile'
-
require 'puppet/util/storage'
describe Puppet::Util::Storage do
+ include PuppetSpec::Files
before(:all) do
@basepath = Puppet.features.posix? ? "/somepath" : "C:/somepath"
- Puppet[:statedir] = Dir.tmpdir
+ Puppet[:statedir] = tmpdir("statedir")
end
after(:all) do
diff --git a/spec/unit/util/zaml_spec.rb b/spec/unit/util/zaml_spec.rb
index b223f89d4..358c6aa11 100755
--- a/spec/unit/util/zaml_spec.rb
+++ b/spec/unit/util/zaml_spec.rb
@@ -61,4 +61,3 @@ describe "Pure ruby yaml implementation" do
x2[2].should equal(x2)
end
end
-
diff --git a/test/data/providers/host/parsed/valid_hosts b/test/data/providers/host/parsed/valid_hosts
new file mode 100644
index 000000000..24636295d
--- /dev/null
+++ b/test/data/providers/host/parsed/valid_hosts
@@ -0,0 +1,19 @@
+# Some leading comment, that should be ignored
+# The next line is empty so it should be ignored
+
+::1 localhost
+
+# We now try another delimiter: Several tabs
+127.0.0.1 localhost
+
+# No test trailing spaces
+10.0.0.1 host1
+
+# Ok its time to test aliases
+2001:252:0:1::2008:8 ipv6host alias1
+192.168.0.1 ipv4host alias2 alias3
+
+# Testing inlinecomments now
+192.168.0.2 host3 # This is host3
+192.168.0.3 host4 alias10 # This is host4
+192.168.0.4 host5 alias11 alias12 # This is host5
diff --git a/test/lib/puppettest.rb b/test/lib/puppettest.rb
index 0b3a89a72..a60092cf7 100755
--- a/test/lib/puppettest.rb
+++ b/test/lib/puppettest.rb
@@ -185,7 +185,7 @@ module PuppetTest
#if rake? or ! Puppet[:debug]
#if defined?($puppet_debug) or ! rake?
Puppet[:color] = false if textmate?
- Puppet::Util::Log.newdestination(@logs)
+ Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(@logs))
if defined? $console
Puppet.info @method_name
Puppet::Util::Log.newdestination(:console)
@@ -305,7 +305,7 @@ module PuppetTest
def logstore
@logs = []
- Puppet::Util::Log.newdestination(@logs)
+ Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(@logs))
end
end
diff --git a/test/other/provider.rb b/test/other/provider.rb
index 052d7a0d0..a539ee5a7 100755
--- a/test/other/provider.rb
+++ b/test/other/provider.rb
@@ -70,24 +70,13 @@ class TestImpl < Test::Unit::TestCase
child = @type.provide("child", :parent => parent.name) {}
}
- assert_nothing_raised {
- child.commands :which => "which"
- }
-
- assert(child.command(:which), "Did not find 'which' command")
-
- assert(child.command(:which) =~ /^\//,
- "Command did not become fully qualified")
- assert(FileTest.exists?(child.command(:which)),
- "Did not find actual 'which' binary")
-
assert_raise(Puppet::DevError) do
child.command(:nosuchcommand)
end
# Now create a parent command
assert_nothing_raised {
- parent.commands :sh => Puppet::Util.binary('sh')
+ parent.commands :sh => Puppet::Util.which('sh')
}
assert(parent.command(:sh), "Did not find 'sh' command")
diff --git a/test/puppet/tc_suidmanager.rb b/test/puppet/tc_suidmanager.rb
index 449f2aef5..eeb56f2c9 100755
--- a/test/puppet/tc_suidmanager.rb
+++ b/test/puppet/tc_suidmanager.rb
@@ -80,20 +80,11 @@ class TestSUIDManager < Test::Unit::TestCase
warn "Cannot run this test on ruby < 1.8.4"
else
set_exit_status!
-
-
- Puppet::Util.expects(:execute).with(
- 'yay',
- { :failonfail => false,
- :uid => @user.uid,
-
- :gid => @user.gid }
- ).returns('output')
-
-
- output = Puppet::Util::SUIDManager.run_and_capture 'yay',
- @user.uid,
- @user.gid
+ Puppet::Util.
+ expects(:execute).
+ with('yay',:combine => true, :failonfail => false, :uid => @user.uid, :gid => @user.gid).
+ returns('output')
+ output = Puppet::Util::SUIDManager.run_and_capture 'yay', @user.uid, @user.gid
assert_equal 'output', output.first
assert_kind_of Process::Status, output.last
diff --git a/test/ral/manager/type.rb b/test/ral/manager/type.rb
index 7df643005..145877722 100755
--- a/test/ral/manager/type.rb
+++ b/test/ral/manager/type.rb
@@ -276,7 +276,7 @@ class TestType < Test::Unit::TestCase
def test_isomorphic_names
catalog = mk_catalog
# First do execs, since they're not isomorphic.
- echo = Puppet::Util.binary "echo"
+ echo = Puppet::Util.which "echo"
exec1 = exec2 = nil
assert_nothing_raised do
diff --git a/test/ral/providers/host/parsed.rb b/test/ral/providers/host/parsed.rb
index c2367d566..955edd5d3 100755
--- a/test/ral/providers/host/parsed.rb
+++ b/test/ral/providers/host/parsed.rb
@@ -67,7 +67,8 @@ class TestParsedHostProvider < Test::Unit::TestCase
# Make sure we convert both directlys correctly using a simple host.
def test_basic_isomorphism
- hash = {:record_type => :parsed, :name => "myhost", :ip => "192.168.43.56", :host_aliases => %w{another host}}
+ hash = {:record_type => :parsed, :name => "myhost", :ip => "192.168.43.56", :host_aliases => %w{another host},
+ :comment => ''}
str = nil
assert_nothing_raised do
@@ -105,11 +106,13 @@ class TestParsedHostProvider < Test::Unit::TestCase
[
{:record_type => :comment, :line => "# comment one"},
{:record_type => :blank, :line => ""},
- {:record_type => :parsed, :name => "myhost", :ip => "192.168.43.56", :host_aliases => %w{another host}},
+ {:record_type => :parsed, :name => "myhost", :ip => "192.168.43.56", :host_aliases => %w{another host},
+ :comment => ''},
{:record_type => :blank, :line => " "},
{:record_type => :comment, :line => "# another comment"},
- {:record_type => :parsed, :name => "anotherhost", :ip => "192.168.43.57", :host_aliases => []}
+ {:record_type => :parsed, :name => "anotherhost", :ip => "192.168.43.57", :host_aliases => [],
+ :comment => ''}
], instances)
newtext = nil
diff --git a/test/ral/providers/provider.rb b/test/ral/providers/provider.rb
index cb0b2a19e..f46e03f82 100755
--- a/test/ral/providers/provider.rb
+++ b/test/ral/providers/provider.rb
@@ -9,7 +9,7 @@ class TestProvider < Test::Unit::TestCase
include PuppetTest
def echo
- echo = Puppet::Util.binary("echo")
+ echo = Puppet::Util.which("echo")
raise "Could not find 'echo' binary; cannot complete test" unless echo
@@ -95,7 +95,7 @@ class TestProvider < Test::Unit::TestCase
provider.commands :testing => "/no/such/path"
- provider.stubs(:binary).returns "/no/such/path"
+ provider.stubs(:which).returns "/no/such/path"
provider.command(:testing)
assert_equal("/no/such/path", provider.command(:testing), "Did not return correct binary path")
@@ -187,7 +187,7 @@ class TestProvider < Test::Unit::TestCase
dir = tstdir
file = File.join(dir, "mycmd")
- sh = Puppet::Util.binary("sh")
+ sh = Puppet::Util.which("sh")
File.open(file, "w") { |f|
f.puts %{#!#{sh}
echo A Failure >&2