diff options
author | Luke Kanies <luke@madstop.com> | 2005-05-30 01:36:48 +0000 |
---|---|---|
committer | Luke Kanies <luke@madstop.com> | 2005-05-30 01:36:48 +0000 |
commit | 2b97b479688e987a8d9e663fd926108e7c02e7e4 (patch) | |
tree | 268177c182c37a118bae0497812dca0b345a08b2 /lib | |
parent | b46135f84cefbc28d41dc6c4da42b93e08da8648 (diff) | |
download | puppet-2b97b479688e987a8d9e663fd926108e7c02e7e4.tar.gz puppet-2b97b479688e987a8d9e663fd926108e7c02e7e4.tar.xz puppet-2b97b479688e987a8d9e663fd926108e7c02e7e4.zip |
there are now explicit tests for transactions, including rollback, and more tests involving querying
git-svn-id: https://reductivelabs.com/svn/puppet/library/trunk@282 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib')
-rw-r--r-- | lib/blink/statechange.rb | 95 | ||||
-rw-r--r-- | lib/blink/transaction.rb | 28 | ||||
-rw-r--r-- | lib/blink/type.rb | 116 | ||||
-rw-r--r-- | lib/blink/type/component.rb | 12 | ||||
-rw-r--r-- | lib/blink/type/file.rb | 55 | ||||
-rw-r--r-- | lib/blink/type/service.rb | 4 | ||||
-rw-r--r-- | lib/blink/type/state.rb | 9 |
7 files changed, 203 insertions, 116 deletions
diff --git a/lib/blink/statechange.rb b/lib/blink/statechange.rb index e50f67c5a..e5d27cc58 100644 --- a/lib/blink/statechange.rb +++ b/lib/blink/statechange.rb @@ -8,7 +8,7 @@ module Blink class StateChange - attr_accessor :is, :should, :type, :path, :state, :transaction + attr_accessor :is, :should, :type, :path, :state, :transaction, :run #--------------------------------------------------------------- def initialize(state) @@ -17,6 +17,51 @@ module Blink @path = state.fqpath @is = state.is @should = state.should + + @run = false + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + def go + if @state.noop + Blink.notice "%s is noop" % @state + return nil + end + + begin + event = @state.sync + @run = true + + # default to a simple event type + if event.nil? + event = @state.parent.name.id2name + "_changed" + elsif ! event.is_a?(Symbol) + Blink.notice "State '%s' returned invalid event '%s'; resetting to default" % + [@state.class,event] + + event = @state.parent.name.id2name + "_changed" + end + + # i should maybe include object type, but the event type + # should basically point to that, right? + return Blink::Event.new( + :event => event, + :object => @state.parent, + :transaction => @transaction, + :message => self.to_s + ) + rescue => detail + Blink.error "%s failed: %s" % [self.to_s,detail] + # there should be a way to ask the state what type of event + # it would have generated, but... + return Blink::Event.new( + :event => @state.parent.name.id2name + "_failed", + :object => @state.parent, + :transaction => @transaction, + :message => "Failed: " + self.to_s + ) + end end #--------------------------------------------------------------- @@ -28,50 +73,20 @@ module Blink raise "StateChange '%s' tried to be executed outside of transaction" % self end - if @state.noop - Blink.notice "%s is noop" % @state - Blink.notice "change noop is %s" % @state.noop - else - Blink.notice "Calling sync on %s" % @state - begin - event = @state.sync - - # default to a simple event type - if event.nil? - event = @state.parent.name.id2name + "_changed" - elsif ! event.is_a?(Symbol) - Blink.notice "State '%s' retuned invalid event '%s'; resetting to default" % - [@state.class,event] - - event = @state.parent.name.id2name + "_changed" - end - - # i should maybe include object type, but the event type - # should basically point to that, right? - return Blink::Event.new( - :event => event, - :object => @state.parent, - :transaction => @transaction, - :message => self.to_s - ) - rescue => detail - Blink.error "%s failed: %s" % [self.to_s,detail] - # there should be a way to ask the state what type of event - # it would have generated, but... - return Blink::Event.new( - :event => @state.parent.name.id2name + "_failed", - :object => @state.parent, - :transaction => @transaction, - :message => "Failed: " + self.to_s - ) - end - end + + return self.go end #--------------------------------------------------------------- #--------------------------------------------------------------- def backward - raise "Moving statechanges backward is currently unsupported" + @state.should = @is + @state.retrieve + + Blink.notice "Rolling %s backward" % self + return self.go + + #raise "Moving statechanges backward is currently unsupported" #@type.change(@path,@should,@is) end #--------------------------------------------------------------- diff --git a/lib/blink/transaction.rb b/lib/blink/transaction.rb index fcdca0128..f5252b436 100644 --- a/lib/blink/transaction.rb +++ b/lib/blink/transaction.rb @@ -104,6 +104,34 @@ class Transaction } end #--------------------------------------------------------------- + + #--------------------------------------------------------------- + def rollback + @changes.each { |change| + if change.is_a?(Blink::StateChange) + next unless change.run + #change.transaction = self + begin + change.backward + #@@changed.push change.state.parent + rescue => detail + Blink.error("%s rollback failed: %s" % [change,detail]) + # at this point, we would normally do error handling + # but i haven't decided what to do for that yet + # so just record that a sync failed for a given object + #@@failures[change.state.parent] += 1 + # this still could get hairy; what if file contents changed, + # but a chmod failed? how would i handle that error? dern + end + elsif change.is_a?(Blink::Transaction) + # yay, recursion + change.rollback + else + raise "Transactions cannot handle objects of type %s" % child.class + end + } + end + #--------------------------------------------------------------- end end #--------------------------------------------------------------- diff --git a/lib/blink/type.rb b/lib/blink/type.rb index b25a4e6c0..4f43921d3 100644 --- a/lib/blink/type.rb +++ b/lib/blink/type.rb @@ -47,6 +47,7 @@ class Blink::Type < Blink::Element @@metaparams = [ :onerror, :schedule, + :check, :require ] @@ -453,6 +454,15 @@ class Blink::Type < Blink::Element @children = [] @evalcount = 0 + # states and parameters are treated equivalently from the outside: + # as name-value pairs (using [] and []=) + # internally, however, parameters are merely a hash, while states + # point to State objects + # further, the lists of valid states and parameters are defined + # at the class level + @states = Hash.new(false) + @parameters = Hash.new(false) + @noop = false # which objects to notify when we change @@ -468,21 +478,6 @@ class Blink::Type < Blink::Element @syncedchanges = 0 @failedchanges = 0 - # which attributes we care about even though they don't have - # values - # this isn't used right now, and isn't likely to be until we support - # querying - @monitor = Array.new - - #namevar = self.class.namevar - #if namevar != :name - # unless hash.include?(namevar) - # raise "Objects of %s type must be passed %s" % [self.class,namevar] - # end - # hash[namevar] = hash[:name] - # hash.delete(:name) - #end - # convert all strings to symbols hash.each { |var,value| unless var.is_a? Symbol hash[var.intern] = value @@ -490,32 +485,11 @@ class Blink::Type < Blink::Element end } - # if they passed in a list of states they're interested in, - # we mark them as "interesting" - # XXX maybe we should just consider params set to nil as 'interesting' - # - # this isn't used as much as it should be, but the idea is that - # the "interesting" states would be the ones retrieved during a - # 'retrieve' call - if hash.include?(:check) - @monitor = hash[:check].dup - hash.delete(:check) - end - if hash.include?(:noop) @noop = hash[:noop] hash.delete(:noop) end - # states and parameters are treated equivalently from the outside: - # as name-value pairs (using [] and []=) - # internally, however, parameters are merely a hash, while states - # point to State objects - # further, the lists of valid states and parameters are defined - # at the class level - @states = Hash.new(false) - @parameters = Hash.new(false) - # we have to set the name of our object before anything else, # because it might be used in creating the other states namevar = self.class.namevar @@ -538,7 +512,6 @@ class Blink::Type < Blink::Element end hash.each { |param,value| - @monitor.push(param) #Blink.debug("adding param '%s' with value '%s'" % # [param,value]) self[param] = value @@ -569,6 +542,14 @@ class Blink::Type < Blink::Element #--------------------------------------------------------------- #--------------------------------------------------------------- + def retrieve + self.collect { |child| + child.retrieve + } + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- def to_s self.name end @@ -581,15 +562,8 @@ class Blink::Type < Blink::Element #--------------------------------------------------------------- #--------------------------------------------------------------- - # iterate across all children, and then iterate across states - # we do children first so we're sure that all dependent objects - # are checked first - # we ignore parameters here, because they only modify how work gets - # done, they don't ever actually result in work specifically - def each - # we want to return the states in the order that each type - # specifies it, because it may (as in the case of File#create) - # be important + def eachstate + Blink.debug "have %s states" % @states.length tmpstates = [] self.class.states.each { |state| if @states.include?(state.name) @@ -599,9 +573,28 @@ class Blink::Type < Blink::Element unless tmpstates.length == @states.length raise "Something went very wrong with tmpstates creation" end - [@children,tmpstates].flatten.each { |child| + tmpstates.each { |state| + yield state + } + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- + # iterate across all children, and then iterate across states + # we do children first so we're sure that all dependent objects + # are checked first + # we ignore parameters here, because they only modify how work gets + # done, they don't ever actually result in work specifically + def each + # we want to return the states in the order that each type + # specifies it, because it may (as in the case of File#create) + # be important + @children.each { |child| yield child } + self.eachstate { |state| + yield state + } end #--------------------------------------------------------------- @@ -682,6 +675,35 @@ class Blink::Type < Blink::Element #--------------------------------------------------------------- #--------------------------------------------------------------- + # this just marks states that we definitely want to retrieve values + # on + def metacheck(args) + unless args.is_a?(Array) + args = [args] + end + + # these are states that we might not have values for but we want to retrieve + # values for anyway + args.each { |state| + unless state.is_a?(Symbol) + state = state.intern + end + next if @states.include?(state) + + stateklass = nil + unless stateklass = self.class.validstate(state) + raise "%s is not a valid state for %s" % [state,self.class] + end + + # XXX it's probably a bad idea to have code this important in + # two places + @states[state] = stateklass.new() + @states[state].parent = self + } + end + #--------------------------------------------------------------- + + #--------------------------------------------------------------- def metaonerror(response) Blink.debug("Would have called metaonerror") @onerror = response diff --git a/lib/blink/type/component.rb b/lib/blink/type/component.rb index 91eff0390..c0e13e0ac 100644 --- a/lib/blink/type/component.rb +++ b/lib/blink/type/component.rb @@ -11,8 +11,14 @@ require 'blink/transaction' module Blink class Component < Blink::Element + include Enumerable + @name = :container + def each + @children.each { |child| yield child } + end + def initialize @children = [] end @@ -35,5 +41,11 @@ module Blink @children.push child } end + + def retrieve + self.collect { |child| + child.retrieve + } + end end end diff --git a/lib/blink/type/file.rb b/lib/blink/type/file.rb index 4784fe054..d7d7a1283 100644 --- a/lib/blink/type/file.rb +++ b/lib/blink/type/file.rb @@ -52,19 +52,22 @@ module Blink end self.is = stat.uid - unless self.should.is_a?(Integer) - begin - user = Etc.getpwnam(self.should) - if user.gid == "" - raise "Could not retrieve uid for '%s'" % self.parent + if defined? @should + unless @should.is_a?(Integer) + begin + user = Etc.getpwnam(@should) + if user.gid == "" + raise "Could not retrieve uid for '%s'" % self.parent + end + Blink.debug "converting %s to integer '%d'" % + [@should,user.uid] + @should = user.uid + rescue + raise "Could not get any info on user '%s'" % @should end - Blink.debug "converting %s to integer '%d'" % - [self.should,user.uid] - self.should = user.uid - rescue - raise "Could not get any info on user '%s'" % self.should end end + Blink.debug "chown state is %d" % self.is end @@ -100,7 +103,7 @@ module Blink @name = :mode @event = :inode_changed - def initialize(should) + def should=(should) # this is pretty hackish, but i need to make sure the number is in # octal, yet the number can only be specified as a string right now unless should.is_a?(Integer) # i've already converted it correctly @@ -109,7 +112,7 @@ module Blink end should = Integer(should) end - super(should) + @should = should end def retrieve @@ -196,20 +199,22 @@ module Blink # we probably shouldn't actually modify the 'should' value # but i don't see a good way around it right now # mmmm, should - unless self.should.is_a?(Integer) - begin - group = Etc.getgrnam(self.should) - # yeah, don't ask me - # this is retarded - #p group - if group.gid == "" - raise "Could not retrieve gid for %s" % self.parent + if defined? @should + unless self.should.is_a?(Integer) + begin + group = Etc.getgrnam(self.should) + # yeah, don't ask me + # this is retarded + #p group + if group.gid == "" + raise "Could not retrieve gid for %s" % self.parent + end + Blink.debug "converting %s to integer %d" % + [self.should,group.gid] + self.should = group.gid + rescue + raise "Could not get any info on group %s" % self.should end - Blink.debug "converting %s to integer %d" % - [self.should,group.gid] - self.should = group.gid - rescue - raise "Could not get any info on group %s" % self.should end end Blink.debug "chgrp state is %d" % self.is diff --git a/lib/blink/type/service.rb b/lib/blink/type/service.rb index 24228cdab..dbae98d9c 100644 --- a/lib/blink/type/service.rb +++ b/lib/blink/type/service.rb @@ -15,7 +15,7 @@ module Blink # this whole thing is annoying # i should probably just be using booleans, but for now, i'm not... - def initialize(should) + def should=(should) if should == false should = 0 elsif should == true @@ -29,7 +29,7 @@ module Blink [self.class,should] should = 0 end - super(should) + @should = should end def retrieve diff --git a/lib/blink/type/state.rb b/lib/blink/type/state.rb index 042e3784b..5b32ccd68 100644 --- a/lib/blink/type/state.rb +++ b/lib/blink/type/state.rb @@ -70,9 +70,14 @@ class Blink::State < Blink::Element #--------------------------------------------------------------- #--------------------------------------------------------------- - def initialize(should) + def initialize(*should) @is = nil - @should = should + + if should.length > 0 # we got passed an argument + @should = should.shift + else # we got passed no argument + # leave @should undefined + end @parent = nil end #--------------------------------------------------------------- |