summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-12-23 04:49:56 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-12-23 04:49:56 +0000
commit9bb5c50d0b30b4dfb82b6b705dfcbf0e126a9d61 (patch)
treee41fbeb90e4050ea2af6d37e7b443cf9f84be162 /lib
parentbe711d357857f5e6d4a28a22bd60dd89e9e136c0 (diff)
downloadpuppet-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.rb2
-rw-r--r--lib/puppet/event.rb16
-rw-r--r--lib/puppet/log.rb13
-rw-r--r--lib/puppet/parser/ast.rb14
-rw-r--r--lib/puppet/parser/ast/casestatement.rb11
-rw-r--r--lib/puppet/parser/ast/selector.rb10
-rw-r--r--lib/puppet/parser/interpreter.rb12
-rw-r--r--lib/puppet/pgraph.rb13
-rw-r--r--lib/puppet/statechange.rb95
-rw-r--r--lib/puppet/transaction.rb45
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)