summaryrefslogtreecommitdiffstats
path: root/lib/puppet
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2007-09-15 22:17:20 -0600
committerLuke Kanies <luke@madstop.com>2007-09-15 22:17:20 -0600
commitf17f19dae941b17a56c1fc83ed3a89712b98c427 (patch)
tree3615e9be9ed585511bbe0b85737208bbd85f00f0 /lib/puppet
parent3ccf483f77b026dde8a53bd8e9dff6a5fd0f6722 (diff)
downloadpuppet-f17f19dae941b17a56c1fc83ed3a89712b98c427.tar.gz
puppet-f17f19dae941b17a56c1fc83ed3a89712b98c427.tar.xz
puppet-f17f19dae941b17a56c1fc83ed3a89712b98c427.zip
The whole system now uses Configuration objects instead of
ever converting the Transportable objects into a tree of components and then converting that into a graph. This is a significant step, and drastically simplifies the model of how to use a configuration. The old code might have looked something like this: file = Puppet::Type.create :path => "/whatever", ... comp = Puppet::Type.create :name => :whatever comp.push file transaction = comp.evaluate transaction.evaluate The new code looks like this: file = Puppet::Type.create :path => "/whatever", ... config = Puppet::Node::Configuration.new config.add_resource file config.apply I did not really intend to do this much refactoring, but I found I could not use a Configuration object to do work without refactoring a lot of the system. The primary problem was that the Client::Master and the Config classes determined how the transactions behaved; when I moved to using a Configuration, this distinction was lost, which meant that configurations were often needing to create other configurations, which resulted in a whole lot of infinite recursion (e.g., Config objects that create directories for Puppet use Configuration objects -- yes, I'm s/Config/Settings/g soon -- and these Configuration objects would need to create directories). Not everything is fixed, but it's very close. I am clearly over the hump, though, so I wanted to get a commit in.
Diffstat (limited to 'lib/puppet')
-rw-r--r--lib/puppet/defaults.rb9
-rw-r--r--lib/puppet/indirector/facts/yaml.rb4
-rw-r--r--lib/puppet/network/client/master.rb174
-rwxr-xr-xlib/puppet/network/handler/fileserver.rb5
-rw-r--r--lib/puppet/node.rb3
-rw-r--r--lib/puppet/node/configuration.rb81
-rw-r--r--lib/puppet/provider/mount.rb2
-rw-r--r--lib/puppet/transaction.rb98
-rw-r--r--lib/puppet/transportable.rb71
-rw-r--r--lib/puppet/type/component.rb1
-rw-r--r--lib/puppet/util/config.rb185
-rw-r--r--lib/puppet/util/storage.rb2
12 files changed, 315 insertions, 320 deletions
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index 4b442d094..cb6e67a7b 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -494,12 +494,11 @@ module Puppet
"The server through which to send email reports."]
)
- self.setdefaults(:facts,
+ # This needs to be in main because it's used too early in the system, such that
+ # we get an infinite loop otherwise.
+ self.setdefaults(:main,
:fact_store => ["yaml",
- "The backend store to use for client facts."]
- )
-
- self.setdefaults(:yamlfacts,
+ "The backend store to use for client facts."],
:yamlfactdir => ["$vardir/facts",
"The directory in which client facts are stored when the yaml fact store is used."]
)
diff --git a/lib/puppet/indirector/facts/yaml.rb b/lib/puppet/indirector/facts/yaml.rb
index f29ea8ebc..55f0d16ee 100644
--- a/lib/puppet/indirector/facts/yaml.rb
+++ b/lib/puppet/indirector/facts/yaml.rb
@@ -16,10 +16,6 @@ Puppet::Indirector.register_terminus :facts, :yaml do
Puppet::Node::Facts.new(node, values)
end
- def initialize
- Puppet.config.use(:yamlfacts)
- end
-
# Store the facts to disk.
def post(facts)
File.open(path(facts.name), "w", 0600) do |f|
diff --git a/lib/puppet/network/client/master.rb b/lib/puppet/network/client/master.rb
index c6d7cd75d..b5824e6bd 100644
--- a/lib/puppet/network/client/master.rb
+++ b/lib/puppet/network/client/master.rb
@@ -7,7 +7,7 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
@@sync = Sync.new
end
- attr_accessor :objects
+ attr_accessor :configuration
attr_reader :compile_time
class << self
@@ -49,50 +49,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
Puppet.config[:dynamicfacts].split(/\s*,\s*/).collect { |fact| fact.downcase }
end
- # This method actually applies the configuration.
- def apply(tags = nil, ignoreschedules = false)
- unless defined? @objects
- raise Puppet::Error, "Cannot apply; objects not defined"
- end
-
- transaction = @objects.evaluate
-
- if tags
- transaction.tags = tags
- end
-
- if ignoreschedules
- transaction.ignoreschedules = true
- end
-
- transaction.addtimes :config_retrieval => @configtime
-
- begin
- transaction.evaluate
- rescue Puppet::Error => detail
- Puppet.err "Could not apply complete configuration: %s" %
- detail
- rescue => detail
- Puppet.err "Got an uncaught exception of type %s: %s" %
- [detail.class, detail]
- if Puppet[:trace]
- puts detail.backtrace
- end
- ensure
- Puppet::Util::Storage.store
- end
-
- if Puppet[:report] or Puppet[:summarize]
- report(transaction)
- end
-
- return transaction
- ensure
- if defined? transaction and transaction
- transaction.cleanup
- end
- end
-
# Cache the config
def cache(text)
Puppet.info "Caching configuration at %s" % self.cachefile
@@ -111,10 +67,10 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
end
def clear
- @objects.remove(true) if @objects
+ @configuration.clear(true) if @configuration
Puppet::Type.allclear
mkdefault_objects
- @objects = nil
+ @configuration = nil
end
# Initialize and load storage
@@ -183,15 +139,15 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
facts = self.class.facts
end
- if self.objects or FileTest.exists?(self.cachefile)
+ if self.configuration or FileTest.exists?(self.cachefile)
if self.fresh?(facts)
Puppet.info "Config is up to date"
- if self.objects
+ if self.configuration
return
end
if oldtext = self.retrievecache
begin
- @objects = YAML.load(oldtext).to_type
+ @configuration = YAML.load(oldtext).to_configuration
rescue => detail
Puppet.warning "Could not load cached configuration: %s" % detail
end
@@ -213,7 +169,7 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
end
unless objects = get_actual_config(facts)
- @objects = nil
+ @configuration = nil
return
end
@@ -225,21 +181,21 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
self.setclasses(objects.classes)
# Clear all existing objects, so we can recreate our stack.
- if self.objects
+ if self.configuration
clear()
end
- # Now convert the objects to real Puppet objects
- @objects = objects.to_type
+ # Now convert the objects to a puppet configuration graph.
+ @configuration = objects.to_configuration
- if @objects.nil?
+ if @configuration.nil?
raise Puppet::Error, "Configuration could not be processed"
end
- # and perform any necessary final actions before we evaluate.
- @objects.finalize
+ # Keep the state database up to date.
+ @configuration.host_config = true
- return @objects
+ return @configuration
end
# A simple proxy method, so it's easy to test.
@@ -252,9 +208,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
Puppet.config.use(:main, :ssl, :puppetd)
super
- # This might be nil
- @configtime = 0
-
self.class.instance = self
@running = false
@@ -297,7 +250,7 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
end
# The code that actually runs the configuration.
- def run(tags = nil, ignoreschedules = false)
+ def run
got_lock = false
splay
Puppet::Util.sync(:puppetrun).synchronize(Sync::EX) do
@@ -307,19 +260,20 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
else
got_lock = true
begin
- @configtime = thinmark do
+ duration = thinmark do
self.getconfig
end
rescue => detail
Puppet.err "Could not retrieve configuration: %s" % detail
end
- if defined? @objects and @objects
+ if defined? @configuration and @configuration
+ @configuration.retrieval_duration = duration
unless @local
Puppet.notice "Starting configuration run"
end
benchmark(:notice, "Finished configuration run") do
- self.apply(tags, ignoreschedules)
+ @configuration.apply
end
end
end
@@ -366,9 +320,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
# Download files from the remote server, returning a list of all
# changed files.
def self.download(args)
- objects = Puppet::Type.type(:component).create(
- :name => "#{args[:name]}_collector"
- )
hash = {
:path => args[:dest],
:recurse => true,
@@ -383,18 +334,23 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
if args[:ignore]
hash[:ignore] = args[:ignore].split(/\s+/)
end
- objects.push Puppet::Type.type(:file).create(hash)
+ downconfig = Puppet::Node::Configuration.new("downloading")
+ downconfig.add_resource Puppet::Type.type(:file).create(hash)
Puppet.info "Retrieving #{args[:name]}s"
noop = Puppet[:noop]
Puppet[:noop] = false
+ files = []
begin
- trans = objects.evaluate
- trans.ignoretags = true
Timeout::timeout(self.timeout) do
- trans.evaluate
+ downconfig.apply do |trans|
+ trans.changed?.find_all do |resource|
+ yield resource if block_given?
+ files << resource[:path]
+ end
+ end
end
rescue Puppet::Error, Timeout::Error => detail
if Puppet[:debug]
@@ -403,18 +359,10 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
Puppet.err "Could not retrieve #{args[:name]}s: %s" % detail
end
- # Now source all of the changed objects, but only source those
- # that are top-level.
- files = []
- trans.changed?.find_all do |object|
- yield object if block_given?
- files << object[:path]
- end
- trans.cleanup
-
# Now clean up after ourselves
- objects.remove
- files
+ downconfig.clear
+
+ return files
ensure
# I can't imagine why this is necessary, but apparently at last one person has had problems with noop
# being nil here.
@@ -427,21 +375,21 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
# Retrieve facts from the central server.
def self.getfacts
- # Clear all existing definitions.
- Facter.clear
# Download the new facts
path = Puppet[:factpath].split(":")
files = []
download(:dest => Puppet[:factdest], :source => Puppet[:factsource],
- :ignore => Puppet[:factsignore], :name => "fact") do |object|
-
- next unless path.include?(::File.dirname(object[:path]))
+ :ignore => Puppet[:factsignore], :name => "fact") do |resource|
- files << object[:path]
+ next unless path.include?(::File.dirname(resource[:path]))
+ files << resource[:path]
end
ensure
+ # Clear all existing definitions.
+ Facter.clear
+
# Reload everything.
if Facter.respond_to? :loadfacts
Facter.loadfacts
@@ -461,20 +409,20 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
# changed plugins, because Puppet::Type loads plugins on demand.
def self.getplugins
download(:dest => Puppet[:plugindest], :source => Puppet[:pluginsource],
- :ignore => Puppet[:pluginsignore], :name => "plugin") do |object|
+ :ignore => Puppet[:pluginsignore], :name => "plugin") do |resource|
- next if FileTest.directory?(object[:path])
- path = object[:path].sub(Puppet[:plugindest], '').sub(/^\/+/, '')
+ next if FileTest.directory?(resource[:path])
+ path = resource[:path].sub(Puppet[:plugindest], '').sub(/^\/+/, '')
unless Puppet::Util::Autoload.loaded?(path)
next
end
begin
Puppet.info "Reloading downloaded file %s" % path
- load object[:path]
+ load resource[:path]
rescue => detail
Puppet.warning "Could not reload downloaded file %s: %s" %
- [object[:path], detail]
+ [resource[:path], detail]
end
end
end
@@ -517,42 +465,6 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
return timeout
end
-
- # Send off the transaction report.
- def report(transaction)
- begin
- report = transaction.generate_report()
- rescue => detail
- Puppet.err "Could not generate report: %s" % detail
- return
- end
-
- if Puppet[:rrdgraph] == true
- report.graph()
- end
-
- if Puppet[:summarize]
- puts report.summary
- end
-
- if Puppet[:report]
- begin
- reportclient().report(report)
- rescue => detail
- Puppet.err "Reporting failed: %s" % detail
- end
- end
- end
-
- def reportclient
- unless defined? @reportclient
- @reportclient = Puppet::Network::Client.report.new(
- :Server => Puppet[:reportserver]
- )
- end
-
- @reportclient
- end
loadfacts()
@@ -633,7 +545,7 @@ class Puppet::Network::Client::Master < Puppet::Network::Client
Puppet.err "Could not retrieve configuration: %s" % detail
unless Puppet[:usecacheonfailure]
- @objects = nil
+ @configuration = nil
Puppet.warning "Not using cache on failed configuration"
return
end
diff --git a/lib/puppet/network/handler/fileserver.rb b/lib/puppet/network/handler/fileserver.rb
index 993e9d51a..022e0c1d4 100755
--- a/lib/puppet/network/handler/fileserver.rb
+++ b/lib/puppet/network/handler/fileserver.rb
@@ -243,7 +243,10 @@ class Puppet::Network::Handler
# the modules.
def modules_mount(module_name, client)
# Find our environment, if we have one.
- if node = Puppet::Node.get(client || Facter.value("hostname"))
+ unless hostname = (client || Facter.value("hostname"))
+ raise ArgumentError, "Could not find hostname"
+ end
+ if node = Puppet::Node.get(hostname)
env = node.environment
else
env = nil
diff --git a/lib/puppet/node.rb b/lib/puppet/node.rb
index 7ad7bc3b3..247cd0521 100644
--- a/lib/puppet/node.rb
+++ b/lib/puppet/node.rb
@@ -38,6 +38,9 @@ class Puppet::Node
end
def initialize(name, options = {})
+ unless name
+ raise ArgumentError, "Node names cannot be nil"
+ end
@name = name
# Provide a default value.
diff --git a/lib/puppet/node/configuration.rb b/lib/puppet/node/configuration.rb
index be30ddb68..8cb6ed1f9 100644
--- a/lib/puppet/node/configuration.rb
+++ b/lib/puppet/node/configuration.rb
@@ -5,9 +5,26 @@ require 'puppet/external/gratr/digraph'
# of the information in the configuration, including the resources
# and the relationships between them.
class Puppet::Node::Configuration < Puppet::PGraph
- attr_accessor :name, :version
+ # The host name this is a configuration for.
+ attr_accessor :name
+
+ # The configuration version. Used for testing whether a configuration
+ # is up to date.
+ attr_accessor :version
+
+ # How long this configuration took to retrieve. Used for reporting stats.
+ attr_accessor :retrieval_duration
+
+ # How we should extract the configuration for sending to the client.
attr_reader :extraction_format
+ # Whether this is a host configuration, which behaves very differently.
+ # In particular, reports are sent, graphs are made, and state is
+ # stored in the state database. If this is set incorrectly, then you often
+ # end up in infinite loops, because configurations are used to make things
+ # that the host configuration needs.
+ attr_accessor :host_config
+
# Add classes to our class list.
def add_class(*classes)
classes.each do |klass|
@@ -30,10 +47,50 @@ class Puppet::Node::Configuration < Puppet::PGraph
else
@resource_table[ref] = resource
end
+ add_vertex!(resource)
+ end
+
+ # Apply our configuration to the local host.
+ def apply
+ Puppet::Util::Storage.load if host_config?
+ transaction = Puppet::Transaction.new(self)
+
+ transaction.addtimes :config_retrieval => @retrieval_duration
+
+ begin
+ transaction.evaluate
+ rescue Puppet::Error => detail
+ Puppet.err "Could not apply complete configuration: %s" % detail
+ rescue => detail
+ if Puppet[:trace]
+ puts detail.backtrace
+ end
+ Puppet.err "Got an uncaught exception of type %s: %s" % [detail.class, detail]
+ ensure
+ # Don't try to store state unless we're a host config
+ # too recursive.
+ Puppet::Util::Storage.store if host_config?
+ end
+
+ if block_given?
+ yield transaction
+ end
+
+ if host_config and (Puppet[:report] or Puppet[:summarize])
+ transaction.send_report
+ end
+
+ return transaction
+ ensure
+ if defined? transaction and transaction
+ transaction.cleanup
+ end
end
- def clear
- super
+ 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
end
@@ -113,13 +170,23 @@ class Puppet::Node::Configuration < Puppet::PGraph
return result
end
- def initialize(name)
+ # Make sure all of our resources are "finished".
+ def finalize
+ @resource_table.values.each { |resource| resource.finish }
+ end
+
+ def initialize(name = nil)
super()
- @name = name
+ @name = name if name
@extraction_format ||= :transportable
@tags = []
@classes = []
@resource_table = {}
+
+ if block_given?
+ yield(self)
+ finalize()
+ end
end
# Look a resource up by its reference (e.g., File[/etc/passwd]).
@@ -127,6 +194,10 @@ class Puppet::Node::Configuration < Puppet::PGraph
@resource_table[ref]
end
+ def host_config?
+ host_config || false
+ end
+
# Add a tag.
def tag(*names)
names.each do |name|
diff --git a/lib/puppet/provider/mount.rb b/lib/puppet/provider/mount.rb
index 446ed641c..6a05d9826 100644
--- a/lib/puppet/provider/mount.rb
+++ b/lib/puppet/provider/mount.rb
@@ -50,5 +50,3 @@ module Puppet::Provider::Mount
end
end
end
-
-# $Id$
diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb
index 46bac3058..0d81b1e63 100644
--- a/lib/puppet/transaction.rb
+++ b/lib/puppet/transaction.rb
@@ -6,10 +6,14 @@ require 'puppet/propertychange'
module Puppet
class Transaction
- attr_accessor :component, :resources, :ignoreschedules, :ignoretags
+ attr_accessor :component, :configuration, :ignoreschedules
attr_accessor :relgraph, :sorted_resources, :configurator
+ # The report, once generated.
attr_reader :report
+
+ # The list of events generated in this transaction.
+ attr_reader :events
attr_writer :tags
@@ -129,6 +133,9 @@ class Transaction
# Find all of the changed resources.
def changed?
@changes.find_all { |change| change.changed }.collect { |change|
+ unless change.property.resource
+ raise "No resource for %s" % change.inspect
+ end
change.property.resource
}.uniq
end
@@ -144,7 +151,6 @@ class Transaction
if defined? @relgraph
@relgraph.clear
end
- @resources.clear
end
# Copy an important relationships from the parent to the newly-generated
@@ -283,7 +289,7 @@ class Transaction
def evaluate
@count = 0
- graph(@resources, :resources)
+ graph(@configuration, :resources)
# Start logging.
Puppet::Util::Log.newdestination(@report)
@@ -347,7 +353,7 @@ class Transaction
# Collect any dynamically generated resources.
def generate
- list = @resources.vertices
+ list = @configuration.vertices
# Store a list of all generated resources, so that we can clean them up
# after the transaction closes.
@@ -369,7 +375,7 @@ class Transaction
end
made.uniq!
made.each do |res|
- @resources.add_vertex!(res)
+ @configuration.add_vertex!(res)
newlist << res
@generated << res
res.finish
@@ -412,8 +418,8 @@ class Transaction
# Produce the graph files if requested.
def graph(gr, name)
- # We don't want to graph the configuration process.
- return if self.configurator
+ # We only want to graph the main host configuration.
+ return unless @configuration.host_config?
return unless Puppet[:graph]
@@ -425,17 +431,24 @@ class Transaction
}
end
+ # Should we ignore tags?
+ def ignore_tags?
+ ! @configuration.host_config?
+ end
+
# this should only be called by a Puppet::Type::Component resource now
# and it should only receive an array
def initialize(resources)
- if resources.is_a?(Puppet::PGraph)
- @resources = resources
+ if resources.is_a?(Puppet::Node::Configuration)
+ @configuration = resources
+ elsif resources.is_a?(Puppet::PGraph)
+ raise "Transactions should get configurations now, not PGraph"
else
- @resources = resources.to_graph
+ raise "Transactions require configurations"
end
@resourcemetrics = {
- :total => @resources.vertices.length,
+ :total => @configuration.vertices.length,
:out_of_sync => 0, # The number of resources that had changes
:applied => 0, # The number of resources fixed
:skipped => 0, # The number of resources skipped
@@ -474,7 +487,7 @@ class Transaction
# types, just providers.
def prefetch
prefetchers = {}
- @resources.each do |resource|
+ @configuration.each do |resource|
if provider = resource.provider and provider.class.respond_to?(:prefetch)
prefetchers[provider.class] ||= {}
prefetchers[provider.class][resource.title] = resource
@@ -514,7 +527,7 @@ class Transaction
graph = Puppet::PGraph.new
# First create the dependency graph
- @resources.vertices.each do |vertex|
+ @configuration.vertices.each do |vertex|
graph.add_vertex!(vertex)
vertex.builddepends.each do |edge|
graph.add_edge!(edge)
@@ -538,12 +551,48 @@ class Transaction
graph(graph, :relationships)
# Then splice in the container information
- graph.splice!(@resources, Puppet::Type::Component)
+ graph.splice!(@configuration, Puppet::Type::Component)
graph(graph, :expanded_relationships)
return graph
end
+
+ # Send off the transaction report.
+ def send_report
+ begin
+ report = generate_report()
+ rescue => detail
+ Puppet.err "Could not generate report: %s" % detail
+ return
+ end
+
+ if Puppet[:rrdgraph] == true
+ report.graph()
+ end
+
+ if Puppet[:summarize]
+ puts report.summary
+ end
+
+ if Puppet[:report]
+ begin
+ reportclient().report(report)
+ rescue => detail
+ Puppet.err "Reporting failed: %s" % detail
+ end
+ end
+ end
+
+ def reportclient
+ unless defined? @reportclient
+ @reportclient = Puppet::Network::Client.report.new(
+ :Server => Puppet[:reportserver]
+ )
+ end
+
+ @reportclient
+ end
# Roll all completed changes back.
def rollback
@@ -606,7 +655,7 @@ class Transaction
# Should this resource be skipped?
def skip?(resource)
skip = false
- if ! tagged?(resource)
+ if missing_tags?(resource)
resource.debug "Not tagged with %s" % tags.join(", ")
elsif ! scheduled?(resource)
resource.debug "Not scheduled"
@@ -620,29 +669,22 @@ class Transaction
# The tags we should be checking.
def tags
- # Allow the tags to be overridden
unless defined? @tags
- @tags = Puppet[:tags]
- end
-
- unless defined? @processed_tags
- if @tags.nil? or @tags == ""
+ tags = Puppet[:tags]
+ if tags.nil? or tags == ""
@tags = []
else
- @tags = [@tags] unless @tags.is_a? Array
- @tags = @tags.collect do |tag|
- tag.split(/\s*,\s*/)
- end.flatten
+ @tags = tags.split(/\s*,\s*/)
end
- @processed_tags = true
end
@tags
end
# Is this resource tagged appropriately?
- def tagged?(resource)
- self.ignoretags or tags.empty? or resource.tagged?(tags)
+ def missing_tags?(resource)
+ return false if self.ignore_tags? or tags.empty?
+ return true unless resource.tagged?(tags)
end
# Are there any edges that target this resource?
diff --git a/lib/puppet/transportable.rb b/lib/puppet/transportable.rb
index 782ba2467..e4cde6e37 100644
--- a/lib/puppet/transportable.rb
+++ b/lib/puppet/transportable.rb
@@ -71,7 +71,7 @@ module Puppet
@ref
end
- def to_type(parent = nil)
+ def to_type
retobj = nil
if typeklass = Puppet::Type.type(self.type)
# FIXME This should really be done differently, but...
@@ -88,10 +88,6 @@ module Puppet
raise Puppet::Error.new("Could not find object type %s" % self.type)
end
- if parent
- parent.push retobj
- end
-
return retobj
end
end
@@ -200,29 +196,29 @@ module Puppet
end
# Create a resource graph from our structure.
- def to_graph
- graph = Puppet::Node::Configuration.new(Facter.value(:hostname))
-
- delver = proc do |obj|
- obj.each do |child|
- unless container = graph.resource(obj.to_ref)
+ def to_configuration
+ configuration = Puppet::Node::Configuration.new(Facter.value("hostname")) do |config|
+ delver = proc do |obj|
+ unless container = config.resource(obj.to_ref)
container = obj.to_type
- graph.add_resource container
- end
- unless resource = graph.resource(child.to_ref)
- resource = child.to_type
- graph.add_resource resource
+ config.add_resource container
end
- graph.add_edge!(container, resource)
- if child.is_a?(self.class)
- delver.call(child)
+ obj.each do |child|
+ unless resource = config.resource(child.to_ref)
+ next unless resource = child.to_type
+ config.add_resource resource
+ end
+ config.add_edge!(container, resource)
+ if child.is_a?(self.class)
+ delver.call(child)
+ end
end
end
+
+ delver.call(self)
end
- delver.call(self)
-
- return graph
+ return configuration
end
def to_ref
@@ -236,7 +232,7 @@ module Puppet
@ref
end
- def to_type(parent = nil)
+ def to_type
# this container will contain the equivalent of all objects at
# this level
#container = Puppet::Component.new(:name => @name, :type => @type)
@@ -283,45 +279,16 @@ module Puppet
#Puppet.debug "%s[%s] has no parameters" % [@type, @name]
end
- #if parent
- # hash[:parent] = parent
- #end
container = Puppet::Type::Component.create(hash)
end
#Puppet.info container.inspect
- if parent
- parent.push container
- end
-
# unless we successfully created the container, return an error
unless container
Puppet.warning "Got no container back"
return nil
end
- self.each { |child|
- # the fact that we descend here means that we are
- # always going to execute depth-first
- # which is _probably_ a good thing, but one never knows...
- unless child.is_a?(Puppet::TransBucket) or
- child.is_a?(Puppet::TransObject)
- raise Puppet::DevError,
- "TransBucket#to_type cannot handle objects of type %s" %
- child.class
- end
-
- # Now just call to_type on them with the container as a parent
- begin
- child.to_type(container)
- rescue => detail
- if Puppet[:trace] and ! detail.is_a?(Puppet::Error)
- puts detail.backtrace
- end
- Puppet.err detail.to_s
- end
- }
-
# at this point, no objects at are level are still Transportable
# objects
return container
diff --git a/lib/puppet/type/component.rb b/lib/puppet/type/component.rb
index 79afa95a7..1615abad8 100644
--- a/lib/puppet/type/component.rb
+++ b/lib/puppet/type/component.rb
@@ -52,6 +52,7 @@ Puppet::Type.newtype(:component) do
# this is only called on one component over the whole system
# this also won't work with scheduling, but eh
def evaluate
+ raise "Component#evaluate is deprecated"
self.finalize unless self.finalized?
transaction = Puppet::Transaction.new(self)
transaction.component = self
diff --git a/lib/puppet/util/config.rb b/lib/puppet/util/config.rb
index 9cdb4cfe3..5875f141b 100644
--- a/lib/puppet/util/config.rb
+++ b/lib/puppet/util/config.rb
@@ -69,14 +69,14 @@ class Puppet::Util::Config
return options
end
- # Turn the config into a transaction and apply it
+ # Turn the config into a Puppet configuration and apply it
def apply
trans = self.to_transportable
begin
- comp = trans.to_type
- trans = comp.evaluate
- trans.evaluate
- comp.remove
+ config = trans.to_configuration
+ config.store_state = false
+ config.apply
+ config.clear
rescue => detail
if Puppet[:trace]
puts detail.backtrace
@@ -476,57 +476,15 @@ class Puppet::Util::Config
end
# Convert a single section into transportable objects.
- def section_to_transportable(section, done = nil, includefiles = true)
+ def section_to_transportable(section, done = nil)
done ||= Hash.new { |hash, key| hash[key] = {} }
objects = []
persection(section) do |obj|
if @config[:mkusers] and value(:mkusers)
- [:owner, :group].each do |attr|
- type = nil
- if attr == :owner
- type = :user
- else
- type = attr
- end
- # If a user and/or group is set, then make sure we're
- # managing that object
- if obj.respond_to? attr and name = obj.send(attr)
- # Skip root or wheel
- next if %w{root wheel}.include?(name.to_s)
-
- # Skip owners and groups we've already done, but tag
- # them with our section if necessary
- if done[type].include?(name)
- tags = done[type][name].tags
- unless tags.include?(section)
- done[type][name].tags = tags << section
- end
- elsif newobj = Puppet::Type.type(type)[name]
- unless newobj.property(:ensure)
- newobj[:ensure] = "present"
- end
- newobj.tag(section)
- if type == :user
- newobj[:comment] ||= "%s user" % name
- end
- else
- newobj = Puppet::TransObject.new(name, type.to_s)
- newobj.tags = ["puppet", "configuration", section]
- newobj[:ensure] = "present"
- if type == :user
- newobj[:comment] ||= "%s user" % name
- end
- # Set the group appropriately for the user
- if type == :user
- newobj[:gid] = Puppet[:group]
- end
- done[type][name] = newobj
- objects << newobj
- end
- end
- end
+ objects += add_user_resources(section, obj, done)
end
+ # Only files are convertable to transportable resources.
if obj.respond_to? :to_transportable
next if value(obj.name) =~ /^\/dev/
transobjects = obj.to_transportable
@@ -544,7 +502,8 @@ class Puppet::Util::Config
end
bucket = Puppet::TransBucket.new
- bucket.type = section
+ bucket.type = "Configuration"
+ bucket.name = section
bucket.push(*objects)
bucket.keyword = "class"
@@ -634,7 +593,7 @@ Generated on #{Time.now}.
end
# Convert our configuration into a list of transportable objects.
- def to_transportable
+ def to_transportable(*sections)
done = Hash.new { |hash, key|
hash[key] = {}
}
@@ -643,14 +602,23 @@ Generated on #{Time.now}.
if defined? @file.file and @file.file
topbucket.name = @file.file
else
- topbucket.name = "configtop"
+ topbucket.name = "top"
end
- topbucket.type = "puppetconfig"
+ topbucket.type = "Configuration"
topbucket.top = true
# Now iterate over each section
- eachsection do |section|
- topbucket.push section_to_transportable(section, done)
+ if sections.empty?
+ eachsection do |section|
+ sections << section
+ end
+ end
+ sections.each do |section|
+ obj = section_to_transportable(section, done)
+ #puts obj.to_manifest
+ #puts "%s: %s" % [section, obj.inspect]
+ topbucket.push obj
+ #topbucket.push section_to_transportable(section, done)
end
topbucket
@@ -683,37 +651,31 @@ Generated on #{Time.now}.
}
return if runners.empty?
- bucket = Puppet::TransBucket.new
- bucket.type = "puppetconfig"
- bucket.top = true
-
- # Create a hash to keep track of what we've done so far.
- @done = Hash.new { |hash, key| hash[key] = {} }
- runners.each do |section|
- bucket.push section_to_transportable(section, @done, false)
- end
-
- objects = bucket.to_type
-
- objects.finalize
- tags = nil
- if Puppet[:tags]
- tags = Puppet[:tags]
- Puppet[:tags] = ""
- end
- trans = objects.evaluate
- trans.ignoretags = true
- trans.configurator = true
- trans.evaluate
- if tags
- Puppet[:tags] = tags
- end
-
- # Remove is a recursive process, so it's sufficient to just call
- # it on the component.
- objects.remove(true)
-
- objects = nil
+ bucket = to_transportable(*sections)
+
+ config = bucket.to_configuration
+ config.host_config = false
+ config.apply
+ config.clear
+
+# tags = nil
+# if Puppet[:tags]
+# tags = Puppet[:tags]
+# Puppet[:tags] = ""
+# end
+# trans = objects.evaluate
+# trans.ignoretags = true
+# trans.configurator = true
+# trans.evaluate
+# if tags
+# Puppet[:tags] = tags
+# end
+#
+# # Remove is a recursive process, so it's sufficient to just call
+# # it on the component.
+# objects.remove(true)
+#
+# objects = nil
runners.each { |s| @used << s }
end
@@ -845,6 +807,48 @@ Generated on #{Time.now}.
private
+ # Create the transportable objects for users and groups.
+ def add_user_resources(section, obj, done)
+ resources = []
+ [:owner, :group].each do |attr|
+ type = nil
+ if attr == :owner
+ type = :user
+ else
+ type = attr
+ end
+ # If a user and/or group is set, then make sure we're
+ # managing that object
+ if obj.respond_to? attr and name = obj.send(attr)
+ # Skip root or wheel
+ next if %w{root wheel}.include?(name.to_s)
+
+ # Skip owners and groups we've already done, but tag
+ # them with our section if necessary
+ if done[type].include?(name)
+ tags = done[type][name].tags
+ unless tags.include?(section)
+ done[type][name].tags = tags << section
+ end
+ else
+ newobj = Puppet::TransObject.new(name, type.to_s)
+ newobj.tags = ["puppet", "configuration", section]
+ newobj[:ensure] = :present
+ if type == :user
+ newobj[:comment] ||= "%s user" % name
+ end
+ # Set the group appropriately for the user
+ if type == :user
+ newobj[:gid] = Puppet[:group]
+ end
+ done[type][name] = newobj
+ resources << newobj
+ end
+ end
+ end
+ resources
+ end
+
# Extract extra setting information for files.
def extract_fileinfo(string)
result = {}
@@ -1141,6 +1145,9 @@ Generated on #{Time.now}.
unless path =~ /^#{File::SEPARATOR}/
path = File.join(Dir.getwd, path)
end
+
+ # Skip plain files that don't exist, since we won't be managing them anyway.
+ return nil unless self.name.to_s =~ /dir$/ or File.exist?(path)
obj = Puppet::TransObject.new(path, "file")
# Only create directories, or files that are specifically marked to
@@ -1157,7 +1164,7 @@ Generated on #{Time.now}.
}
# Only chown or chgrp when root
- if Puppet::Util::SUIDManager.uid == 0
+ if Puppet.features.root?
[:group, :owner].each { |var|
if value = self.send(var)
obj[var] = value
@@ -1218,5 +1225,3 @@ Generated on #{Time.now}.
end
end
end
-
-# $Id$
diff --git a/lib/puppet/util/storage.rb b/lib/puppet/util/storage.rb
index a10183615..cd41aa572 100644
--- a/lib/puppet/util/storage.rb
+++ b/lib/puppet/util/storage.rb
@@ -99,5 +99,3 @@ class Puppet::Util::Storage
end
end
end
-
-# $Id$