diff options
-rw-r--r-- | lib/puppet/client.rb | 10 | ||||
-rw-r--r-- | lib/puppet/type.rb | 132 | ||||
-rw-r--r-- | lib/puppet/type/component.rb | 6 | ||||
-rwxr-xr-x | test/other/events.rb | 2 | ||||
-rwxr-xr-x | test/other/relationships.rb | 2 | ||||
-rwxr-xr-x | test/types/component.rb | 6 | ||||
-rwxr-xr-x | test/types/cron.rb | 12 | ||||
-rwxr-xr-x | test/types/exec.rb | 6 | ||||
-rw-r--r-- | test/types/file.rb | 1 | ||||
-rw-r--r-- | test/types/type.rb | 28 |
10 files changed, 178 insertions, 27 deletions
diff --git a/lib/puppet/client.rb b/lib/puppet/client.rb index c58f33ec3..15c2acdd7 100644 --- a/lib/puppet/client.rb +++ b/lib/puppet/client.rb @@ -235,10 +235,9 @@ module Puppet facts end - # this method is how the client receives the tree of Transportable - # objects - # for now, just descend into the tree and perform and necessary - # manipulations + # This method is how the client receives the tree of Transportable + # objects. For now, just descend into the tree and perform and + # necessary manipulations. def apply unless defined? @objects raise Puppet::Error, "Cannot apply; objects not defined" @@ -260,6 +259,9 @@ module Puppet # FIXME this should be in getconfig, not apply container = @objects.to_type + + # Now perform any necessary final actions before we evaluate. + Puppet::Type.finalize #if @local # container = @objects.to_type #else diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index 135b3b427..1b9f61ac8 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -142,6 +142,7 @@ class Type < Puppet::Element def self.initvars # all of the instances of this class @objects = Hash.new + @aliases = Hash.new @validstates = {} @@ -180,10 +181,32 @@ class Type < Puppet::Element public + # Create an alias. We keep these in a separate hash so that we don't encounter + # the objects multiple times when iterating over them. + def self.alias(name, obj) + if @objects.include?(name) + raise Puppet::Error.new( + "Cannot create alias %s: object already exists" % + [name] + ) + end + + if @aliases.include?(name) + raise Puppet::Error.new( + "Object %s already has alias %s" % + [@aliases[name].name, name] + ) + end + + @aliases[name] = obj + end + # retrieve a named instance of the current type def self.[](name) if @objects.has_key?(name) return @objects[name] + elsif @aliases.has_key?(name) + return @aliases[name] else return nil end @@ -221,6 +244,7 @@ class Type < Puppet::Element @@typeary.each { |subtype| subtype.clear } + @finalized = false end # remove all of the instances of a single type @@ -249,6 +273,23 @@ class Type < Puppet::Element } end + # Perform any operations that need to be done between instance creation + # and instance evaluation. + def self.finalize + self.mkdepends + + @finalized = true + end + + # Has the finalize method been called yet? + def self.finalized? + if defined? @finalized + return @finalized + else + return false + end + end + # does the type have an object with the given name? def self.has_key?(name) return @objects.has_key?(name) @@ -540,27 +581,31 @@ class Type < Puppet::Element if name == :name name = self.class.namevar end - if self.class.validstate?(name) + case self.class.attrtype(name) + when :state + #if self.class.validstate?(name) if @states.include?(name) return @states[name].is else return nil end - elsif Puppet::Type.metaparam?(name) + when :meta + #elsif Puppet::Type.metaparam?(name) if @metaparams.include?(name) return @metaparams[name].value else - if default = self.class.metaattrclass(name).default + if default = self.class.metaparamclass(name).default return default else return nil end end - elsif self.class.validparameter?(name) + when :param + #elsif self.class.validparameter?(name) if @parameters.include?(name) return @parameters[name].value else - if default = self.class.attrclass(name).default + if default = self.class.paramclass(name).default return default else return nil @@ -1053,14 +1098,21 @@ class Type < Puppet::Element unless list.is_a?(Array) list = [list] end + + # Collect the current prereqs list.each { |dep| - if obj = typeobj[dep] - unless self.requires?(obj) - self.info "Auto-requiring %s" % obj.name - self[:require] = [type, dep] - end - end + # Skip autorequires that we aren't managing + next unless obj = typeobj[dep] + + # Skip autorequires that we already require + next if self.requires?(obj) + self.info "Auto-requiring %s" % obj.name + + self[:require] = [type, dep] } + + #self.info reqs.inspect + #self[:require] = reqs } end @@ -1355,6 +1407,39 @@ class Type < Puppet::Element # @callbacks[object][event] = method #end + # Build all of the dependencies for all of the different types. This is called + # after all of the objects are instantiated, so that we don't depend on + # file order. If we didn't use this (and instead just checked dependencies + # as we came across them), any required object would have to come before the + # requiring object in the file(s). + def self.mkdepends + @@typeary.each { |type| + type.builddepends + } + end + + # The per-type version of dependency building. This actually goes through + # all of the objects themselves and builds deps. + def self.builddepends + return unless defined? @objects + @objects.each { |name, obj| + obj.builddepends + } + end + + # Build the dependencies associated with an individual object. + def builddepends + # Handle the requires + if self[:require] + self.handledepends(self[:require], :NONE, nil) + end + + # And the subscriptions + if self[:subscribe] + self.handledepends(self[:subscribe], :ALL_EVENTS, :refresh) + end + end + # return all objects that we depend on def eachdependency Puppet::Event::Subscription.dependencies(self).each { |dep| @@ -1424,7 +1509,6 @@ class Type < Puppet::Element end def requires?(object) - #Puppet.notice "Checking reqs for %s" % object.name req = false self.eachdependency { |dep| if dep == object @@ -1548,8 +1632,22 @@ class Type < Puppet::Element This is used purely for guaranteeing that changes to required objects happen before the dependent object." + # Take whatever dependencies currently exist and add these. + # Note that this probably doesn't behave correctly with unsubscribe. munge do |requires| - @parent.handledepends(requires, :NONE, nil) + # We need to be two arrays deep... + unless requires.is_a?(Array) + requires = [requires] + end + unless requires[0].is_a?(Array) + requires = [requires] + end + if values = @parent[:require] + requires = values + requires + end + requires + #p @parent[:require] + #@parent.handledepends(requires, :NONE, nil) end end @@ -1561,7 +1659,11 @@ class Type < Puppet::Element refreshed (e.g., a service will get restarted)." munge do |requires| - @parent.handledepends(requires, :ALL_EVENTS, :refresh) + if values = @parent[:subscribe] + requires = values + requires + end + requires + # @parent.handledepends(requires, :ALL_EVENTS, :refresh) end end @@ -1610,7 +1712,7 @@ class Type < Puppet::Element end next end - @parent.class[other] = @parent + @parent.class.alias(other, @parent) end end end diff --git a/lib/puppet/type/component.rb b/lib/puppet/type/component.rb index 237c17724..1ffe05f19 100644 --- a/lib/puppet/type/component.rb +++ b/lib/puppet/type/component.rb @@ -85,6 +85,12 @@ module Puppet # this is only called on one component over the whole system # this also won't work with scheduling, but eh def evaluate + # The normal client process will automatically finalize things, but + # this simplifies a lot of test code -- as long as we use a + # compontent, we get finalized. + unless Puppet::Type.finalized? + Puppet::Type.finalize + end transaction = Puppet::Transaction.new(self.flatten) transaction.component = self return transaction diff --git a/test/other/events.rb b/test/other/events.rb index 911180b28..f57fd3272 100755 --- a/test/other/events.rb +++ b/test/other/events.rb @@ -98,6 +98,8 @@ class TestEvents < Test::Unit::TestCase comps[:b][:subscribe] = [[comps[:a].class.name, comps[:a].name]] + Puppet::Type.finalize + trans = comps[:a].evaluate events = nil assert_nothing_raised { diff --git a/test/other/relationships.rb b/test/other/relationships.rb index f2764c639..3decfd5af 100755 --- a/test/other/relationships.rb +++ b/test/other/relationships.rb @@ -26,6 +26,8 @@ class TestRelationships < Test::Unit::TestCase file1[:require] = [file2.class.name, file2.name] } + Puppet::Type.finalize + deps = [] assert_nothing_raised { file1.eachdependency { |obj| diff --git a/test/types/component.rb b/test/types/component.rb index b97695f9f..83da95a56 100755 --- a/test/types/component.rb +++ b/test/types/component.rb @@ -22,7 +22,7 @@ class TestComponent < Test::Unit::TestCase looped = 0 loop do looped += 1 - if looped > 1000 + if looped > 2000 raise "Reached limit of looping" break end @@ -89,6 +89,7 @@ class TestComponent < Test::Unit::TestCase comp.push obj } + Puppet::Type.finalize comp end @@ -158,6 +159,7 @@ class TestComponent < Test::Unit::TestCase ) } + Puppet::Type.finalize comp = Puppet.type(:component).create(:name => "RefreshTest") [cmd, file].each { |obj| comp.push obj @@ -202,6 +204,7 @@ class TestComponent < Test::Unit::TestCase ecomp[:subscribe] = [[fcomp.class.name,fcomp.name]] comp = newcomp("bflatten", ecomp, fcomp) + Puppet::Type.finalize objects = nil assert_nothing_raised { objects = comp.flatten @@ -254,6 +257,7 @@ class TestComponent < Test::Unit::TestCase ocmd[:subscribe] = [[cmd.class.name,cmd.name]] comp = newcomp("bflatten", ocomp, ecomp, fcomp) + Puppet::Type.finalize objects = nil assert_nothing_raised { objects = comp.flatten diff --git a/test/types/cron.rb b/test/types/cron.rb index 3ff1dbd18..4bf0ab6b7 100755 --- a/test/types/cron.rb +++ b/test/types/cron.rb @@ -14,11 +14,11 @@ require 'facter' # Here we just want to unit-test our cron type, to verify that -class TestCronType < Test::Unit::TestCase - include TestPuppet - - -end +#class TestCronType < Test::Unit::TestCase +# include TestPuppet +# +# +#end class TestCron < Test::Unit::TestCase include TestPuppet @@ -256,7 +256,7 @@ class TestCron < Test::Unit::TestCase def test_mkcronwithtab Puppet.type(:cron).crontype.remove(@me) Puppet.type(:cron).crontype.write(@me, -"1 1 1 1 * date > %s/crontesting\n" % testdir() +"1 1 1 1 * date > %s/crontesting\n" % tstdir() ) cron = mkcron("testwithtab") diff --git a/test/types/exec.rb b/test/types/exec.rb index 446865774..370fe380f 100755 --- a/test/types/exec.rb +++ b/test/types/exec.rb @@ -243,14 +243,17 @@ class TestExec < Test::Unit::TestCase exec = Puppet.type(:exec).create( :name => oexe, + :path => ENV["PATH"], :cwd => basedir ) cat = Puppet.type(:exec).create( - :name => "cat %s" % oexe, + :name => "cat %s %s" % [exe, oexe], :path => ENV["PATH"] ) + Puppet::Type.finalize + # Verify we get the script itself assert(exec.requires?(file), "Exec did not autorequire file") @@ -261,6 +264,7 @@ class TestExec < Test::Unit::TestCase assert(!exec.requires?(ofile), "Exec incorrectly required file") # Verify that we catch inline files + assert(cat.requires?(ofile), "Exec did not catch second inline file") assert(cat.requires?(file), "Exec did not catch inline file") end diff --git a/test/types/file.rb b/test/types/file.rb index 93332e06a..4aee2a4e9 100644 --- a/test/types/file.rb +++ b/test/types/file.rb @@ -581,6 +581,7 @@ class TestFile < Test::Unit::TestCase :create => "file" ) + Puppet::Type.finalize assert(subobj.requires?(baseobj), "File did not require basedir") assert(!subobj.requires?(subobj), "File required itself") comp = newcomp(subobj, baseobj) diff --git a/test/types/type.rb b/test/types/type.rb index 7a95e2574..fd551c4fd 100644 --- a/test/types/type.rb +++ b/test/types/type.rb @@ -153,6 +153,34 @@ class TestType < Test::Unit::TestCase "Could not retrieve alias") end + + # Verify that requirements don't depend on file order + def test_prereqorder + one = tempfile() + two = tempfile() + + twoobj = nil + oneobj = nil + assert_nothing_raised("Could not create prereq that doesn't exist yet") { + twoobj = Puppet.type(:file).create( + :name => two, + :require => [:file, one] + ) + } + + assert_nothing_raised { + oneobj = Puppet.type(:file).create( + :name => one + ) + } + + assert_nothing_raised { + Puppet::Type.finalize + } + + + assert(twoobj.requires?(oneobj), "Requirement was not created") + end end # $Id$ |