summaryrefslogtreecommitdiffstats
path: root/lib/puppet
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-01-12 05:02:51 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2006-01-12 05:02:51 +0000
commit4c4f530bb5f81ab793e93b5034bddd89f3ec677e (patch)
tree2c7e47caf190914c8941d23c77b9e9f26da0a9d1 /lib/puppet
parent21410a2152d03d8a7f52bebcdf52666e77a0dbfa (diff)
downloadpuppet-4c4f530bb5f81ab793e93b5034bddd89f3ec677e.tar.gz
puppet-4c4f530bb5f81ab793e93b5034bddd89f3ec677e.tar.xz
puppet-4c4f530bb5f81ab793e93b5034bddd89f3ec677e.zip
Fixing dependencies to not depend on file order. Added Puppet::Type.{finalize,mkdepends,builddepends}
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@808 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib/puppet')
-rw-r--r--lib/puppet/client.rb10
-rw-r--r--lib/puppet/type.rb132
-rw-r--r--lib/puppet/type/component.rb6
3 files changed, 129 insertions, 19 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