summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2005-05-30 01:36:48 +0000
committerLuke Kanies <luke@madstop.com>2005-05-30 01:36:48 +0000
commit2b97b479688e987a8d9e663fd926108e7c02e7e4 (patch)
tree268177c182c37a118bae0497812dca0b345a08b2 /lib
parentb46135f84cefbc28d41dc6c4da42b93e08da8648 (diff)
downloadpuppet-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.rb95
-rw-r--r--lib/blink/transaction.rb28
-rw-r--r--lib/blink/type.rb116
-rw-r--r--lib/blink/type/component.rb12
-rw-r--r--lib/blink/type/file.rb55
-rw-r--r--lib/blink/type/service.rb4
-rw-r--r--lib/blink/type/state.rb9
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
#---------------------------------------------------------------