[Pkg-puppet-devel] [SCM] Puppet packaging for Debian branch, experimental, updated. debian/2.6.8-1-844-g7ec39d5
Max Martin
max at puppetlabs.com
Tue May 10 08:11:17 UTC 2011
The following commit has been merged in the experimental branch:
commit 20bff91c8b8e450d913deeb1750a00a14f1b1061
Merge: e17cc651a9625576aa79af428bbaec702e216ac8 da4457be4dedaed5368bacf81a08f0429e21cd45
Author: Max Martin <max at puppetlabs.com>
Date: Thu Apr 7 12:21:42 2011 -0700
Merge branch '2.6.x' into next
* 2.6.x:
(maint) Indentation fixes
(#6490) Add plugin initialization callback system to core
Fix #4339 - Locally save the last report to $lastrunreport
Fix #4339 - Save a last run report summary to $statedir/last_run_summary.yaml
Fixed #3127 - removed legacy debug code
Fixed #3127 - Fixed gem selection regex
(#5437) Invalidate cached TypeCollection when there was an error parsing
(#6937) Adjust formatting of recurse's desc
(#6937) Document the recurse parameter of File type.
(#6893) Document the cron type in the case of specials.
(#5670) Don't trigger refresh from a failed resource
Fixed #6554 - Missing $haveftool if/else conditional in install.rb breaking Ruby 1.9
Conflicts (Manually resolved):
lib/puppet/application/agent.rb
lib/puppet/application/apply.rb
lib/puppet/configurer.rb
lib/puppet/resource/type_collection.rb
lib/puppet/type/file.rb
spec/integration/configurer_spec.rb
spec/unit/application/agent_spec.rb
spec/unit/application/apply_spec.rb
spec/unit/configurer_spec.rb
spec/unit/indirector/report/yaml_spec.rb
spec/unit/resource/type_collection_spec.rb
Paired-with: Nick Lewis
diff --combined install.rb
index 6854363,351ba25..6bf4f55
--- a/install.rb
+++ b/install.rb
@@@ -53,6 -53,18 +53,6 @@@ rescue LoadErro
$haverdoc = false
end
-begin
- if $haverdoc
- ronn = %x{which ronn}
- $haveman = true
- else
- $haveman = false
- end
-rescue
- puts "Missing ronn; skipping man page creation"
- $haveman = false
-end
-
PREREQS = %w{openssl facter xmlrpc/client xmlrpc/server cgi}
MIN_FACTER_VERSION = 1.5
@@@ -80,8 -92,12 +80,12 @@@ def do_configs(configs, target, strip
Dir.mkdir(target) unless File.directory? target
configs.each do |cf|
ocf = File.join(InstallOptions.config_dir, cf.gsub(/#{strip}/, ''))
- File.install(cf, ocf, 0644, true)
- end
+ if $haveftools
+ File.install(cf, ocf, 0644, true)
+ else
+ FileUtils.install(cf, ocf, {:mode => 0644, :verbose => true})
+ end
+ end
end
def do_bins(bins, target, strip = 's?bin/')
@@@ -166,6 -182,15 +170,6 @@@ def prepare_installatio
end
- if $haveman
- InstallOptions.man = true
- if $operatingsystem == "windows"
- InstallOptions.man = false
- end
- else
- InstallOptions.man = false
- end
-
InstallOptions.tests = true
ARGV.options do |opts|
@@@ -177,6 -202,9 +181,6 @@@
opts.on('--[no-]ri', 'Prevents the creation of RI output.', 'Default off on mswin32.') do |onri|
InstallOptions.ri = onri
end
- opts.on('--[no-]man', 'Prevents the creation of man pages.', 'Default on.') do |onman|
- InstallOptions.man = onman
- end
opts.on('--[no-]tests', 'Prevents the execution of unit tests.', 'Default on.') do |ontest|
InstallOptions.tests = ontest
end
@@@ -209,6 -237,7 +213,6 @@@
end
opts.on('--full', 'Performs a full installation. All', 'optional installation steps are run.') do |full|
InstallOptions.rdoc = true
- InstallOptions.man = true
InstallOptions.ri = true
InstallOptions.tests = true
InstallOptions.configs = true
@@@ -338,6 -367,33 +342,6 @@@ def build_ri(files
end
end
-def build_man(bins, sbins)
- return unless $haveman
- begin
- # Locate ronn
- ronn = %x{which ronn}
- ronn.chomp!
- # Create puppet.conf.5 man page
- %x{bin/puppetdoc --reference configuration > ./man/man5/puppetconf.5.ronn}
- %x{#{ronn} -r ./man/man5/puppetconf.5.ronn}
- File.move("./man/man5/puppetconf.5", "./man/man5/puppet.conf.5")
- File.unlink("./man/man5/puppetconf.5.ronn")
-
- # Create binary man pages
- binary = bins + sbins
- binary.each do |bin|
- b = bin.gsub( /(bin|sbin)\//, "")
- %x{#{bin} --help > ./man/man8/#{b}.8.ronn}
- %x{#{ronn} -r ./man/man8/#{b}.8.ronn}
- File.unlink("./man/man8/#{b}.8.ronn")
- end
-
-rescue SystemCallError
- $stderr.puts "Couldn't build man pages: " + $ERROR_INFO
- $stderr.puts "Continuing with install..."
- end
-end
-
def run_tests(test_list)
require 'test/unit/ui/console/testrunner'
$LOAD_PATH.unshift "lib"
@@@ -431,6 -487,7 +435,6 @@@ prepare_installatio
#run_tests(tests) if InstallOptions.tests
#build_rdoc(rdoc) if InstallOptions.rdoc
#build_ri(ri) if InstallOptions.ri
-#build_man(bins, sbins) if InstallOptions.man
do_configs(configs, InstallOptions.config_dir) if InstallOptions.configs
do_bins(sbins, InstallOptions.sbin_dir)
do_bins(bins, InstallOptions.bin_dir)
diff --combined lib/puppet/application.rb
index 7ef71bc,a028a15..57bd888
--- a/lib/puppet/application.rb
+++ b/lib/puppet/application.rb
@@@ -1,4 -1,5 +1,5 @@@
require 'optparse'
+ require 'puppet/util/plugins'
# This class handles all the aspects of a Puppet application/executable
# * setting up options
@@@ -250,8 -251,7 +251,8 @@@ class Applicatio
# Every app responds to --help
option("--help", "-h") do |v|
- help
+ puts help
+ exit
end
def should_parse_config?
@@@ -298,11 -298,11 +299,11 @@@
# This is the main application entry point
def run
- exit_on_fail("initialize") { preinit }
- exit_on_fail("parse options") { parse_options }
+ exit_on_fail("initialize") { hook('preinit') { preinit } }
+ exit_on_fail("parse options") { hook('parse_options') { parse_options } }
exit_on_fail("parse configuration file") { Puppet.settings.parse } if should_parse_config?
- exit_on_fail("prepare for execution") { setup }
- exit_on_fail("run") { run_command }
+ exit_on_fail("prepare for execution") { hook('setup') { setup } }
+ exit_on_fail("run") { hook('run_command') { run_command } }
end
def main
@@@ -386,17 -386,40 +387,24 @@@
end
def help
- if Puppet.features.usage?
- # RH:FIXME: My goodness, this is ugly.
- ::RDoc.const_set("PuppetSourceFile", name)
- #:stopdoc: # Issue #4161
- def (::RDoc).caller
- docfile = `grep -l 'Puppet::Application\\[:#{::RDoc::PuppetSourceFile}\\]' #{DOCPATTERN}`.chomp
- super << "#{docfile}:0"
- end
- #:startdoc:
- ::RDoc::usage && exit
- else
- puts "No help available unless you have RDoc::usage installed"
- exit
- end
- rescue Errno::ENOENT
- puts "No help available for puppet #{name}"
- exit
+ "No help available for puppet #{name}"
end
private
def exit_on_fail(message, code = 1)
- yield
+ yield
rescue RuntimeError, NotImplementedError => detail
- puts detail.backtrace if Puppet[:trace]
- $stderr.puts "Could not #{message}: #{detail}"
- exit(code)
+ puts detail.backtrace if Puppet[:trace]
+ $stderr.puts "Could not #{message}: #{detail}"
+ exit(code)
+ end
+
+ def hook(step,&block)
+ Puppet::Plugins.send("before_application_#{step}",:application_object => self)
+ x = yield
+ Puppet::Plugins.send("after_application_#{step}",:application_object => self, :return_value => x)
+ x
end
end
end
diff --combined lib/puppet/configurer.rb
index 72e387c,9f68ca4..cfeb73a
--- a/lib/puppet/configurer.rb
+++ b/lib/puppet/configurer.rb
@@@ -173,9 -173,7 +173,7 @@@ class Puppet::Configure
report.finalize_report if trans
puts report.summary if Puppet[:summarize]
save_last_run_summary(report)
- if Puppet[:report]
- Puppet::Transaction::Report.indirection.save(report)
- end
- report.save if Puppet[:report]
++ Puppet::Transaction::Report.indirection.save(report) if Puppet[:report]
rescue => detail
puts detail.backtrace if Puppet[:trace]
Puppet.err "Could not send report: #{detail}"
@@@ -222,7 -220,7 +220,7 @@@
def retrieve_catalog_from_cache(fact_options)
result = nil
@duration = thinmark do
- result = Puppet::Resource::Catalog.find(Puppet[:certname], fact_options.merge(:ignore_terminus => true))
+ result = Puppet::Resource::Catalog.indirection.find(Puppet[:certname], fact_options.merge(:ignore_terminus => true))
end
Puppet.notice "Using cached catalog"
result
@@@ -235,7 -233,7 +233,7 @@@
def retrieve_new_catalog(fact_options)
result = nil
@duration = thinmark do
- result = Puppet::Resource::Catalog.find(Puppet[:certname], fact_options.merge(:ignore_cache => true))
+ result = Puppet::Resource::Catalog.indirection.find(Puppet[:certname], fact_options.merge(:ignore_cache => true))
end
result
rescue SystemExit,NoMemoryError
diff --combined lib/puppet/node/environment.rb
index d505306,807479b..dc63197
--- a/lib/puppet/node/environment.rb
+++ b/lib/puppet/node/environment.rb
@@@ -76,12 -76,12 +76,12 @@@ class Puppet::Node::Environmen
# per environment semantics with an efficient most common cases; we almost
# always just return our thread's known-resource types. Only at the start
# of a compilation (after our thread var has been set to nil) or when the
- # environment has changed do we delve deeper.
+ # environment has changed do we delve deeper.
Thread.current[:known_resource_types] = nil if (krt = Thread.current[:known_resource_types]) && krt.environment != self
Thread.current[:known_resource_types] ||= synchronize {
- if @known_resource_types.nil? or @known_resource_types.stale?
+ if @known_resource_types.nil? or @known_resource_types.require_reparse?
@known_resource_types = Puppet::Resource::TypeCollection.new(self)
- @known_resource_types.perform_initial_import
+ @known_resource_types.import_ast(perform_initial_import, '')
end
@known_resource_types
}
@@@ -128,7 -128,7 +128,7 @@@
to_s.to_sym
end
- # The only thing we care about when serializing an environment is its
+ # The only thing we care about when serializing an environment is its
# identity; everything else is ephemeral and should not be stored or
# transmitted.
def to_zaml(z)
@@@ -147,30 -147,5 +147,32 @@@
end
end
+ private
+
+ def perform_initial_import
+ return empty_parse_result if Puppet.settings[:ignoreimport]
+ parser = Puppet::Parser::Parser.new(self)
+ if code = Puppet.settings.uninterpolated_value(:code, name.to_s) and code != ""
+ parser.string = code
+ else
+ file = Puppet.settings.value(:manifest, name.to_s)
+ parser.file = file
+ end
+ parser.parse
+ rescue => detail
++ known_resource_types.parse_failed = true
++
+ msg = "Could not parse for environment #{self}: #{detail}"
+ error = Puppet::Error.new(msg)
+ error.set_backtrace(detail.backtrace)
+ raise error
+ end
+
+ def empty_parse_result
+ # Return an empty toplevel hostclass to use as the result of
+ # perform_initial_import when no file was actually loaded.
+ return Puppet::Parser::AST::Hostclass.new('')
+ end
+
@root = new(:'*root*')
end
diff --combined lib/puppet/resource/type_collection.rb
index 6ab978f,4210475..9fe7cdd
--- a/lib/puppet/resource/type_collection.rb
+++ b/lib/puppet/resource/type_collection.rb
@@@ -1,5 -1,5 +1,6 @@@
class Puppet::Resource::TypeCollection
attr_reader :environment
++ attr_accessor :parse_failed
def clear
@hostclasses.clear
@@@ -19,12 -19,6 +20,12 @@@
@watched_files = {}
end
+ def import_ast(ast, modname)
+ ast.instantiate(modname).each do |instance|
+ add(instance)
+ end
+ end
+
def inspect
"TypeCollection" + { :hostclasses => @hostclasses.keys, :definitions => @definitions.keys, :nodes => @nodes.keys }.inspect
end
@@@ -102,8 -96,50 +103,8 @@@
@definitions[munge_name(name)]
end
- def find(namespaces, name, type)
- #Array("") == [] for some reason
- namespaces = [namespaces] unless namespaces.is_a?(Array)
-
- if name =~ /^::/
- return send(type, name.sub(/^::/, ''))
- end
-
- namespaces.each do |namespace|
- ary = namespace.split("::")
-
- while ary.length > 0
- tmp_namespace = ary.join("::")
- if r = find_partially_qualified(tmp_namespace, name, type)
- return r
- end
-
- # Delete the second to last object, which reduces our namespace by one.
- ary.pop
- end
-
- if result = send(type, name)
- return result
- end
- end
- nil
- end
-
- def find_or_load(namespaces, name, type)
- name = name.downcase
- namespaces = [namespaces] unless namespaces.is_a?(Array)
- namespaces = namespaces.collect { |ns| ns.downcase }
-
- # This could be done in the load_until, but the knowledge seems to
- # belong here.
- if r = find(namespaces, name, type)
- return r
- end
-
- loader.load_until(namespaces, name) { find(namespaces, name, type) }
- end
-
def find_node(namespaces, name)
- find("", name, :node)
+ @nodes[munge_name(name)]
end
def find_hostclass(namespaces, name)
@@@ -120,6 -156,28 +121,10 @@@
end
end
- def perform_initial_import
- parser = Puppet::Parser::Parser.new(environment)
- if code = Puppet.settings.uninterpolated_value(:code, environment.to_s) and code != ""
- parser.string = code
- else
- file = Puppet.settings.value(:manifest, environment.to_s)
- parser.file = file
- end
- parser.parse
- rescue => detail
- @parse_failed = true
-
- msg = "Could not parse for environment #{environment}: #{detail}"
- error = Puppet::Error.new(msg)
- error.set_backtrace(detail.backtrace)
- raise error
- end
-
+ def require_reparse?
+ @parse_failed || stale?
+ end
+
def stale?
@watched_files.values.detect { |file| file.changed? }
end
@@@ -148,52 -206,8 +153,52 @@@
private
- def find_partially_qualified(namespace, name, type)
- send(type, [namespace, name].join("::"))
+ # Return a list of all possible fully-qualified names that might be
+ # meant by the given name, in the context of namespaces.
+ def resolve_namespaces(namespaces, name)
+ name = name.downcase
+ if name =~ /^::/
+ # name is explicitly fully qualified, so just return it, sans
+ # initial "::".
+ return [name.sub(/^::/, '')]
+ end
+ if name == ""
+ # The name "" has special meaning--it always refers to a "main"
+ # hostclass which contains all toplevel resources.
+ return [""]
+ end
+
+ namespaces = [namespaces] unless namespaces.is_a?(Array)
+ namespaces = namespaces.collect { |ns| ns.downcase }
+
+ result = []
+ namespaces.each do |namespace|
+ ary = namespace.split("::")
+
+ # Search each namespace nesting in innermost-to-outermost order.
+ while ary.length > 0
+ result << "#{ary.join("::")}::#{name}"
+ ary.pop
+ end
+
+ # Finally, search the toplevel namespace.
+ result << name
+ end
+
+ return result.uniq
+ end
+
+ # Resolve namespaces and find the given object. Autoload it if
+ # necessary.
+ def find_or_load(namespaces, name, type)
+ resolve_namespaces(namespaces, name).each do |fqname|
+ if result = send(type, fqname) || loader.try_load_fqname(type, fqname)
+ return result
+ end
+ end
+
+ # Nothing found.
+ return nil
end
def munge_name(name)
diff --combined lib/puppet/transaction.rb
index 8118178,48154ad..0533273
--- a/lib/puppet/transaction.rb
+++ b/lib/puppet/transaction.rb
@@@ -4,7 -4,6 +4,7 @@@
require 'puppet'
require 'puppet/util/tagging'
require 'puppet/application'
+require 'sha1'
class Puppet::Transaction
require 'puppet/transaction/event'
@@@ -13,7 -12,7 +13,7 @@@
require 'puppet/resource/status'
attr_accessor :component, :catalog, :ignoreschedules
- attr_accessor :sorted_resources, :configurator
+ attr_accessor :configurator
# The report, once generated.
attr_accessor :report
@@@ -48,7 -47,7 +48,7 @@@
def apply(resource, ancestor = nil)
status = resource_harness.evaluate(resource)
add_resource_status(status)
- event_manager.queue_events(ancestor || resource, status.events)
+ event_manager.queue_events(ancestor || resource, status.events) unless status.failed?
rescue => detail
resource.err "Could not evaluate: #{detail}"
end
@@@ -58,36 -57,68 +58,36 @@@
report.resource_statuses.values.find_all { |status| status.changed }.collect { |status| catalog.resource(status.resource) }
end
+ # Find all of the applied resources (including failed attempts).
+ def applied_resources
+ report.resource_statuses.values.collect { |status| catalog.resource(status.resource) }
+ end
+
# Copy an important relationships from the parent to the newly-generated
# child resource.
- def make_parent_child_relationship(resource, children)
- depthfirst = resource.depthfirst?
-
- children.each do |gen_child|
- if depthfirst
- edge = [gen_child, resource]
- else
- edge = [resource, gen_child]
- end
- relationship_graph.add_vertex(gen_child)
-
- unless relationship_graph.edge?(edge[1], edge[0])
- relationship_graph.add_edge(*edge)
- else
- resource.debug "Skipping automatic relationship to #{gen_child}"
- end
+ def add_conditional_directed_dependency(parent, child, label=nil)
+ relationship_graph.add_vertex(child)
+ edge = parent.depthfirst? ? [child, parent] : [parent, child]
+ if relationship_graph.edge?(*edge.reverse)
+ parent.debug "Skipping automatic relationship to #{child}"
+ else
+ relationship_graph.add_edge(edge[0],edge[1],label)
end
end
- # See if the resource generates new resources at evaluation time.
- def eval_generate(resource)
- generate_additional_resources(resource, :eval_generate)
- end
-
# Evaluate a single resource.
def eval_resource(resource, ancestor = nil)
if skip?(resource)
resource_status(resource).skipped = true
else
- eval_children_and_apply_resource(resource, ancestor)
+ resource_status(resource).scheduled = true
+ apply(resource, ancestor)
end
# Check to see if there are any events queued for this resource
event_manager.process_events(resource)
end
- def eval_children_and_apply_resource(resource, ancestor = nil)
- resource_status(resource).scheduled = true
-
- # We need to generate first regardless, because the recursive
- # actions sometimes change how the top resource is applied.
- children = eval_generate(resource)
-
- if ! children.empty? and resource.depthfirst?
- children.each do |child|
- # The child will never be skipped when the parent isn't
- eval_resource(child, ancestor || resource)
- end
- end
-
- # Perform the actual changes
- apply(resource, ancestor)
-
- if ! children.empty? and ! resource.depthfirst?
- children.each do |child|
- eval_resource(child, ancestor || resource)
- end
- end
- end
-
# This method does all the actual work of running a transaction. It
# collects all of the changes, executes them, and responds to any
# necessary events.
@@@ -100,13 -131,19 +100,13 @@@
Puppet.info "Applying configuration version '#{catalog.version}'" if catalog.version
begin
- @sorted_resources.each do |resource|
- next if stop_processing?
+ relationship_graph.traverse do |resource|
if resource.is_a?(Puppet::Type::Component)
Puppet.warning "Somehow left a component in the relationship graph"
- next
+ else
+ seconds = thinmark { eval_resource(resource) }
+ resource.info "Evaluated in %0.2f seconds" % seconds if Puppet[:evaltrace] and @catalog.host_config?
end
- ret = nil
- seconds = thinmark do
- ret = eval_resource(resource)
- end
-
- resource.info "Evaluated in %0.2f seconds" % seconds if Puppet[:evaltrace] and @catalog.host_config?
- ret
end
ensure
# And then close the transaction log.
@@@ -140,66 -177,48 +140,66 @@@
found_failed
end
+ def eval_generate(resource)
+ raise Puppet::DevError,"Depthfirst resources are not supported by eval_generate" if resource.depthfirst?
+ begin
+ made = resource.eval_generate.uniq.reverse
+ rescue => detail
+ puts detail.backtrace if Puppet[:trace]
+ resource.err "Failed to generate additional resources using 'eval_generate: #{detail}"
+ return
+ end
+ made.each do |res|
+ begin
+ res.tag(*resource.tags)
+ @catalog.add_resource(res)
+ res.finish
+ rescue Puppet::Resource::Catalog::DuplicateResourceError
+ res.info "Duplicate generated resource; skipping"
+ end
+ end
+ sentinal = Puppet::Type::Whit.new(:name => "completed_#{resource.title}", :catalog => resource.catalog)
+ relationship_graph.adjacent(resource,:direction => :out,:type => :edges).each { |e|
+ add_conditional_directed_dependency(sentinal, e.target, e.label)
+ relationship_graph.remove_edge! e
+ }
+ default_label = Puppet::Resource::Catalog::Default_label
+ made.each do |res|
+ add_conditional_directed_dependency(made.find { |r| r != res && r.name == res.name[0,r.name.length]} || resource, res)
+ add_conditional_directed_dependency(res, sentinal, default_label)
+ end
+ add_conditional_directed_dependency(resource, sentinal, default_label)
+ end
+
# A general method for recursively generating new resources from a
# resource.
- def generate_additional_resources(resource, method)
- return [] unless resource.respond_to?(method)
+ def generate_additional_resources(resource)
+ return unless resource.respond_to?(:generate)
begin
- made = resource.send(method)
+ made = resource.generate
rescue => detail
puts detail.backtrace if Puppet[:trace]
- resource.err "Failed to generate additional resources using '#{method}': #{detail}"
+ resource.err "Failed to generate additional resources using 'generate': #{detail}"
end
- return [] unless made
+ return unless made
made = [made] unless made.is_a?(Array)
- made.uniq.find_all do |res|
+ made.uniq.each do |res|
begin
res.tag(*resource.tags)
- @catalog.add_resource(res) do |r|
- r.finish
- make_parent_child_relationship(resource, [r])
-
- # Call 'generate' recursively
- generate_additional_resources(r, method)
- end
- true
+ @catalog.add_resource(res)
+ res.finish
+ add_conditional_directed_dependency(resource, res)
+ generate_additional_resources(res)
rescue Puppet::Resource::Catalog::DuplicateResourceError
res.info "Duplicate generated resource; skipping"
- false
end
end
end
# Collect any dynamically generated resources. This method is called
# before the transaction starts.
- def generate
- list = @catalog.vertices
- newlist = []
- while ! list.empty?
- list.each do |resource|
- newlist += generate_additional_resources(resource, :generate)
- end
- list = newlist
- newlist = []
- end
+ def xgenerate
+ @catalog.vertices.each { |resource| generate_additional_resources(resource) }
end
# Should we ignore tags?
@@@ -212,7 -231,7 +212,7 @@@
def initialize(catalog)
@catalog = catalog
- @report = Report.new("apply", catalog.version)
+ @report = Puppet::Transaction::Report.new("apply")
@event_manager = Puppet::Transaction::EventManager.new(self)
@@@ -245,75 -264,18 +245,75 @@@
# Prepare to evaluate the resources in a transaction.
def prepare
# Now add any dynamically generated resources
- generate
+ xgenerate
# Then prefetch. It's important that we generate and then prefetch,
# so that any generated resources also get prefetched.
prefetch
+ end
+
- # This will throw an error if there are cycles in the graph.
- @sorted_resources = relationship_graph.topsort
+ # We want to monitor changes in the relationship graph of our
+ # catalog but this is complicated by the fact that the catalog
+ # both is_a graph and has_a graph, by the fact that changes to
+ # the structure of the object can have adverse serialization
+ # effects, by threading issues, by order-of-initialization issues,
+ # etc.
+ #
+ # Since the proper lifetime/scope of the monitoring is a transaction
+ # and the transaction is already commiting a mild law-of-demeter
+ # transgression, we cut the Gordian knot here by simply wrapping the
+ # transaction's view of the resource graph to capture and maintain
+ # the information we need. Nothing outside the transaction needs
+ # this information, and nothing outside the transaction can see it
+ # except via the Transaction#relationship_graph
+
+ class Relationship_graph_wrapper
+ attr_reader :real_graph,:transaction,:ready,:generated,:done,:unguessable_deterministic_key
+ def initialize(real_graph,transaction)
+ @real_graph = real_graph
+ @transaction = transaction
+ @ready = {}
+ @generated = {}
+ @done = {}
+ @unguessable_deterministic_key = Hash.new { |h,k| h[k] = Digest::SHA1.hexdigest("NaCl, MgSO4 (salts) and then #{k.title}") }
+ vertices.each { |v| check_if_now_ready(v) }
+ end
+ def method_missing(*args,&block)
+ real_graph.send(*args,&block)
+ end
+ def add_vertex(v)
+ real_graph.add_vertex(v)
+ check_if_now_ready(v) # ?????????????????????????????????????????
+ end
+ def add_edge(f,t,label=nil)
+ ready.delete(t)
+ real_graph.add_edge(f,t,label)
+ end
+ def check_if_now_ready(r)
+ ready[r] = true if direct_dependencies_of(r).all? { |r2| done[r2] }
+ end
+ def next_resource
+ ready.keys.sort_by { |r0| unguessable_deterministic_key[r0] }.first
+ end
+ def traverse(&block)
+ real_graph.report_cycles_in_graph
+ while (r = next_resource) && !transaction.stop_processing?
+ if !generated[r] && r.respond_to?(:eval_generate)
+ transaction.eval_generate(r)
+ generated[r] = true
+ else
+ ready.delete(r)
+ yield r
+ done[r] = true
+ direct_dependents_of(r).each { |v| check_if_now_ready(v) }
+ end
+ end
+ end
end
def relationship_graph
- catalog.relationship_graph
+ @relationship_graph ||= Relationship_graph_wrapper.new(catalog.relationship_graph,self)
end
def add_resource_status(status)
diff --combined lib/puppet/type/file.rb
index 5632d41,630ebe5..715836b
--- a/lib/puppet/type/file.rb
+++ b/lib/puppet/type/file.rb
@@@ -44,7 -44,7 +44,7 @@@ Puppet::Type.newtype(:file) d
# convert the current path in an index into the collection and the last
# path name. The aim is to use less storage for all common paths in a hierarchy
munge do |value|
- path, name = File.split(value.gsub(/\/+/,'/'))
+ path, name = ::File.split(value.gsub(/\/+/,'/'))
{ :index => Puppet::FileCollection.collection.index(path), :name => name }
end
@@@ -55,7 -55,7 +55,7 @@@
if value[:name] == '/'
basedir
else
- File.join( basedir, value[:name] )
+ ::File.join( basedir, value[:name] )
end
end
end
@@@ -123,15 -123,16 +123,16 @@@
newparam(:recurse) do
desc "Whether and how deeply to do recursive
management. Options are:
- inf,true => Regular style recursion on both remote and local
- directory structure.
- remote => Descends recursively into the remote directory
- but not the local directory. Allows copying of
- a few files into a directory containing many
- unmanaged files without scanning all the local files.
- false => Default of no-recursion.
- [0-9]+ => Both, but limit recursion. Warning: this syntax
- is deprecated and has moved to recurselimit.
+
+ * `inf,true` --- Regular style recursion on both remote and local
+ directory structure.
+ * `remote` --- Descends recursively into the remote directory
+ but not the local directory. Allows copying of
+ a few files into a directory containing many
+ unmanaged files without scanning all the local files.
+ * `false` --- Default of no recursion.
+ * `[0-9]+` --- Same as true, but limit recursion. Warning: this syntax
+ has been deprecated in favor of the `recurselimit` attribute.
"
newvalues(:true, :false, :inf, :remote, /^[0-9]+$/)
@@@ -258,7 -259,7 +259,7 @@@
# Autorequire any parent directories.
autorequire(:file) do
- basedir = File.dirname(self[:path])
+ basedir = ::File.dirname(self[:path])
if basedir != self[:path]
basedir
else
@@@ -313,11 -314,13 +314,11 @@@
return self.new(:name => base, :recurse => true, :recurselimit => 1, :audit => :all).recurse_local.values
end
- @depthfirst = false
-
# Determine the user to write files as.
def asuser
if self.should(:owner) and ! self.should(:owner).is_a?(Symbol)
writeable = Puppet::Util::SUIDManager.asuser(self.should(:owner)) {
- FileTest.writable?(File.dirname(self[:path]))
+ FileTest.writable?(::File.dirname(self[:path]))
}
# If the parent directory is writeable, then we execute
@@@ -420,7 -423,7 +421,7 @@@
# Create a new file or directory object as a child to the current
# object.
def newchild(path)
- full_path = File.join(self[:path], path)
+ full_path = ::File.join(self[:path], path)
# Add some new values to our original arguments -- these are the ones
# set at initialization. We specifically want to exclude any param
@@@ -472,7 -475,8 +473,7 @@@
# be used to copy remote files, manage local files, and/or make links
# to map to another directory.
def recurse
- children = {}
- children = recurse_local if self[:recurse] != :remote
+ children = (self[:recurse] == :remote) ? {} : recurse_local
if self[:target]
recurse_link(children)
@@@ -493,23 -497,27 +494,23 @@@
# not likely to have many actual conflicts, which is good, because
# this is a pretty inefficient implementation.
def remove_less_specific_files(files)
- mypath = self[:path].split(File::Separator)
+ mypath = self[:path].split(::File::Separator)
other_paths = catalog.vertices.
select { |r| r.is_a?(self.class) and r[:path] != self[:path] }.
- collect { |r| r[:path].split(File::Separator) }.
+ collect { |r| r[:path].split(::File::Separator) }.
select { |p| p[0,mypath.length] == mypath }
return files if other_paths.empty?
files.reject { |file|
- path = file[:path].split(File::Separator)
+ path = file[:path].split(::File::Separator)
other_paths.any? { |p| path[0,p.length] == p }
}
end
# A simple method for determining whether we should be recursing.
def recurse?
- return false unless @parameters.include?(:recurse)
-
- val = @parameters[:recurse].value
-
- !!(val and (val == true or val == :remote))
+ self[:recurse] == true or self[:recurse] == :remote
end
# Recurse the target of the link.
@@@ -581,10 -589,13 +582,10 @@@
end
def perform_recursion(path)
-
- Puppet::FileServing::Metadata.search(
-
+ Puppet::FileServing::Metadata.indirection.search(
path,
:links => self[:links],
:recurse => (self[:recurse] == :remote ? true : self[:recurse]),
-
:recurselimit => self[:recurselimit],
:ignore => self[:ignore],
:checksum_type => (self[:source] || self[:content]) ? self[:checksum] : :none
@@@ -612,7 -623,7 +613,7 @@@
end
when "link", "file"
debug "Removing existing #{s.ftype} for replacement with #{should}"
- File.unlink(self[:path])
+ ::File.unlink(self[:path])
else
self.fail "Could not back up files of type #{s.ftype}"
end
@@@ -677,7 -688,7 +678,7 @@@
path = self[:path]
begin
- File.send(method, self[:path])
+ ::File.send(method, self[:path])
rescue Errno::ENOENT => error
return nil
rescue Errno::EACCES => error
@@@ -703,7 -714,7 +704,7 @@@
use_temporary_file = write_temporary_file?
if use_temporary_file
path = "#{self[:path]}.puppettmp_#{rand(10000)}"
- path = "#{self[:path]}.puppettmp_#{rand(10000)}" while File.exists?(path) or File.symlink?(path)
+ path = "#{self[:path]}.puppettmp_#{rand(10000)}" while ::File.exists?(path) or ::File.symlink?(path)
else
path = self[:path]
end
@@@ -712,18 -723,18 +713,18 @@@
umask = mode ? 000 : 022
mode_int = mode ? mode.to_i(8) : nil
- content_checksum = Puppet::Util.withumask(umask) { File.open(path, 'w', mode_int ) { |f| write_content(f) } }
+ content_checksum = Puppet::Util.withumask(umask) { ::File.open(path, 'w', mode_int ) { |f| write_content(f) } }
# And put our new file in place
if use_temporary_file # This is only not true when our file is empty.
begin
fail_if_checksum_is_wrong(path, content_checksum) if validate_checksum?
- File.rename(path, self[:path])
+ ::File.rename(path, self[:path])
rescue => detail
fail "Could not rename temporary file #{path} to #{self[:path]}: #{detail}"
ensure
# Make sure the created file gets removed
- File.unlink(path) if FileTest.exists?(path)
+ ::File.unlink(path) if FileTest.exists?(path)
end
end
diff --combined spec/integration/transaction_spec.rb
index ff15e59,66a049e..e608faa
--- a/spec/integration/transaction_spec.rb
+++ b/spec/integration/transaction_spec.rb
@@@ -1,6 -1,6 +1,6 @@@
#!/usr/bin/env ruby
-require File.dirname(__FILE__) + '/../spec_helper'
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
require 'puppet_spec/files'
require 'puppet/transaction'
@@@ -135,33 -135,26 +135,26 @@@ describe Puppet::Transaction d
it "should not let one failed refresh result in other refreshes failing" do
path = tmpfile("path")
newfile = tmpfile("file")
-
- file = Puppet::Type.type(:file).new(
-
+ file = Puppet::Type.type(:file).new(
:path => path,
:ensure => "file"
)
- exec1 = Puppet::Type.type(:exec).new(
-
+ exec1 = Puppet::Type.type(:exec).new(
:path => ENV["PATH"],
:command => "touch /this/cannot/possibly/exist",
:logoutput => true,
:refreshonly => true,
:subscribe => file,
:title => "one"
)
- exec2 = Puppet::Type.type(:exec).new(
-
+ exec2 = Puppet::Type.type(:exec).new(
:path => ENV["PATH"],
:command => "touch #{newfile}",
:logoutput => true,
:refreshonly => true,
:subscribe => [file, exec1],
-
:title => "two"
)
@@@ -178,22 -171,18 +171,18 @@@
Puppet[:ignoreschedules] = false
- file = Puppet::Type.type(:file).new(
-
+ file = Puppet::Type.type(:file).new(
:name => tmpfile("file"),
-
:ensure => "file",
:backup => false
)
fname = tmpfile("exec")
- exec = Puppet::Type.type(:exec).new(
-
+ exec = Puppet::Type.type(:exec).new(
:name => "touch #{fname}",
:path => "/usr/bin:/bin",
:schedule => "monthly",
-
:subscribe => Puppet::Resource.new("file", file.name)
)
@@@ -230,29 -219,21 +219,21 @@@
it "should not attempt to evaluate resources with failed dependencies" do
- exec = Puppet::Type.type(:exec).new(
-
+ exec = Puppet::Type.type(:exec).new(
:command => "/bin/mkdir /this/path/cannot/possibly/exit",
:title => "mkdir"
)
-
- file1 = Puppet::Type.type(:file).new(
-
+ file1 = Puppet::Type.type(:file).new(
:title => "file1",
:path => tmpfile("file1"),
-
:require => exec,
:ensure => :file
)
-
- file2 = Puppet::Type.type(:file).new(
-
+ file2 = Puppet::Type.type(:file).new(
:title => "file2",
:path => tmpfile("file2"),
-
:require => file1,
:ensure => :file
)
@@@ -264,6 -245,32 +245,32 @@@
FileTest.should_not be_exists(file2[:path])
end
+ it "should not trigger subscribing resources on failure" do
+ file1 = tmpfile("file1")
+ file2 = tmpfile("file2")
+
+ create_file1 = Puppet::Type.type(:exec).new(
+ :command => "/usr/bin/touch #{file1}"
+ )
+
+ exec = Puppet::Type.type(:exec).new(
+ :command => "/bin/mkdir /this/path/cannot/possibly/exit",
+ :title => "mkdir",
+ :notify => create_file1
+ )
+
+ create_file2 = Puppet::Type.type(:exec).new(
+ :command => "/usr/bin/touch #{file2}",
+ :subscribe => exec
+ )
+
+ catalog = mk_catalog(exec, create_file1, create_file2)
+ catalog.apply
+
+ FileTest.should_not be_exists(file1)
+ FileTest.should_not be_exists(file2)
+ end
+
# #801 -- resources only checked in noop should be rescheduled immediately.
it "should immediately reschedule noop resources" do
Puppet::Type.type(:schedule).mkdefaultschedules
diff --combined spec/unit/configurer_spec.rb
index f8acdd0,a4b627c..d21d86e
--- a/spec/unit/configurer_spec.rb
+++ b/spec/unit/configurer_spec.rb
@@@ -3,7 -3,7 +3,7 @@@
# Created by Luke Kanies on 2007-11-12.
# Copyright (c) 2007. All rights reserved.
-require File.dirname(__FILE__) + '/../spec_helper'
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
require 'puppet/configurer'
describe Puppet::Configurer do
@@@ -82,7 -82,9 +82,7 @@@ describe Puppet::Configurer, "when exec
@catalog.stubs(:apply)
@agent.stubs(:retrieve_catalog).returns @catalog
@agent.stubs(:save_last_run_summary)
-
- Puppet::Util::Log.stubs(:newdestination)
- Puppet::Util::Log.stubs(:close)
+ Puppet::Transaction::Report.indirection.stubs(:save)
end
it "should prepare for the run" do
@@@ -93,7 -95,7 +93,7 @@@
it "should initialize a transaction report if one is not provided" do
report = Puppet::Transaction::Report.new("apply")
- Puppet::Transaction::Report.expects(:new).returns report
+ Puppet::Transaction::Report.expects(:new).at_least_once.returns report
@agent.run
end
@@@ -118,7 -120,6 +118,7 @@@
report = Puppet::Transaction::Report.new("apply")
Puppet::Transaction::Report.expects(:new).returns report
+ @agent.stubs(:send_report)
Puppet::Util::Log.expects(:newdestination).with(report)
@agent.run
@@@ -211,10 -212,9 +211,10 @@@
report = Puppet::Transaction::Report.new("apply")
Puppet::Transaction::Report.expects(:new).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
@@@ -226,10 -226,12 +226,12 @@@
end
describe Puppet::Configurer, "when sending a report" do
+ include PuppetSpec::Files
+
before do
Puppet.settings.stubs(:use).returns(true)
@configurer = Puppet::Configurer.new
- @configurer.stubs(:save_last_run_summary)
+ Puppet[:lastrunfile] = tmpfile('last_run_file')
@report = Puppet::Transaction::Report.new("apply")
@trans = stub 'transaction'
@@@ -259,14 -261,14 +261,14 @@@
it "should save the report if reporting is enabled" do
Puppet.settings[:report] = true
- @report.expects(:save)
+ Puppet::Transaction::Report.indirection.expects(:save).with(@report)
@configurer.send_report(@report, nil)
end
it "should not save the report if reporting is disabled" do
Puppet.settings[:report] = false
- @report.expects(:save).never
+ Puppet::Transaction::Report.indirection.expects(:save).never
@configurer.send_report(@report, nil)
end
@@@ -277,17 -279,17 +279,17 @@@
@configurer.send_report(@report, nil)
end
- it "should not save the last run summary if reporting is disabled" do
+ it "should save the last run summary if reporting is disabled" do
Puppet.settings[:report] = false
- @configurer.expects(:save_last_run_summary).never
+ @configurer.expects(:save_last_run_summary).with(@report)
@configurer.send_report(@report, nil)
end
it "should log but not fail if saving the report fails" do
Puppet.settings[:report] = true
- @report.expects(:save).raises "whatever"
+ Puppet::Transaction::Report.indirection.expects(:save).with(@report).raises "whatever"
Puppet.expects(:err)
lambda { @configurer.send_report(@report, nil) }.should_not raise_error
@@@ -344,15 -346,15 +346,15 @@@ describe Puppet::Configurer, "when retr
end
it "should first look in the cache for a catalog" do
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_terminus] == true }.returns @catalog
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_cache] == true }.never
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_terminus] == true }.returns @catalog
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_cache] == true }.never
@agent.retrieve_catalog.should == @catalog
end
it "should compile a new catalog if none is found in the cache" do
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_terminus] == true }.returns nil
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_cache] == true }.returns @catalog
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_terminus] == true }.returns nil
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_cache] == true }.returns @catalog
@agent.retrieve_catalog.should == @catalog
end
@@@ -361,7 -363,7 +363,7 @@@
describe "when not using a REST terminus for catalogs" do
it "should not pass any facts when retrieving the catalog" do
@agent.expects(:facts_for_uploading).never
- Puppet::Resource::Catalog.expects(:find).with { |name, options|
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options|
options[:facts].nil?
}.returns @catalog
@@@ -372,7 -374,7 +374,7 @@@
describe "when using a REST terminus for catalogs" do
it "should pass the prepared facts and the facts format as arguments when retrieving the catalog" do
@agent.expects(:facts_for_uploading).returns(:facts => "myfacts", :facts_format => :foo)
- Puppet::Resource::Catalog.expects(:find).with { |name, options|
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options|
options[:facts] == "myfacts" and options[:facts_format] == :foo
}.returns @catalog
@@@ -381,7 -383,7 +383,7 @@@
end
it "should use the Catalog class to get its catalog" do
- Puppet::Resource::Catalog.expects(:find).returns @catalog
+ Puppet::Resource::Catalog.indirection.expects(:find).returns @catalog
@agent.retrieve_catalog
end
@@@ -389,20 -391,20 +391,20 @@@
it "should use its certname to retrieve the catalog" do
Facter.stubs(:value).returns "eh"
Puppet.settings[:certname] = "myhost.domain.com"
- Puppet::Resource::Catalog.expects(:find).with { |name, options| name == "myhost.domain.com" }.returns @catalog
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| name == "myhost.domain.com" }.returns @catalog
@agent.retrieve_catalog
end
it "should default to returning a catalog retrieved directly from the server, skipping the cache" do
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_cache] == true }.returns @catalog
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_cache] == true }.returns @catalog
@agent.retrieve_catalog.should == @catalog
end
it "should log and return the cached catalog when no catalog can be retrieved from the server" do
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_cache] == true }.returns nil
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_terminus] == true }.returns @catalog
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_cache] == true }.returns nil
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_terminus] == true }.returns @catalog
Puppet.expects(:notice)
@@@ -410,15 -412,15 +412,15 @@@
end
it "should not look in the cache for a catalog if one is returned from the server" do
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_cache] == true }.returns @catalog
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_terminus] == true }.never
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_cache] == true }.returns @catalog
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_terminus] == true }.never
@agent.retrieve_catalog.should == @catalog
end
it "should return the cached catalog when retrieving the remote catalog throws an exception" do
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_cache] == true }.raises "eh"
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_terminus] == true }.returns @catalog
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_cache] == true }.raises "eh"
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_terminus] == true }.returns @catalog
@agent.retrieve_catalog.should == @catalog
end
@@@ -426,7 -428,7 +428,7 @@@
it "should log and return nil if no catalog can be retrieved from the server and :usecacheonfailure is disabled" do
Puppet.stubs(:[])
Puppet.expects(:[]).with(:usecacheonfailure).returns false
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_cache] == true }.returns nil
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_cache] == true }.returns nil
Puppet.expects(:warning)
@@@ -434,21 -436,21 +436,21 @@@
end
it "should return nil if no cached catalog is available and no catalog can be retrieved from the server" do
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_cache] == true }.returns nil
- Puppet::Resource::Catalog.expects(:find).with { |name, options| options[:ignore_terminus] == true }.returns nil
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_cache] == true }.returns nil
+ Puppet::Resource::Catalog.indirection.expects(:find).with { |name, options| options[:ignore_terminus] == true }.returns nil
@agent.retrieve_catalog.should be_nil
end
it "should convert the catalog before returning" do
- Puppet::Resource::Catalog.stubs(:find).returns @catalog
+ Puppet::Resource::Catalog.indirection.stubs(:find).returns @catalog
@agent.expects(:convert_catalog).with { |cat, dur| cat == @catalog }.returns "converted catalog"
@agent.retrieve_catalog.should == "converted catalog"
end
it "should return nil if there is an error while retrieving the catalog" do
- Puppet::Resource::Catalog.expects(:find).at_least_once.raises "eh"
+ Puppet::Resource::Catalog.indirection.expects(:find).at_least_once.raises "eh"
@agent.retrieve_catalog.should be_nil
end
diff --combined spec/unit/node/environment_spec.rb
index 05527e7,6109007..d34bdb0
--- a/spec/unit/node/environment_spec.rb
+++ b/spec/unit/node/environment_spec.rb
@@@ -1,12 -1,11 +1,12 @@@
#!/usr/bin/env ruby
-require File.dirname(__FILE__) + '/../../spec_helper'
+require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
require 'puppet/node/environment'
require 'puppet/util/execution'
describe Puppet::Node::Environment do
+ include PuppetSpec::Files
after do
Puppet::Node::Environment.clear
end
@@@ -53,7 -52,7 +53,7 @@@
before do
@env = Puppet::Node::Environment.new("dev")
@collection = Puppet::Resource::TypeCollection.new(@env)
- @collection.stubs(:perform_initial_import)
+ @env.stubs(:perform_initial_import).returns(Puppet::Parser::AST::Hostclass.new(''))
Thread.current[:known_resource_types] = nil
end
@@@ -67,8 -66,9 +67,8 @@@
end
it "should perform the initial import when creating a new collection" do
- @collection.expects(:perform_initial_import)
- Puppet::Resource::TypeCollection.expects(:new).returns @collection
-
+ @env = Puppet::Node::Environment.new("dev")
+ @env.expects(:perform_initial_import).returns(Puppet::Parser::AST::Hostclass.new(''))
@env.known_resource_types
end
@@@ -85,28 -85,29 +85,29 @@@
@env.known_resource_types.should equal(@collection)
end
- it "should give to all threads the same collection if it didn't change" do
- Puppet::Resource::TypeCollection.expects(:new).with(@env).returns @collection
- @env.known_resource_types
+ it "should give to all threads using the same environment the same collection if the collection isn't stale" do
+ original_thread_type_collection = Puppet::Resource::TypeCollection.new(@env)
+ Puppet::Resource::TypeCollection.expects(:new).with(@env).returns original_thread_type_collection
+ @env.known_resource_types.should equal(original_thread_type_collection)
+
+ original_thread_type_collection.expects(:require_reparse?).returns(false)
+ Puppet::Resource::TypeCollection.stubs(:new).with(@env).returns @collection
t = Thread.new {
- @env.known_resource_types.should equal(@collection)
+ @env.known_resource_types.should equal(original_thread_type_collection)
}
t.join
end
- it "should give to new threads a new collection if it isn't stale" do
- Puppet::Resource::TypeCollection.expects(:new).with(@env).returns @collection
- @env.known_resource_types.expects(:stale?).returns(true)
-
- Puppet::Resource::TypeCollection.expects(:new).returns @collection
+ it "should generate a new TypeCollection if the current one requires reparsing" do
+ old_type_collection = @env.known_resource_types
+ old_type_collection.stubs(:require_reparse?).returns true
+ Thread.current[:known_resource_types] = nil
+ new_type_collection = @env.known_resource_types
- t = Thread.new {
- @env.known_resource_types.should equal(@collection)
- }
- t.join
+ new_type_collection.should be_a Puppet::Resource::TypeCollection
+ new_type_collection.should_not equal(old_type_collection)
end
-
end
[:modulepath, :manifestdir].each do |setting|
@@@ -274,52 -275,4 +275,61 @@@
@helper.environment.name.should == :foo
end
end
+
+ describe "when performing initial import" do
+ before do
- @parser = stub 'parser'
++ @parser = Puppet::Parser::Parser.new("test")
+ Puppet::Parser::Parser.stubs(:new).returns @parser
+ @env = Puppet::Node::Environment.new("env")
+ end
+
+ it "should set the parser's string to the 'code' setting and parse if code is available" do
+ Puppet.settings[:code] = "my code"
+ @parser.expects(:string=).with "my code"
+ @parser.expects(:parse)
+ @env.instance_eval { perform_initial_import }
+ end
+
+ it "should set the parser's file to the 'manifest' setting and parse if no code is available and the manifest is available" do
+ filename = tmpfile('myfile')
+ File.open(filename, 'w'){|f| }
+ Puppet.settings[:manifest] = filename
+ @parser.expects(:file=).with filename
+ @parser.expects(:parse)
+ @env.instance_eval { perform_initial_import }
+ end
+
+ it "should pass the manifest file to the parser even if it does not exist on disk" do
+ filename = tmpfile('myfile')
+ Puppet.settings[:code] = ""
+ Puppet.settings[:manifest] = filename
+ @parser.expects(:file=).with(filename).once
+ @parser.expects(:parse).once
+ @env.instance_eval { perform_initial_import }
+ end
+
+ it "should fail helpfully if there is an error importing" do
+ File.stubs(:exist?).returns true
++ @env.stubs(:known_resource_types).returns Puppet::Resource::TypeCollection.new(@env)
+ @parser.expects(:file=).once
+ @parser.expects(:parse).raises ArgumentError
+ lambda { @env.instance_eval { perform_initial_import } }.should raise_error(Puppet::Error)
+ end
+
+ it "should not do anything if the ignore_import settings is set" do
+ Puppet.settings[:ignoreimport] = true
+ @parser.expects(:string=).never
+ @parser.expects(:file=).never
+ @parser.expects(:parse).never
+ @env.instance_eval { perform_initial_import }
+ end
++
++ it "should mark the type collection as needing a reparse when there is an error parsing" do
++ @parser.expects(:parse).raises Puppet::ParseError.new("Syntax error at ...")
++ @env.stubs(:known_resource_types).returns Puppet::Resource::TypeCollection.new(@env)
++
++ lambda { @env.instance_eval { perform_initial_import } }.should raise_error(Puppet::Error, /Syntax error at .../)
++ @env.known_resource_types.require_reparse?.should be_true
++ end
+ end
end
diff --combined spec/unit/provider/package/gem_spec.rb
index 7c0d34d,32c067a..c2bd3cc
--- a/spec/unit/provider/package/gem_spec.rb
+++ b/spec/unit/provider/package/gem_spec.rb
@@@ -1,6 -1,6 +1,6 @@@
#!/usr/bin/env ruby
-require File.dirname(__FILE__) + '/../../../spec_helper'
+require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
provider_class = Puppet::Type.type(:package).provider(:gem)
@@@ -42,8 -42,18 +42,18 @@@ describe provider_class d
@provider.install
end
+ it "should specify that documentation should not be included" do
+ @provider.expects(:execute).with { |args| args[3] == "--no-rdoc" }.returns ""
+ @provider.install
+ end
+
+ it "should specify that RI should not be included" do
+ @provider.expects(:execute).with { |args| args[4] == "--no-ri" }.returns ""
+ @provider.install
+ end
+
it "should specify the package name" do
- @provider.expects(:execute).with { |args| args[3] == "myresource" }.returns ""
+ @provider.expects(:execute).with { |args| args[5] == "myresource" }.returns ""
@provider.install
end
--
Puppet packaging for Debian
More information about the Pkg-puppet-devel
mailing list