diff options
| author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-12-23 04:49:56 +0000 |
|---|---|---|
| committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-12-23 04:49:56 +0000 |
| commit | 9bb5c50d0b30b4dfb82b6b705dfcbf0e126a9d61 (patch) | |
| tree | e41fbeb90e4050ea2af6d37e7b443cf9f84be162 /lib | |
| parent | be711d357857f5e6d4a28a22bd60dd89e9e136c0 (diff) | |
| download | puppet-9bb5c50d0b30b4dfb82b6b705dfcbf0e126a9d61.tar.gz puppet-9bb5c50d0b30b4dfb82b6b705dfcbf0e126a9d61.tar.xz puppet-9bb5c50d0b30b4dfb82b6b705dfcbf0e126a9d61.zip | |
Not downcasing facts any longer, closing #210 (although not using the patch from mpalmer, since I had not noticed the patch was there). Also, making all nodes, classes, and definitions case insensitive, closing #344. Finally, I added case insensitivity to the language in general, which should preserve backwards compatibility and probably makes the most sense in the long run anyway.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1964 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/puppet/client/master.rb | 2 | ||||
| -rw-r--r-- | lib/puppet/event.rb | 16 | ||||
| -rw-r--r-- | lib/puppet/log.rb | 13 | ||||
| -rw-r--r-- | lib/puppet/parser/ast.rb | 14 | ||||
| -rw-r--r-- | lib/puppet/parser/ast/casestatement.rb | 11 | ||||
| -rw-r--r-- | lib/puppet/parser/ast/selector.rb | 10 | ||||
| -rw-r--r-- | lib/puppet/parser/interpreter.rb | 12 | ||||
| -rw-r--r-- | lib/puppet/pgraph.rb | 13 | ||||
| -rw-r--r-- | lib/puppet/statechange.rb | 95 | ||||
| -rw-r--r-- | lib/puppet/transaction.rb | 45 |
10 files changed, 132 insertions, 99 deletions
diff --git a/lib/puppet/client/master.rb b/lib/puppet/client/master.rb index d6997f631..e6e7c7835 100644 --- a/lib/puppet/client/master.rb +++ b/lib/puppet/client/master.rb @@ -83,7 +83,7 @@ class Puppet::Client::MasterClient < Puppet::Client facts = {} Facter.each { |name,fact| - facts[name] = fact.to_s.downcase + facts[name] = fact.to_s } # Add our client version to the list of facts, so people can use it diff --git a/lib/puppet/event.rb b/lib/puppet/event.rb index 98ea92c9d..16e76bf50 100644 --- a/lib/puppet/event.rb +++ b/lib/puppet/event.rb @@ -1,5 +1,6 @@ require 'puppet' -require 'puppet/type' +require 'puppet/util/methodhelper' +require 'puppet/util/errors' module Puppet # events are transient packets of information; they result in one or more (or none) @@ -7,19 +8,16 @@ module Puppet # eventually, these will be passed on to some central event system class Event include Puppet + include Puppet::Util::MethodHelper + include Puppet::Util::Errors + attr_accessor :event, :source, :transaction @@events = [] def initialize(args) - unless args.include?(:event) and args.include?(:source) - raise Puppet::DevError, "Event.new called incorrectly" - end - - @change = args[:change] - @event = args[:event] - @source = args[:source] - @transaction = args[:transaction] + set_options symbolize_options(args) + requiredopts(:event, :source) end def to_s diff --git a/lib/puppet/log.rb b/lib/puppet/log.rb index 8362e8d4d..53535e90c 100644 --- a/lib/puppet/log.rb +++ b/lib/puppet/log.rb @@ -368,6 +368,19 @@ module Puppet end end + # Log to an array, just for testing. + newdesttype :array do + match "Array" + + def initialize(array) + @array = array + end + + def handle(msg) + @array << msg + end + end + # Create a new log destination. def Log.newdestination(dest) # Each destination can only occur once. diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb index ccd6d216a..e8cfcc4dd 100644 --- a/lib/puppet/parser/ast.rb +++ b/lib/puppet/parser/ast.rb @@ -80,24 +80,18 @@ class Puppet::Parser::AST # correctly handles errors. It is critical to use this method because # it can enable you to catch the error where it happens, rather than # much higher up the stack. - def safeevaluate(*args) + def safeevaluate(options) # We duplicate code here, rather than using exceptwrap, because this # is called so many times during parsing. - #exceptwrap do - # self.evaluate(*args) - #end begin - return self.evaluate(*args) + return self.evaluate(options) rescue Puppet::Error => detail raise adderrorcontext(detail) rescue => detail - message = options[:message] || "%s failed with error %s: %s" % - [self.class, detail.class, detail.to_s] - - error = options[:type].new(message) + error = Puppet::Error.new(detail.to_s) # We can't use self.fail here because it always expects strings, # not exceptions. - raise adderrorcontext(error, detail) + raise adderrorcontext(error) end end diff --git a/lib/puppet/parser/ast/casestatement.rb b/lib/puppet/parser/ast/casestatement.rb index 6543293b4..b4197d9b4 100644 --- a/lib/puppet/parser/ast/casestatement.rb +++ b/lib/puppet/parser/ast/casestatement.rb @@ -11,13 +11,21 @@ class Puppet::Parser::AST def evaluate(hash) scope = hash[:scope] value = @test.safeevaluate(:scope => scope) + sensitive = Puppet[:casesensitive] + value = value.downcase if ! sensitive and value.respond_to?(:downcase) retvalue = nil found = false # Iterate across the options looking for a match. @options.each { |option| - if option.eachvalue(scope) { |opval| break true if opval == value } + if option.eachvalue(scope) { |opval| + opval = opval.downcase if ! sensitive and opval.respond_to?(:downcase) + # break true if opval == value + if opval == value + break true + end + } # we found a matching option retvalue = option.safeevaluate(:scope => scope) found = true @@ -31,6 +39,7 @@ class Puppet::Parser::AST retvalue = @default.safeevaluate(:scope => scope) else Puppet.debug "No true answers and no default" + retvalue = nil end end return retvalue diff --git a/lib/puppet/parser/ast/selector.rb b/lib/puppet/parser/ast/selector.rb index 94b7a5583..ce421e491 100644 --- a/lib/puppet/parser/ast/selector.rb +++ b/lib/puppet/parser/ast/selector.rb @@ -18,10 +18,15 @@ class Puppet::Parser::AST # Get our parameter. paramvalue = @param.safeevaluate(:scope => scope) + + sensitive = Puppet[:casesensitive] + + if ! sensitive and paramvalue.respond_to?(:downcase) + paramvalue = paramvalue.downcase + end default = nil - #@values = [@values] unless @values.instance_of? AST::ASTArray unless @values.instance_of? AST::ASTArray or @values.instance_of? Array @values = [@values] end @@ -29,6 +34,9 @@ class Puppet::Parser::AST # Then look for a match in the options. @values.each { |obj| param = obj.param.safeevaluate(:scope => scope) + if ! sensitive && param.respond_to?(:downcase) + param = param.downcase + end if param == paramvalue # we found a matching option retvalue = obj.value.safeevaluate(:scope => scope) diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb index 5144c4970..a81b7939f 100644 --- a/lib/puppet/parser/interpreter.rb +++ b/lib/puppet/parser/interpreter.rb @@ -10,6 +10,12 @@ require 'puppet/parser/scope' class Puppet::Parser::Interpreter include Puppet::Util + + Puppet.setdefaults(:puppet, + :casesensitive => [false, + "Whether matching in case statements and selectors + should be case-sensitive. Case insensitivity is + handled by downcasing all values before comparison."]) Puppet.setdefaults("ldap", :ldapnodes => [false, @@ -239,6 +245,8 @@ class Puppet::Parser::Interpreter # The recursive method used to actually look these objects up. def fqfind(namespace, name, table) + namespace = namespace.downcase + name = name.downcase if name =~ /^::/ or namespace == "" return table[name.sub(/^::/, '')] end @@ -469,6 +477,7 @@ class Puppet::Parser::Interpreter # Create a new class, or merge with an existing class. def newclass(fqname, options = {}) + fqname = fqname.downcase if @definetable.include?(fqname) raise Puppet::ParseError, "Cannot redefine class %s as a definition" % fqname @@ -521,6 +530,7 @@ class Puppet::Parser::Interpreter # Create a new definition. def newdefine(fqname, options = {}) + fqname = fqname.downcase if @classtable.include?(fqname) raise Puppet::ParseError, "Cannot redefine class %s as a definition" % fqname @@ -551,6 +561,7 @@ class Puppet::Parser::Interpreter def newnode(names, options = {}) names = [names] unless names.instance_of?(Array) names.collect do |name| + name = name.to_s.downcase if other = @nodetable[name] @parser.error("Node %s is already defined at %s:%s; cannot redefine" % [other.name, other.file, other.line]) end @@ -585,6 +596,7 @@ class Puppet::Parser::Interpreter # Search for our node in the various locations. def nodesearch(*nodes) + nodes = nodes.collect { |n| n.to_s.downcase } # At this point, stop at the first source that defines # the node @nodesources.each do |source| diff --git a/lib/puppet/pgraph.rb b/lib/puppet/pgraph.rb index 7be785477..36df0cc96 100644 --- a/lib/puppet/pgraph.rb +++ b/lib/puppet/pgraph.rb @@ -66,13 +66,14 @@ class Puppet::PGraph < GRATR::Digraph # Collect all of the edges that the passed events match. Returns # an array of edges. - def matching_edges(source, events) - unless vertex?(source) - Puppet.warning "Got an event from invalid vertex %s" % source.ref - return [] - end - + def matching_edges(events, base = nil) events.collect do |event| + source = base || event.source + + unless vertex?(source) + Puppet.warning "Got an event from invalid vertex %s" % source.ref + next + end # 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. diff --git a/lib/puppet/statechange.rb b/lib/puppet/statechange.rb index 4884026fe..de160d584 100644 --- a/lib/puppet/statechange.rb +++ b/lib/puppet/statechange.rb @@ -6,21 +6,40 @@ module Puppet # Handle all of the work around performing an actual change, # including calling 'sync' on the states and producing events. class StateChange - attr_accessor :is, :should, :type, :path, :state, :transaction, :changed + attr_accessor :is, :should, :type, :path, :state, :transaction, :changed, :proxy # The log file generated when this object was changed. attr_reader :report + + # Switch the goals of the state, thus running the change in reverse. + def backward + @state.should = @is + @state.retrieve + + unless defined? @transaction + raise Puppet::Error, + "StateChange '%s' tried to be executed outside of transaction" % + self + end + unless @state.insync? + @state.info "Backing %s" % self + return self.go + else + @state.debug "rollback is already in sync: %s vs. %s" % + [@state.is.inspect, @state.should.inspect] + return nil + end + end + + def changed? + self.changed + end def initialize(state) @state = state @path = [state.path,"change"].flatten @is = state.is - if state.insync? - raise Puppet::Error.new( - "Tried to create a change for in-sync state %s" % state.name - ) - end @should = state.should @changed = false @@ -29,20 +48,7 @@ module Puppet # Perform the actual change. This method can go either forward or # backward, and produces an event. def go - if @state.insync? - @state.info "Already in sync" - return nil - end - - if @state.noop - @state.log "is %s, should be %s (noop)" % - [state.is_to_s, state.should_to_s] - #@state.debug "%s is noop" % @state - return nil - end - - #@state.info "Is: %s, Should: %s" % - # [@state.is.inspect, @state.should.inspect] + return nil if skip? # The transaction catches any exceptions here. events = @state.sync @@ -60,24 +66,18 @@ module Puppet return events.collect { |event| # default to a simple event type - if ! event.is_a?(Symbol) + unless event.is_a?(Symbol) @state.warning("State '%s' returned invalid event '%s'; resetting to default" % [@state.class,event]) event = @state.parent.class.name.id2name + "_changed" end - - # i should maybe include object type, but the event type - # should basically point to that, right? - #:state => @state, - #:object => @state.parent, + @report = @state.log(@state.change_to_s) Puppet::Event.new( :event => event, - :change => self, :transaction => @transaction, - :source => @state.parent, - :message => self.to_s + :source => self.source ) } end @@ -93,29 +93,28 @@ module Puppet return self.go end - - # Switch the goals of the state, thus running the change in reverse. - def backward - @state.should = @is - @state.retrieve - - unless defined? @transaction - raise Puppet::Error, - "StateChange '%s' tried to be executed outside of transaction" % - self + + def noop + return @state.noop + end + + def skip? + if @state.insync? + @state.info "Already in sync" + return true end - unless @state.insync? - @state.info "Backing %s" % self - return self.go - else - @state.debug "rollback is already in sync: %s vs. %s" % - [@state.is.inspect, @state.should.inspect] - return nil + + if @state.noop + @state.log "is %s, should be %s (noop)" % + [state.is_to_s, state.should_to_s] + #@state.debug "%s is noop" % @state + return true end + return false end - def noop - return @state.noop + def source + self.proxy || @state.parent end def to_s diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb index 2feb3e27d..a7862aea2 100644 --- a/lib/puppet/transaction.rb +++ b/lib/puppet/transaction.rb @@ -47,6 +47,7 @@ class Transaction # And then return return [] end + changes = [changes] unless changes.is_a?(Array) # If a resource is going to be deleted but it still has dependencies, then # don't delete it unless it's implicit. @@ -79,6 +80,7 @@ class Transaction if Puppet[:trace] puts detail.backtrace end + puts detail change.state.err "change from %s to %s failed: %s" % [change.state.is_to_s, change.state.should_to_s, detail] @failures[resource] += 1 @@ -134,27 +136,13 @@ class Transaction # child resource. def copy_relationships(resource, children) depthfirst = resource.depthfirst? - - # We only have to worry about dependents, because any dependencies - # already missed their chance to register an event for us. - #dependents = @relgraph.adjacent(resource, - # :direction => :out, :type => :edges).reject { |e| ! e.callback } - - #sources = @relgraph.adjacent(resource, - # :direction => :in, :type => :edges).reject { |e| ! e.callback } - + children.each do |gen_child| if depthfirst @relgraph.add_edge!(gen_child, resource) else @relgraph.add_edge!(resource, gen_child) end - #dependents.each do |edge| - # @relgraph.add_edge!(gen_child, edge.target, edge.label) - #end - #sources.each do |edge| - # @relgraph.add_edge!(edge.source, gen_child, edge.label) - #end end end @@ -189,11 +177,13 @@ class Transaction else @resourcemetrics[:scheduled] += 1 + changecount = @changes.length + # We need to generate first regardless, because the recursive # actions sometimes change how the top resource is applied. children = eval_generate(resource) - if resource.depthfirst? and children + if children and resource.depthfirst? children.each do |child| # The child will never be skipped when the parent isn't events += eval_resource(child, false) @@ -205,11 +195,19 @@ class Transaction events += apply(resource) end - if ! resource.depthfirst? and children + if children and ! resource.depthfirst? children.each do |child| - events += eval_resource(child) + events += eval_resource(child, false) end end + + # A bit of hackery here -- if skipcheck is true, then we're the top-level + # resource. If that's the case, then make sure all of the changes list this resource + # as a proxy. This is really only necessary for rollback, since we know the generating + # resource during forward changes. + if children and checkskip + @changes[changecount..-1].each { |change| change.proxy = resource } + end # Keep track of how long we spend in each type of resource @timemetrics[resource.class.name] += seconds @@ -220,8 +218,10 @@ class Transaction events += triggedevents end - # Collect the targets of any subscriptions to those events - @relgraph.matching_edges(resource, events).each do |edge| + # Collect the targets of any subscriptions to those events. We pass the parent resource + # in so it will override the source in the events, since eval_generated children can't + # have direct relationships. + @relgraph.matching_edges(events, resource).each do |edge| @targets[edge.target] << edge end @@ -360,6 +360,7 @@ class Transaction end @report = Report.new + @count = 0 end # Prefetch any providers that support it. We don't support prefetching @@ -507,7 +508,6 @@ class Transaction def skip?(resource) skip = false if ! tagged?(resource) - p resource.tags resource.debug "Not tagged with %s" % tags.join(", ") elsif ! scheduled?(resource) resource.debug "Not scheduled" @@ -604,8 +604,7 @@ class Transaction trigged << Puppet::Event.new( :event => :triggered, :transaction => self, - :source => obj, - :message => message + :source => obj ) triggered(obj, callback) |
