summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/client.rb10
-rw-r--r--lib/puppet/type.rb132
-rw-r--r--lib/puppet/type/component.rb6
-rwxr-xr-xtest/other/events.rb2
-rwxr-xr-xtest/other/relationships.rb2
-rwxr-xr-xtest/types/component.rb6
-rwxr-xr-xtest/types/cron.rb12
-rwxr-xr-xtest/types/exec.rb6
-rw-r--r--test/types/file.rb1
-rw-r--r--test/types/type.rb28
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$