summaryrefslogtreecommitdiffstats
path: root/lib/puppet/node
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet/node')
-rw-r--r--lib/puppet/node/configuration.rb164
1 files changed, 147 insertions, 17 deletions
diff --git a/lib/puppet/node/configuration.rb b/lib/puppet/node/configuration.rb
index 9cd23926e..c882e0ee1 100644
--- a/lib/puppet/node/configuration.rb
+++ b/lib/puppet/node/configuration.rb
@@ -35,20 +35,22 @@ class Puppet::Node::Configuration < Puppet::PGraph
tag(*classes)
end
- # Add a resource to our graph and to our resource table.
- def add_resource(resource)
- unless resource.respond_to?(:ref)
- raise ArgumentError, "Can only add objects that respond to :ref"
- end
+ # Add one or more resources to our graph and to our resource table.
+ def add_resource(*resources)
+ resources.each do |resource|
+ unless resource.respond_to?(:ref)
+ raise ArgumentError, "Can only add objects that respond to :ref"
+ end
- ref = resource.ref
- if @resource_table.include?(ref)
- raise ArgumentError, "Resource %s is already defined" % ref
- else
- @resource_table[ref] = resource
+ ref = resource.ref
+ if @resource_table.include?(ref)
+ raise ArgumentError, "Resource %s is already defined" % ref
+ else
+ @resource_table[ref] = resource
+ end
+ resource.configuration = self
+ add_vertex!(resource)
end
- resource.configuration = self
- add_vertex!(resource)
end
# Apply our configuration to the local host.
@@ -58,6 +60,8 @@ class Puppet::Node::Configuration < Puppet::PGraph
transaction.addtimes :config_retrieval => @retrieval_duration
+ @applying = true
+
begin
transaction.evaluate
rescue Puppet::Error => detail
@@ -83,22 +87,62 @@ class Puppet::Node::Configuration < Puppet::PGraph
return transaction
ensure
+ @applying = false
+ cleanup()
if defined? transaction and transaction
transaction.cleanup
end
end
+
+ # Are we in the middle of applying the configuration?
+ def applying?
+ @applying
+ end
def clear(remove_resources = true)
super()
# We have to do this so that the resources clean themselves up.
@resource_table.values.each { |resource| resource.remove } if remove_resources
@resource_table.clear
+
+ if defined?(@relationship_graph) and @relationship_graph
+ @relationship_graph.clear(false)
+ @relationship_graph = nil
+ end
end
def classes
@classes.dup
end
+ # Create an implicit resource, meaning that it will lose out
+ # to any explicitly defined resources. This method often returns
+ # nil.
+ def create_implicit_resource(type, options)
+ unless options.include?(:implicit)
+ options[:implicit] = true
+ end
+ if resource = create_resource(type, options)
+ resource.implicit = true
+
+ return resource
+ else
+ return nil
+ end
+ end
+
+ # Create a new resource and register it in the configuration.
+ def create_resource(type, options)
+ unless klass = Puppet::Type.type(type)
+ raise ArgumentError, "Unknown resource type %s" % type
+ end
+ return unless resource = klass.create(options)
+
+ @transient_resources << resource if applying?
+ add_resource(resource)
+ resource
+ end
+
# Make sure we support the requested extraction format.
def extraction_format=(value)
unless respond_to?("extract_to_%s" % value)
@@ -174,6 +218,12 @@ class Puppet::Node::Configuration < Puppet::PGraph
# Make sure all of our resources are "finished".
def finalize
@resource_table.values.each { |resource| resource.finish }
+
+ write_graph(:resources)
+ end
+
+ def host_config?
+ host_config || false
end
def initialize(name = nil)
@@ -183,20 +233,76 @@ class Puppet::Node::Configuration < Puppet::PGraph
@tags = []
@classes = []
@resource_table = {}
+ @transient_resources = []
+ @applying = false
if block_given?
yield(self)
finalize()
end
end
+
+ # Create a graph of all of the relationships in our configuration.
+ def relationship_graph
+ unless defined? @relationship_graph and @relationship_graph
+ relationships = self.class.new
+
+ # First create the dependency graph
+ self.vertices.each do |vertex|
+ relationships.add_resource vertex
+ vertex.builddepends.each do |edge|
+ relationships.add_edge!(edge)
+ end
+ end
+
+ # Lastly, add in any autorequires
+ relationships.vertices.each do |vertex|
+ vertex.autorequire.each do |edge|
+ unless relationships.edge?(edge)
+ unless relationships.edge?(edge.target, edge.source)
+ vertex.debug "Autorequiring %s" % [edge.source]
+ relationships.add_edge!(edge)
+ else
+ vertex.debug "Skipping automatic relationship with %s" % (edge.source == vertex ? edge.target : edge.source)
+ end
+ end
+ end
+ end
+
+ relationships.write_graph(:relationships)
+
+ # Then splice in the container information
+ relationships.splice!(self, Puppet::Type::Component)
+
+ relationships.write_graph(:expanded_relationships)
+ @relationship_graph = relationships
+ end
+ @relationship_graph
+ end
- # Look a resource up by its reference (e.g., File[/etc/passwd]).
- def resource(ref)
- @resource_table[ref]
+ # Remove the resource from our configuration. Notice that we also call
+ # 'remove' on the resource, at least until resource classes no longer maintain
+ # references to the resource instances.
+ def remove_resource(*resources)
+ resources.each do |resource|
+ @resource_table.delete(resource.ref) if @resource_table.include?(resource.ref)
+ remove_vertex!(resource) if vertex?(resource)
+ resource.remove
+ end
end
- def host_config?
- host_config || false
+ # Look a resource up by its reference (e.g., File[/etc/passwd]).
+ def resource(type, title = nil)
+ if title
+ ref = "%s[%s]" % [type.to_s.capitalize, title]
+ else
+ ref = type
+ end
+ if resource = @resource_table[ref]
+ return resource
+ elsif defined?(@relationship_graph) and @relationship_graph
+ @relationship_graph.resource(ref)
+ end
end
# Add a tag.
@@ -217,4 +323,28 @@ class Puppet::Node::Configuration < Puppet::PGraph
def tags
@tags.dup
end
+
+ # Produce the graph files if requested.
+ def write_graph(name)
+ # We only want to graph the main host configuration.
+ return unless host_config?
+
+ return unless Puppet[:graph]
+
+ Puppet.config.use(:graphing)
+
+ file = File.join(Puppet[:graphdir], "%s.dot" % name.to_s)
+ File.open(file, "w") { |f|
+ f.puts to_dot("name" => name.to_s.capitalize)
+ }
+ end
+
+ private
+
+ def cleanup
+ unless @transient_resources.empty?
+ remove_resource(*@transient_resources)
+ @transient_resources.clear
+ end
+ end
end