summaryrefslogtreecommitdiffstats
path: root/lib/puppet/network/handler
diff options
context:
space:
mode:
authorMarkus Roberts <Markus@reality.com>2010-07-09 18:12:17 -0700
committerMarkus Roberts <Markus@reality.com>2010-07-09 18:12:17 -0700
commit3180b9d9b2c844dade1d361326600f7001ec66dd (patch)
tree98fe7c5ac7eb942aac9c39f019a17b0b3f5a57f4 /lib/puppet/network/handler
parent543225970225de5697734bfaf0a6eee996802c04 (diff)
downloadpuppet-3180b9d9b2c844dade1d361326600f7001ec66dd.tar.gz
puppet-3180b9d9b2c844dade1d361326600f7001ec66dd.tar.xz
puppet-3180b9d9b2c844dade1d361326600f7001ec66dd.zip
Code smell: Two space indentation
Replaced 106806 occurances of ^( +)(.*$) with The ruby community almost universally (i.e. everyone but Luke, Markus, and the other eleven people who learned ruby in the 1900s) uses two-space indentation. 3 Examples: The code: end # Tell getopt which arguments are valid def test_get_getopt_args element = Setting.new :name => "foo", :desc => "anything", :settings => Puppet::Util::Settings.new assert_equal([["--foo", GetoptLong::REQUIRED_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args") becomes: end # Tell getopt which arguments are valid def test_get_getopt_args element = Setting.new :name => "foo", :desc => "anything", :settings => Puppet::Util::Settings.new assert_equal([["--foo", GetoptLong::REQUIRED_ARGUMENT]], element.getopt_args, "Did not produce appropriate getopt args") The code: assert_equal(str, val) assert_instance_of(Float, result) end # Now test it with a passed object becomes: assert_equal(str, val) assert_instance_of(Float, result) end # Now test it with a passed object The code: end assert_nothing_raised do klass[:Yay] = "boo" klass["Cool"] = :yayness end becomes: end assert_nothing_raised do klass[:Yay] = "boo" klass["Cool"] = :yayness end
Diffstat (limited to 'lib/puppet/network/handler')
-rw-r--r--lib/puppet/network/handler/ca.rb258
-rwxr-xr-xlib/puppet/network/handler/filebucket.rb86
-rwxr-xr-xlib/puppet/network/handler/fileserver.rb1250
-rw-r--r--lib/puppet/network/handler/master.rb126
-rwxr-xr-xlib/puppet/network/handler/report.rb120
-rwxr-xr-xlib/puppet/network/handler/runner.rb38
-rw-r--r--lib/puppet/network/handler/status.rb18
7 files changed, 948 insertions, 948 deletions
diff --git a/lib/puppet/network/handler/ca.rb b/lib/puppet/network/handler/ca.rb
index 101cf6f8e..ebb6fc427 100644
--- a/lib/puppet/network/handler/ca.rb
+++ b/lib/puppet/network/handler/ca.rb
@@ -7,145 +7,145 @@ require 'xmlrpc/server'
# http://segment7.net/projects/ruby/QuickCert/
class Puppet::Network::Handler
- class CA < Handler
- attr_reader :ca
-
- desc "Provides an interface for signing CSRs. Accepts a CSR and returns
- the CA certificate and the signed certificate, or returns nil if
- the cert is not signed."
+ class CA < Handler
+ attr_reader :ca
+
+ desc "Provides an interface for signing CSRs. Accepts a CSR and returns
+ the CA certificate and the signed certificate, or returns nil if
+ the cert is not signed."
+
+ @interface = XMLRPC::Service::Interface.new("puppetca") { |iface|
+ iface.add_method("array getcert(csr)")
+ }
+
+ def autosign
+ if defined?(@autosign)
+ @autosign
+ else
+ Puppet[:autosign]
+ end
+ end
- @interface = XMLRPC::Service::Interface.new("puppetca") { |iface|
- iface.add_method("array getcert(csr)")
+ # FIXME autosign? should probably accept both hostnames and IP addresses
+ def autosign?(hostname)
+ # simple values are easy
+ if autosign == true or autosign == false
+ return autosign
+ end
+
+ # we only otherwise know how to handle files
+ unless autosign =~ /^\//
+ raise Puppet::Error, "Invalid autosign value #{autosign.inspect}"
+ end
+
+ unless FileTest.exists?(autosign)
+ unless defined?(@@warnedonautosign)
+ @@warnedonautosign = true
+ Puppet.info "Autosign is enabled but #{autosign} is missing"
+ end
+ return false
+ end
+ auth = Puppet::Network::AuthStore.new
+ File.open(autosign) { |f|
+ f.each { |line|
+ next if line =~ /^\s*#/
+ next if line =~ /^\s*$/
+ auth.allow(line.chomp)
}
+ }
- def autosign
- if defined?(@autosign)
- @autosign
- else
- Puppet[:autosign]
- end
- end
+ # for now, just cheat and pass a fake IP address to allowed?
+ auth.allowed?(hostname, "127.1.1.1")
+ end
- # FIXME autosign? should probably accept both hostnames and IP addresses
- def autosign?(hostname)
- # simple values are easy
- if autosign == true or autosign == false
- return autosign
- end
-
- # we only otherwise know how to handle files
- unless autosign =~ /^\//
- raise Puppet::Error, "Invalid autosign value #{autosign.inspect}"
- end
-
- unless FileTest.exists?(autosign)
- unless defined?(@@warnedonautosign)
- @@warnedonautosign = true
- Puppet.info "Autosign is enabled but #{autosign} is missing"
- end
- return false
- end
- auth = Puppet::Network::AuthStore.new
- File.open(autosign) { |f|
- f.each { |line|
- next if line =~ /^\s*#/
- next if line =~ /^\s*$/
- auth.allow(line.chomp)
- }
- }
-
- # for now, just cheat and pass a fake IP address to allowed?
- auth.allowed?(hostname, "127.1.1.1")
- end
+ def initialize(hash = {})
+ Puppet.settings.use(:main, :ssl, :ca)
+ @autosign = hash[:autosign] if hash.include? :autosign
- def initialize(hash = {})
- Puppet.settings.use(:main, :ssl, :ca)
- @autosign = hash[:autosign] if hash.include? :autosign
+ @ca = Puppet::SSLCertificates::CA.new(hash)
+ end
- @ca = Puppet::SSLCertificates::CA.new(hash)
- end
+ # our client sends us a csr, and we either store it for later signing,
+ # or we sign it right away
+ def getcert(csrtext, client = nil, clientip = nil)
+ csr = OpenSSL::X509::Request.new(csrtext)
+
+ # Use the hostname from the CSR, not from the network.
+ subject = csr.subject
+
+ nameary = subject.to_a.find { |ary|
+ ary[0] == "CN"
+ }
- # our client sends us a csr, and we either store it for later signing,
- # or we sign it right away
- def getcert(csrtext, client = nil, clientip = nil)
- csr = OpenSSL::X509::Request.new(csrtext)
-
- # Use the hostname from the CSR, not from the network.
- subject = csr.subject
-
- nameary = subject.to_a.find { |ary|
- ary[0] == "CN"
- }
-
- if nameary.nil?
- Puppet.err(
- "Invalid certificate request: could not retrieve server name"
- )
- return "invalid"
- end
-
- hostname = nameary[1]
-
- unless @ca
- Puppet.notice "Host #{hostname} asked for signing from non-CA master"
- return ""
- end
-
- # We used to save the public key, but it's basically unnecessary
- # and it mucks with the permissions requirements.
- # save_pk(hostname, csr.public_key)
-
- certfile = File.join(Puppet[:certdir], [hostname, "pem"].join("."))
-
- # first check to see if we already have a signed cert for the host
- cert, cacert = ca.getclientcert(hostname)
- if cert and cacert
- Puppet.info "Retrieving existing certificate for #{hostname}"
- unless csr.public_key.to_s == cert.public_key.to_s
- raise Puppet::Error, "Certificate request does not match existing certificate; run 'puppetca --clean #{hostname}'."
- end
- return [cert.to_pem, cacert.to_pem]
- elsif @ca
- if self.autosign?(hostname) or client.nil?
- Puppet.info "Signing certificate for CA server" if client.nil?
- # okay, we don't have a signed cert
- # if we're a CA and autosign is turned on, then go ahead and sign
- # the csr and return the results
- Puppet.info "Signing certificate for #{hostname}"
- cert, cacert = @ca.sign(csr)
- #Puppet.info "Cert: #{cert.class}; Cacert: #{cacert.class}"
- return [cert.to_pem, cacert.to_pem]
- else # just write out the csr for later signing
- if @ca.getclientcsr(hostname)
- Puppet.info "Not replacing existing request from #{hostname}"
- else
- Puppet.notice "Host #{hostname} has a waiting certificate request"
- @ca.storeclientcsr(csr)
- end
- return ["", ""]
- end
- else
- raise "huh?"
- end
+ if nameary.nil?
+ Puppet.err(
+ "Invalid certificate request: could not retrieve server name"
+ )
+ return "invalid"
+ end
+
+ hostname = nameary[1]
+
+ unless @ca
+ Puppet.notice "Host #{hostname} asked for signing from non-CA master"
+ return ""
+ end
+
+ # We used to save the public key, but it's basically unnecessary
+ # and it mucks with the permissions requirements.
+ # save_pk(hostname, csr.public_key)
+
+ certfile = File.join(Puppet[:certdir], [hostname, "pem"].join("."))
+
+ # first check to see if we already have a signed cert for the host
+ cert, cacert = ca.getclientcert(hostname)
+ if cert and cacert
+ Puppet.info "Retrieving existing certificate for #{hostname}"
+ unless csr.public_key.to_s == cert.public_key.to_s
+ raise Puppet::Error, "Certificate request does not match existing certificate; run 'puppetca --clean #{hostname}'."
end
+ return [cert.to_pem, cacert.to_pem]
+ elsif @ca
+ if self.autosign?(hostname) or client.nil?
+ Puppet.info "Signing certificate for CA server" if client.nil?
+ # okay, we don't have a signed cert
+ # if we're a CA and autosign is turned on, then go ahead and sign
+ # the csr and return the results
+ Puppet.info "Signing certificate for #{hostname}"
+ cert, cacert = @ca.sign(csr)
+ #Puppet.info "Cert: #{cert.class}; Cacert: #{cacert.class}"
+ return [cert.to_pem, cacert.to_pem]
+ else # just write out the csr for later signing
+ if @ca.getclientcsr(hostname)
+ Puppet.info "Not replacing existing request from #{hostname}"
+ else
+ Puppet.notice "Host #{hostname} has a waiting certificate request"
+ @ca.storeclientcsr(csr)
+ end
+ return ["", ""]
+ end
+ else
+ raise "huh?"
+ end
+ end
+
+ private
- private
-
- # Save the public key.
- def save_pk(hostname, public_key)
- pkeyfile = File.join(Puppet[:publickeydir], [hostname, "pem"].join('.'))
-
- if FileTest.exists?(pkeyfile)
- currentkey = File.open(pkeyfile) { |k| k.read }
- unless currentkey == public_key.to_s
- raise Puppet::Error, "public keys for #{hostname} differ"
- end
- else
- File.open(pkeyfile, "w", 0644) { |f|
- f.print public_key.to_s
- }
- end
+ # Save the public key.
+ def save_pk(hostname, public_key)
+ pkeyfile = File.join(Puppet[:publickeydir], [hostname, "pem"].join('.'))
+
+ if FileTest.exists?(pkeyfile)
+ currentkey = File.open(pkeyfile) { |k| k.read }
+ unless currentkey == public_key.to_s
+ raise Puppet::Error, "public keys for #{hostname} differ"
end
+ else
+ File.open(pkeyfile, "w", 0644) { |f|
+ f.print public_key.to_s
+ }
+ end
end
+ end
end
diff --git a/lib/puppet/network/handler/filebucket.rb b/lib/puppet/network/handler/filebucket.rb
index c0693ad7a..6aaa2df1c 100755
--- a/lib/puppet/network/handler/filebucket.rb
+++ b/lib/puppet/network/handler/filebucket.rb
@@ -3,49 +3,49 @@ require 'digest/md5'
require 'puppet/external/base64'
class Puppet::Network::Handler # :nodoc:
- # Accept files and store them by md5 sum, returning the md5 sum back
- # to the client. Alternatively, accept an md5 sum and return the
- # associated content.
- class FileBucket < Handler
- desc "The interface to Puppet's FileBucket system. Can be used to store
- files in and retrieve files from a filebucket."
-
- @interface = XMLRPC::Service::Interface.new("puppetbucket") { |iface|
- iface.add_method("string addfile(string, string)")
- iface.add_method("string getfile(string)")
- }
-
- Puppet::Util.logmethods(self, true)
- attr_reader :name, :path
-
- def initialize(hash)
- @path = hash[:Path] || Puppet[:bucketdir]
- @name = "Filebucket[#{@path}]"
- end
-
- # Accept a file from a client and store it by md5 sum, returning
- # the sum.
- def addfile(contents, path, client = nil, clientip = nil)
- contents = Base64.decode64(contents) if client
- bucket = Puppet::FileBucket::File.new(contents)
- bucket.save
- end
-
- # Return the contents associated with a given md5 sum.
- def getfile(md5, client = nil, clientip = nil)
- bucket = Puppet::FileBucket::File.find("md5:#{md5}")
- contents = bucket.contents
-
- if client
- return Base64.encode64(contents)
- else
- return contents
- end
- end
-
- def to_s
- self.name
- end
+ # Accept files and store them by md5 sum, returning the md5 sum back
+ # to the client. Alternatively, accept an md5 sum and return the
+ # associated content.
+ class FileBucket < Handler
+ desc "The interface to Puppet's FileBucket system. Can be used to store
+ files in and retrieve files from a filebucket."
+
+ @interface = XMLRPC::Service::Interface.new("puppetbucket") { |iface|
+ iface.add_method("string addfile(string, string)")
+ iface.add_method("string getfile(string)")
+ }
+
+ Puppet::Util.logmethods(self, true)
+ attr_reader :name, :path
+
+ def initialize(hash)
+ @path = hash[:Path] || Puppet[:bucketdir]
+ @name = "Filebucket[#{@path}]"
end
+
+ # Accept a file from a client and store it by md5 sum, returning
+ # the sum.
+ def addfile(contents, path, client = nil, clientip = nil)
+ contents = Base64.decode64(contents) if client
+ bucket = Puppet::FileBucket::File.new(contents)
+ bucket.save
+ end
+
+ # Return the contents associated with a given md5 sum.
+ def getfile(md5, client = nil, clientip = nil)
+ bucket = Puppet::FileBucket::File.find("md5:#{md5}")
+ contents = bucket.contents
+
+ if client
+ return Base64.encode64(contents)
+ else
+ return contents
+ end
+ end
+
+ def to_s
+ self.name
+ end
+ end
end
diff --git a/lib/puppet/network/handler/fileserver.rb b/lib/puppet/network/handler/fileserver.rb
index 0a5082012..27b913ab9 100755
--- a/lib/puppet/network/handler/fileserver.rb
+++ b/lib/puppet/network/handler/fileserver.rb
@@ -9,717 +9,717 @@ require 'puppet/file_serving'
require 'puppet/file_serving/metadata'
class Puppet::Network::Handler
- AuthStoreError = Puppet::AuthStoreError
- class FileServerError < Puppet::Error; end
- class FileServer < Handler
- desc "The interface to Puppet's fileserving abilities."
+ AuthStoreError = Puppet::AuthStoreError
+ class FileServerError < Puppet::Error; end
+ class FileServer < Handler
+ desc "The interface to Puppet's fileserving abilities."
- attr_accessor :local
+ attr_accessor :local
- CHECKPARAMS = [:mode, :type, :owner, :group, :checksum]
+ CHECKPARAMS = [:mode, :type, :owner, :group, :checksum]
- # Special filserver module for puppet's module system
- MODULES = "modules"
- PLUGINS = "plugins"
+ # Special filserver module for puppet's module system
+ MODULES = "modules"
+ PLUGINS = "plugins"
- @interface = XMLRPC::Service::Interface.new("fileserver") { |iface|
- iface.add_method("string describe(string, string)")
- iface.add_method("string list(string, string, boolean, array)")
- iface.add_method("string retrieve(string, string)")
- }
+ @interface = XMLRPC::Service::Interface.new("fileserver") { |iface|
+ iface.add_method("string describe(string, string)")
+ iface.add_method("string list(string, string, boolean, array)")
+ iface.add_method("string retrieve(string, string)")
+ }
- def self.params
- CHECKPARAMS.dup
- end
+ def self.params
+ CHECKPARAMS.dup
+ end
- # If the configuration file exists, then create (if necessary) a LoadedFile
- # object to manage it; else, return nil.
- def configuration
- # Short-circuit the default case.
- return @configuration if defined?(@configuration)
+ # If the configuration file exists, then create (if necessary) a LoadedFile
+ # object to manage it; else, return nil.
+ def configuration
+ # Short-circuit the default case.
+ return @configuration if defined?(@configuration)
- config_path = @passed_configuration_path || Puppet[:fileserverconfig]
- return nil unless FileTest.exist?(config_path)
+ config_path = @passed_configuration_path || Puppet[:fileserverconfig]
+ return nil unless FileTest.exist?(config_path)
- # The file exists but we don't have a LoadedFile instance for it.
- @configuration = Puppet::Util::LoadedFile.new(config_path)
- end
+ # The file exists but we don't have a LoadedFile instance for it.
+ @configuration = Puppet::Util::LoadedFile.new(config_path)
+ end
- # Create our default mounts for modules and plugins. This is duplicated code,
- # but I'm not really worried about that.
- def create_default_mounts
- @mounts = {}
- Puppet.debug "No file server configuration file; autocreating #{MODULES} mount with default permissions"
- mount = Mount.new(MODULES)
- mount.allow("*")
- @mounts[MODULES] = mount
-
- Puppet.debug "No file server configuration file; autocreating #{PLUGINS} mount with default permissions"
- mount = PluginMount.new(PLUGINS)
- mount.allow("*")
- @mounts[PLUGINS] = mount
- end
+ # Create our default mounts for modules and plugins. This is duplicated code,
+ # but I'm not really worried about that.
+ def create_default_mounts
+ @mounts = {}
+ Puppet.debug "No file server configuration file; autocreating #{MODULES} mount with default permissions"
+ mount = Mount.new(MODULES)
+ mount.allow("*")
+ @mounts[MODULES] = mount
+
+ Puppet.debug "No file server configuration file; autocreating #{PLUGINS} mount with default permissions"
+ mount = PluginMount.new(PLUGINS)
+ mount.allow("*")
+ @mounts[PLUGINS] = mount
+ end
- # Describe a given file. This returns all of the manageable aspects
- # of that file.
- def describe(url, links = :follow, client = nil, clientip = nil)
- links = links.intern if links.is_a? String
+ # Describe a given file. This returns all of the manageable aspects
+ # of that file.
+ def describe(url, links = :follow, client = nil, clientip = nil)
+ links = links.intern if links.is_a? String
- mount, path = convert(url, client, clientip)
+ mount, path = convert(url, client, clientip)
- mount.debug("Describing #{url} for #{client}") if client
+ mount.debug("Describing #{url} for #{client}") if client
- # use the mount to resolve the path for us.
- return "" unless full_path = mount.file_path(path, client)
+ # use the mount to resolve the path for us.
+ return "" unless full_path = mount.file_path(path, client)
- metadata = Puppet::FileServing::Metadata.new(url, :path => full_path, :links => links)
+ metadata = Puppet::FileServing::Metadata.new(url, :path => full_path, :links => links)
- return "" unless metadata.exist?
+ return "" unless metadata.exist?
- begin
- metadata.collect
- rescue => detail
- puts detail.backtrace if Puppet[:trace]
- Puppet.err detail
- return ""
- end
+ begin
+ metadata.collect
+ rescue => detail
+ puts detail.backtrace if Puppet[:trace]
+ Puppet.err detail
+ return ""
+ end
- metadata.attributes_with_tabs
- end
+ metadata.attributes_with_tabs
+ end
- # Create a new fileserving module.
- def initialize(hash = {})
- @mounts = {}
- @files = {}
+ # Create a new fileserving module.
+ def initialize(hash = {})
+ @mounts = {}
+ @files = {}
- @local = hash[:Local]
+ @local = hash[:Local]
- @noreadconfig = true if hash[:Config] == false
+ @noreadconfig = true if hash[:Config] == false
- @passed_configuration_path = hash[:Config]
+ @passed_configuration_path = hash[:Config]
- if hash.include?(:Mount)
- @passedconfig = true
- raise Puppet::DevError, "Invalid mount hash #{hash[:Mount].inspect}" unless hash[:Mount].is_a?(Hash)
+ if hash.include?(:Mount)
+ @passedconfig = true
+ raise Puppet::DevError, "Invalid mount hash #{hash[:Mount].inspect}" unless hash[:Mount].is_a?(Hash)
- hash[:Mount].each { |dir, name|
- self.mount(dir, name) if FileTest.exists?(dir)
- }
- self.mount(nil, MODULES)
- self.mount(nil, PLUGINS)
- else
- @passedconfig = false
- if configuration
- readconfig(false) # don't check the file the first time.
- else
- create_default_mounts
- end
- end
+ hash[:Mount].each { |dir, name|
+ self.mount(dir, name) if FileTest.exists?(dir)
+ }
+ self.mount(nil, MODULES)
+ self.mount(nil, PLUGINS)
+ else
+ @passedconfig = false
+ if configuration
+ readconfig(false) # don't check the file the first time.
+ else
+ create_default_mounts
end
+ end
+ end
- # List a specific directory's contents.
- def list(url, links = :ignore, recurse = false, ignore = false, client = nil, clientip = nil)
- mount, path = convert(url, client, clientip)
-
- mount.debug "Listing #{url} for #{client}" if client
+ # List a specific directory's contents.
+ def list(url, links = :ignore, recurse = false, ignore = false, client = nil, clientip = nil)
+ mount, path = convert(url, client, clientip)
- return "" unless mount.path_exists?(path, client)
+ mount.debug "Listing #{url} for #{client}" if client
- desc = mount.list(path, recurse, ignore, client)
+ return "" unless mount.path_exists?(path, client)
- if desc.length == 0
- mount.notice "Got no information on //#{mount}/#{path}"
- return ""
- end
-
- desc.collect { |sub| sub.join("\t") }.join("\n")
- end
+ desc = mount.list(path, recurse, ignore, client)
- def local?
- self.local
- end
+ if desc.length == 0
+ mount.notice "Got no information on //#{mount}/#{path}"
+ return ""
+ end
- # Is a given mount available?
- def mounted?(name)
- @mounts.include?(name)
- end
+ desc.collect { |sub| sub.join("\t") }.join("\n")
+ end
- # Mount a new directory with a name.
- def mount(path, name)
- if @mounts.include?(name)
- if @mounts[name] != path
- raise FileServerError, "#{@mounts[name].path} is already mounted at #{name}"
- else
- # it's already mounted; no problem
- return
- end
- end
+ def local?
+ self.local
+ end
- # Let the mounts do their own error-checking.
- @mounts[name] = Mount.new(name, path)
- @mounts[name].info "Mounted #{path}"
+ # Is a given mount available?
+ def mounted?(name)
+ @mounts.include?(name)
+ end
- @mounts[name]
+ # Mount a new directory with a name.
+ def mount(path, name)
+ if @mounts.include?(name)
+ if @mounts[name] != path
+ raise FileServerError, "#{@mounts[name].path} is already mounted at #{name}"
+ else
+ # it's already mounted; no problem
+ return
end
+ end
- # Retrieve a file from the local disk and pass it to the remote
- # client.
- def retrieve(url, links = :ignore, client = nil, clientip = nil)
- links = links.intern if links.is_a? String
-
- mount, path = convert(url, client, clientip)
+ # Let the mounts do their own error-checking.
+ @mounts[name] = Mount.new(name, path)
+ @mounts[name].info "Mounted #{path}"
- mount.info "Sending #{url} to #{client}" if client
-
- unless mount.path_exists?(path, client)
- mount.debug "#{mount} reported that #{path} does not exist"
- return ""
- end
-
- links = links.intern if links.is_a? String
+ @mounts[name]
+ end
- if links == :ignore and FileTest.symlink?(path)
- mount.debug "I think that #{path} is a symlink and we're ignoring them"
- return ""
- end
+ # Retrieve a file from the local disk and pass it to the remote
+ # client.
+ def retrieve(url, links = :ignore, client = nil, clientip = nil)
+ links = links.intern if links.is_a? String
- str = mount.read_file(path, client)
+ mount, path = convert(url, client, clientip)
- if @local
- return str
- else
- return CGI.escape(str)
- end
- end
+ mount.info "Sending #{url} to #{client}" if client
- def umount(name)
- @mounts.delete(name) if @mounts.include? name
- end
+ unless mount.path_exists?(path, client)
+ mount.debug "#{mount} reported that #{path} does not exist"
+ return ""
+ end
- private
+ links = links.intern if links.is_a? String
- def authcheck(file, mount, client, clientip)
- # If we're local, don't bother passing in information.
- if local?
- client = nil
- clientip = nil
- end
- unless mount.allowed?(client, clientip)
- mount.warning "#{client} cannot access #{file}"
- raise Puppet::AuthorizationError, "Cannot access #{mount}"
- end
- end
+ if links == :ignore and FileTest.symlink?(path)
+ mount.debug "I think that #{path} is a symlink and we're ignoring them"
+ return ""
+ end
- # Take a URL and some client info and return a mount and relative
- # path pair.
- #
- def convert(url, client, clientip)
- readconfig
+ str = mount.read_file(path, client)
- url = URI.unescape(url)
+ if @local
+ return str
+ else
+ return CGI.escape(str)
+ end
+ end
- mount, stub = splitpath(url, client)
+ def umount(name)
+ @mounts.delete(name) if @mounts.include? name
+ end
- authcheck(url, mount, client, clientip)
+ private
+
+ def authcheck(file, mount, client, clientip)
+ # If we're local, don't bother passing in information.
+ if local?
+ client = nil
+ clientip = nil
+ end
+ unless mount.allowed?(client, clientip)
+ mount.warning "#{client} cannot access #{file}"
+ raise Puppet::AuthorizationError, "Cannot access #{mount}"
+ end
+ end
- return mount, stub
- end
+ # Take a URL and some client info and return a mount and relative
+ # path pair.
+ #
+ def convert(url, client, clientip)
+ readconfig
- # Return the mount for the Puppet modules; allows file copying from
- # the modules.
- def modules_mount(module_name, client)
- # Find our environment, if we have one.
- unless hostname = (client || Facter.value("hostname"))
- raise ArgumentError, "Could not find hostname"
- end
- env = (node = Puppet::Node.find(hostname)) ? node.environment : nil
+ url = URI.unescape(url)
- # And use the environment to look up the module.
- (mod = Puppet::Node::Environment.new(env).module(module_name) and mod.files?) ? @mounts[MODULES].copy(mod.name, mod.file_directory) : nil
- end
+ mount, stub = splitpath(url, client)
- # Read the configuration file.
- def readconfig(check = true)
- return if @noreadconfig
-
- return unless configuration
-
- return if check and ! @configuration.changed?
-
- newmounts = {}
- begin
- File.open(@configuration.file) { |f|
- mount = nil
- count = 1
- f.each { |line|
- case line
- when /^\s*#/; next # skip comments
- when /^\s*$/; next # skip blank lines
- when /\[([-\w]+)\]/
- name = $1
- raise FileServerError, "#{newmounts[name]} is already mounted as #{name} in #{@configuration.file}" if newmounts.include?(name)
- mount = Mount.new(name)
- newmounts[name] = mount
- when /^\s*(\w+)\s+(.+)$/
- var = $1
- value = $2
- case var
- when "path"
- if mount.name == MODULES
- Puppet.warning "The '#{mount.name}' module can not have a path. Ignoring attempt to set it"
- else
- begin
- mount.path = value
- rescue FileServerError => detail
- Puppet.err "Removing mount #{mount.name}: #{detail}"
- newmounts.delete(mount.name)
- end
- end
- when "allow"
- value.split(/\s*,\s*/).each { |val|
- begin
- mount.info "allowing #{val} access"
- mount.allow(val)
- rescue AuthStoreError => detail
- puts detail.backtrace if Puppet[:trace]
-
- raise FileServerError.new(
- detail.to_s,
-
- count, @configuration.file)
- end
- }
- when "deny"
- value.split(/\s*,\s*/).each { |val|
- begin
- mount.info "denying #{val} access"
- mount.deny(val)
- rescue AuthStoreError => detail
-
- raise FileServerError.new(
- detail.to_s,
-
- count, @configuration.file)
- end
- }
- else
- raise FileServerError.new("Invalid argument '#{var}'", count, @configuration.file)
- end
- else
- raise FileServerError.new("Invalid line '#{line.chomp}'", count, @configuration.file)
- end
- count += 1
- }
- }
- rescue Errno::EACCES => detail
- Puppet.err "FileServer error: Cannot read #{@configuration}; cannot serve"
- #raise Puppet::Error, "Cannot read #{@configuration}"
- rescue Errno::ENOENT => detail
- Puppet.err "FileServer error: '#{@configuration}' does not exist; cannot serve"
- end
+ authcheck(url, mount, client, clientip)
- unless newmounts[MODULES]
- Puppet.debug "No #{MODULES} mount given; autocreating with default permissions"
- mount = Mount.new(MODULES)
- mount.allow("*")
- newmounts[MODULES] = mount
- end
-
- unless newmounts[PLUGINS]
- Puppet.debug "No #{PLUGINS} mount given; autocreating with default permissions"
- mount = PluginMount.new(PLUGINS)
- mount.allow("*")
- newmounts[PLUGINS] = mount
- end
-
- unless newmounts[PLUGINS].valid?
- Puppet.debug "No path given for #{PLUGINS} mount; creating a special PluginMount"
- # We end up here if the user has specified access rules for
- # the plugins mount, without specifying a path (which means
- # they want to have the default behaviour for the mount, but
- # special access control). So we need to move all the
- # user-specified access controls into the new PluginMount
- # object...
- mount = PluginMount.new(PLUGINS)
- # Yes, you're allowed to hate me for this.
-
- mount.instance_variable_set(
- :@declarations,
-
- newmounts[PLUGINS].instance_variable_get(:@declarations)
- )
- newmounts[PLUGINS] = mount
- end
+ return mount, stub
+ end
- # Verify each of the mounts are valid.
- # We let the check raise an error, so that it can raise an error
- # pointing to the specific problem.
- newmounts.each { |name, mount|
- raise FileServerError, "Invalid mount #{name}" unless mount.valid?
- }
- @mounts = newmounts
- end
+ # Return the mount for the Puppet modules; allows file copying from
+ # the modules.
+ def modules_mount(module_name, client)
+ # Find our environment, if we have one.
+ unless hostname = (client || Facter.value("hostname"))
+ raise ArgumentError, "Could not find hostname"
+ end
+ env = (node = Puppet::Node.find(hostname)) ? node.environment : nil
+
+ # And use the environment to look up the module.
+ (mod = Puppet::Node::Environment.new(env).module(module_name) and mod.files?) ? @mounts[MODULES].copy(mod.name, mod.file_directory) : nil
+ end
- # Split the path into the separate mount point and path.
- def splitpath(dir, client)
- # the dir is based on one of the mounts
- # so first retrieve the mount path
- mount = nil
- path = nil
- if dir =~ %r{/([-\w]+)}
- # Strip off the mount name.
- mount_name, path = dir.sub(%r{^/}, '').split(File::Separator, 2)
-
- unless mount = modules_mount(mount_name, client)
- unless mount = @mounts[mount_name]
- raise FileServerError, "Fileserver module '#{mount_name}' not mounted"
- end
+ # Read the configuration file.
+ def readconfig(check = true)
+ return if @noreadconfig
+
+ return unless configuration
+
+ return if check and ! @configuration.changed?
+
+ newmounts = {}
+ begin
+ File.open(@configuration.file) { |f|
+ mount = nil
+ count = 1
+ f.each { |line|
+ case line
+ when /^\s*#/; next # skip comments
+ when /^\s*$/; next # skip blank lines
+ when /\[([-\w]+)\]/
+ name = $1
+ raise FileServerError, "#{newmounts[name]} is already mounted as #{name} in #{@configuration.file}" if newmounts.include?(name)
+ mount = Mount.new(name)
+ newmounts[name] = mount
+ when /^\s*(\w+)\s+(.+)$/
+ var = $1
+ value = $2
+ case var
+ when "path"
+ if mount.name == MODULES
+ Puppet.warning "The '#{mount.name}' module can not have a path. Ignoring attempt to set it"
+ else
+ begin
+ mount.path = value
+ rescue FileServerError => detail
+ Puppet.err "Removing mount #{mount.name}: #{detail}"
+ newmounts.delete(mount.name)
+ end
end
+ when "allow"
+ value.split(/\s*,\s*/).each { |val|
+ begin
+ mount.info "allowing #{val} access"
+ mount.allow(val)
+ rescue AuthStoreError => detail
+ puts detail.backtrace if Puppet[:trace]
+
+ raise FileServerError.new(
+ detail.to_s,
+
+ count, @configuration.file)
+ end
+ }
+ when "deny"
+ value.split(/\s*,\s*/).each { |val|
+ begin
+ mount.info "denying #{val} access"
+ mount.deny(val)
+ rescue AuthStoreError => detail
+
+ raise FileServerError.new(
+ detail.to_s,
+
+ count, @configuration.file)
+ end
+ }
+ else
+ raise FileServerError.new("Invalid argument '#{var}'", count, @configuration.file)
+ end
else
- raise FileServerError, "Fileserver error: Invalid path '#{dir}'"
- end
-
- if path.nil? or path == ''
- path = '/'
- elsif path
- # Remove any double slashes that might have occurred
- path = URI.unescape(path.gsub(/\/\//, "/"))
+ raise FileServerError.new("Invalid line '#{line.chomp}'", count, @configuration.file)
end
+ count += 1
+ }
+ }
+ rescue Errno::EACCES => detail
+ Puppet.err "FileServer error: Cannot read #{@configuration}; cannot serve"
+ #raise Puppet::Error, "Cannot read #{@configuration}"
+ rescue Errno::ENOENT => detail
+ Puppet.err "FileServer error: '#{@configuration}' does not exist; cannot serve"
+ end
+
+ unless newmounts[MODULES]
+ Puppet.debug "No #{MODULES} mount given; autocreating with default permissions"
+ mount = Mount.new(MODULES)
+ mount.allow("*")
+ newmounts[MODULES] = mount
+ end
+
+ unless newmounts[PLUGINS]
+ Puppet.debug "No #{PLUGINS} mount given; autocreating with default permissions"
+ mount = PluginMount.new(PLUGINS)
+ mount.allow("*")
+ newmounts[PLUGINS] = mount
+ end
+
+ unless newmounts[PLUGINS].valid?
+ Puppet.debug "No path given for #{PLUGINS} mount; creating a special PluginMount"
+ # We end up here if the user has specified access rules for
+ # the plugins mount, without specifying a path (which means
+ # they want to have the default behaviour for the mount, but
+ # special access control). So we need to move all the
+ # user-specified access controls into the new PluginMount
+ # object...
+ mount = PluginMount.new(PLUGINS)
+ # Yes, you're allowed to hate me for this.
+
+ mount.instance_variable_set(
+ :@declarations,
+
+ newmounts[PLUGINS].instance_variable_get(:@declarations)
+ )
+ newmounts[PLUGINS] = mount
+ end
+
+ # Verify each of the mounts are valid.
+ # We let the check raise an error, so that it can raise an error
+ # pointing to the specific problem.
+ newmounts.each { |name, mount|
+ raise FileServerError, "Invalid mount #{name}" unless mount.valid?
+ }
+ @mounts = newmounts
+ end
- return mount, path
- end
-
- def to_s
- "fileserver"
+ # Split the path into the separate mount point and path.
+ def splitpath(dir, client)
+ # the dir is based on one of the mounts
+ # so first retrieve the mount path
+ mount = nil
+ path = nil
+ if dir =~ %r{/([-\w]+)}
+ # Strip off the mount name.
+ mount_name, path = dir.sub(%r{^/}, '').split(File::Separator, 2)
+
+ unless mount = modules_mount(mount_name, client)
+ unless mount = @mounts[mount_name]
+ raise FileServerError, "Fileserver module '#{mount_name}' not mounted"
+ end
end
+ else
+ raise FileServerError, "Fileserver error: Invalid path '#{dir}'"
+ end
+
+ if path.nil? or path == ''
+ path = '/'
+ elsif path
+ # Remove any double slashes that might have occurred
+ path = URI.unescape(path.gsub(/\/\//, "/"))
+ end
+
+ return mount, path
+ end
- # A simple class for wrapping mount points. Instances of this class
- # don't know about the enclosing object; they're mainly just used for
- # authorization.
- class Mount < Puppet::Network::AuthStore
- attr_reader :name
-
- @@syncs = {}
-
- @@files = {}
-
- Puppet::Util.logmethods(self, true)
-
- # Create a map for a specific client.
- def clientmap(client)
- {
- "h" => client.sub(/\..*$/, ""),
- "H" => client,
- "d" => client.sub(/[^.]+\./, "") # domain name
- }
- end
-
- # Replace % patterns as appropriate.
- def expand(path, client = nil)
- # This map should probably be moved into a method.
- map = nil
-
- if client
- map = clientmap(client)
- else
- Puppet.notice "No client; expanding '#{path}' with local host"
- # Else, use the local information
- map = localmap
- end
- path.gsub(/%(.)/) do |v|
- key = $1
- if key == "%"
- "%"
- else
- map[key] || v
- end
- end
- end
-
- # Do we have any patterns in our path, yo?
- def expandable?
- if defined?(@expandable)
- @expandable
- else
- false
- end
- end
-
- # Return a fully qualified path, given a short path and
- # possibly a client name.
- def file_path(relative_path, node = nil)
- full_path = path(node)
-
- unless full_path
- p self
- raise ArgumentError.new("Mounts without paths are not usable") unless full_path
- end
-
- # If there's no relative path name, then we're serving the mount itself.
- return full_path unless relative_path and relative_path != "/"
-
- File.join(full_path, relative_path)
- end
-
- # Create out object. It must have a name.
- def initialize(name, path = nil)
- unless name =~ %r{^[-\w]+$}
- raise FileServerError, "Invalid name format '#{name}'"
- end
- @name = name
-
- if path
- self.path = path
- else
- @path = nil
- end
-
- @files = {}
-
- super()
- end
-
- def fileobj(path, links, client)
- obj = nil
- if obj = @files[file_path(path, client)]
- # This can only happen in local fileserving, but it's an
- # important one. It'd be nice if we didn't just set
- # the check params every time, but I'm not sure it's worth
- # the effort.
- obj[:audit] = CHECKPARAMS
- else
-
- obj = Puppet::Type.type(:file).new(
-
- :name => file_path(path, client),
-
- :audit => CHECKPARAMS
- )
- @files[file_path(path, client)] = obj
- end
-
- if links == :manage
- links = :follow
- end
+ def to_s
+ "fileserver"
+ end
- # This, ah, might be completely redundant
- obj[:links] = links unless obj[:links] == links
+ # A simple class for wrapping mount points. Instances of this class
+ # don't know about the enclosing object; they're mainly just used for
+ # authorization.
+ class Mount < Puppet::Network::AuthStore
+ attr_reader :name
- obj
- end
+ @@syncs = {}
- # Read the contents of the file at the relative path given.
- def read_file(relpath, client)
- File.read(file_path(relpath, client))
- end
+ @@files = {}
- # Cache this manufactured map, since if it's used it's likely
- # to get used a lot.
- def localmap
- unless defined?(@@localmap)
- @@localmap = {
- "h" => Facter.value("hostname"),
- "H" => [Facter.value("hostname"),
- Facter.value("domain")].join("."),
- "d" => Facter.value("domain")
- }
- end
- @@localmap
- end
-
- # Return the path as appropriate, expanding as necessary.
- def path(client = nil)
- if expandable?
- return expand(@path, client)
- else
- return @path
- end
- end
+ Puppet::Util.logmethods(self, true)
- # Set the path.
- def path=(path)
- # FIXME: For now, just don't validate paths with replacement
- # patterns in them.
- if path =~ /%./
- # Mark that we're expandable.
- @expandable = true
- else
- raise FileServerError, "#{path} does not exist" unless FileTest.exists?(path)
- raise FileServerError, "#{path} is not a directory" unless FileTest.directory?(path)
- raise FileServerError, "#{path} is not readable" unless FileTest.readable?(path)
- @expandable = false
- end
- @path = path
- end
-
- # Verify that the path given exists within this mount's subtree.
- #
- def path_exists?(relpath, client = nil)
- File.exists?(file_path(relpath, client))
- end
+ # Create a map for a specific client.
+ def clientmap(client)
+ {
+ "h" => client.sub(/\..*$/, ""),
+ "H" => client,
+ "d" => client.sub(/[^.]+\./, "") # domain name
+ }
+ end
+
+ # Replace % patterns as appropriate.
+ def expand(path, client = nil)
+ # This map should probably be moved into a method.
+ map = nil
+
+ if client
+ map = clientmap(client)
+ else
+ Puppet.notice "No client; expanding '#{path}' with local host"
+ # Else, use the local information
+ map = localmap
+ end
+ path.gsub(/%(.)/) do |v|
+ key = $1
+ if key == "%"
+ "%"
+ else
+ map[key] || v
+ end
+ end
+ end
+
+ # Do we have any patterns in our path, yo?
+ def expandable?
+ if defined?(@expandable)
+ @expandable
+ else
+ false
+ end
+ end
- # Return the current values for the object.
- def properties(obj)
- obj.retrieve.inject({}) { |props, ary| props[ary[0].name] = ary[1]; props }
- end
+ # Return a fully qualified path, given a short path and
+ # possibly a client name.
+ def file_path(relative_path, node = nil)
+ full_path = path(node)
- # Retrieve a specific directory relative to a mount point.
- # If they pass in a client, then expand as necessary.
- def subdir(dir = nil, client = nil)
- basedir = self.path(client)
+ unless full_path
+ p self
+ raise ArgumentError.new("Mounts without paths are not usable") unless full_path
+ end
- dirname = if dir
- File.join(basedir, *dir.split("/"))
- else
- basedir
- end
+ # If there's no relative path name, then we're serving the mount itself.
+ return full_path unless relative_path and relative_path != "/"
- dirname
- end
+ File.join(full_path, relative_path)
+ end
- def sync(path)
- @@syncs[path] ||= Sync.new
- @@syncs[path]
- end
+ # Create out object. It must have a name.
+ def initialize(name, path = nil)
+ unless name =~ %r{^[-\w]+$}
+ raise FileServerError, "Invalid name format '#{name}'"
+ end
+ @name = name
- def to_s
- "mount[#{@name}]"
- end
+ if path
+ self.path = path
+ else
+ @path = nil
+ end
- # Verify our configuration is valid. This should really check to
- # make sure at least someone will be allowed, but, eh.
- def valid?
- if name == MODULES
- return @path.nil?
- else
- return ! @path.nil?
- end
- end
+ @files = {}
- # Return a new mount with the same properties as +self+, except
- # with a different name and path.
- def copy(name, path)
- result = self.clone
- result.path = path
- result.instance_variable_set(:@name, name)
- result
- end
+ super()
+ end
- # List the contents of the relative path +relpath+ of this mount.
- #
- # +recurse+ is the number of levels to recurse into the tree,
- # or false to provide no recursion or true if you just want to
- # go for broke.
- #
- # +ignore+ is an array of filenames to ignore when traversing
- # the list.
- #
- # The return value of this method is a complex nest of arrays,
- # which describes a directory tree. Each file or directory is
- # represented by an array, where the first element is the path
- # of the file (relative to the root of the mount), and the
- # second element is the type. A directory is represented by an
- # array as well, where the first element is a "directory" array,
- # while the remaining elements are other file or directory
- # arrays. Confusing? Hell yes. As an added bonus, all names
- # must start with a slash, because... well, I'm fairly certain
- # a complete explanation would involve the words "crack pipe"
- # and "bad batch".
- #
- def list(relpath, recurse, ignore, client = nil)
- abspath = file_path(relpath, client)
- if FileTest.exists?(abspath)
- if FileTest.directory?(abspath) and recurse
- return reclist(abspath, recurse, ignore)
- else
- return [["/", File.stat(abspath).ftype]]
- end
- end
- nil
- end
+ def fileobj(path, links, client)
+ obj = nil
+ if obj = @files[file_path(path, client)]
+ # This can only happen in local fileserving, but it's an
+ # important one. It'd be nice if we didn't just set
+ # the check params every time, but I'm not sure it's worth
+ # the effort.
+ obj[:audit] = CHECKPARAMS
+ else
- def reclist(abspath, recurse, ignore)
- require 'puppet/file_serving'
- require 'puppet/file_serving/fileset'
- if recurse.is_a?(Fixnum)
- args = { :recurse => true, :recurselimit => recurse, :links => :follow }
- else
- args = { :recurse => recurse, :links => :follow }
- end
- args[:ignore] = ignore if ignore
- fs = Puppet::FileServing::Fileset.new(abspath, args)
- ary = fs.files.collect do |file|
- if file == "."
- file = "/"
- else
- file = File.join("/", file )
- end
- stat = fs.stat(File.join(abspath, file))
- next if stat.nil?
- [ file, stat.ftype ]
- end
+ obj = Puppet::Type.type(:file).new(
- ary.compact
- end
+ :name => file_path(path, client),
+ :audit => CHECKPARAMS
+ )
+ @files[file_path(path, client)] = obj
end
- # A special mount class specifically for the plugins mount -- just
- # has some magic to effectively do a union mount of the 'plugins'
- # directory of all modules.
- #
- class PluginMount < Mount
- def path(client)
- ''
- end
-
- def mod_path_exists?(mod, relpath, client = nil)
- ! mod.plugin(relpath).nil?
- end
+ if links == :manage
+ links = :follow
+ end
- def path_exists?(relpath, client = nil)
- !valid_modules(client).find { |mod| mod.plugin(relpath) }.nil?
- end
+ # This, ah, might be completely redundant
+ obj[:links] = links unless obj[:links] == links
+
+ obj
+ end
+
+ # Read the contents of the file at the relative path given.
+ def read_file(relpath, client)
+ File.read(file_path(relpath, client))
+ end
+
+ # Cache this manufactured map, since if it's used it's likely
+ # to get used a lot.
+ def localmap
+ unless defined?(@@localmap)
+ @@localmap = {
+ "h" => Facter.value("hostname"),
+ "H" => [Facter.value("hostname"),
+ Facter.value("domain")].join("."),
+ "d" => Facter.value("domain")
+ }
+ end
+ @@localmap
+ end
+
+ # Return the path as appropriate, expanding as necessary.
+ def path(client = nil)
+ if expandable?
+ return expand(@path, client)
+ else
+ return @path
+ end
+ end
+
+ # Set the path.
+ def path=(path)
+ # FIXME: For now, just don't validate paths with replacement
+ # patterns in them.
+ if path =~ /%./
+ # Mark that we're expandable.
+ @expandable = true
+ else
+ raise FileServerError, "#{path} does not exist" unless FileTest.exists?(path)
+ raise FileServerError, "#{path} is not a directory" unless FileTest.directory?(path)
+ raise FileServerError, "#{path} is not readable" unless FileTest.readable?(path)
+ @expandable = false
+ end
+ @path = path
+ end
+
+ # Verify that the path given exists within this mount's subtree.
+ #
+ def path_exists?(relpath, client = nil)
+ File.exists?(file_path(relpath, client))
+ end
+
+ # Return the current values for the object.
+ def properties(obj)
+ obj.retrieve.inject({}) { |props, ary| props[ary[0].name] = ary[1]; props }
+ end
+
+ # Retrieve a specific directory relative to a mount point.
+ # If they pass in a client, then expand as necessary.
+ def subdir(dir = nil, client = nil)
+ basedir = self.path(client)
+
+ dirname = if dir
+ File.join(basedir, *dir.split("/"))
+ else
+ basedir
+ end
- def valid?
- true
- end
+ dirname
+ end
+
+ def sync(path)
+ @@syncs[path] ||= Sync.new
+ @@syncs[path]
+ end
+
+ def to_s
+ "mount[#{@name}]"
+ end
+
+ # Verify our configuration is valid. This should really check to
+ # make sure at least someone will be allowed, but, eh.
+ def valid?
+ if name == MODULES
+ return @path.nil?
+ else
+ return ! @path.nil?
+ end
+ end
+
+ # Return a new mount with the same properties as +self+, except
+ # with a different name and path.
+ def copy(name, path)
+ result = self.clone
+ result.path = path
+ result.instance_variable_set(:@name, name)
+ result
+ end
+
+ # List the contents of the relative path +relpath+ of this mount.
+ #
+ # +recurse+ is the number of levels to recurse into the tree,
+ # or false to provide no recursion or true if you just want to
+ # go for broke.
+ #
+ # +ignore+ is an array of filenames to ignore when traversing
+ # the list.
+ #
+ # The return value of this method is a complex nest of arrays,
+ # which describes a directory tree. Each file or directory is
+ # represented by an array, where the first element is the path
+ # of the file (relative to the root of the mount), and the
+ # second element is the type. A directory is represented by an
+ # array as well, where the first element is a "directory" array,
+ # while the remaining elements are other file or directory
+ # arrays. Confusing? Hell yes. As an added bonus, all names
+ # must start with a slash, because... well, I'm fairly certain
+ # a complete explanation would involve the words "crack pipe"
+ # and "bad batch".
+ #
+ def list(relpath, recurse, ignore, client = nil)
+ abspath = file_path(relpath, client)
+ if FileTest.exists?(abspath)
+ if FileTest.directory?(abspath) and recurse
+ return reclist(abspath, recurse, ignore)
+ else
+ return [["/", File.stat(abspath).ftype]]
+ end
+ end
+ nil
+ end
+
+ def reclist(abspath, recurse, ignore)
+ require 'puppet/file_serving'
+ require 'puppet/file_serving/fileset'
+ if recurse.is_a?(Fixnum)
+ args = { :recurse => true, :recurselimit => recurse, :links => :follow }
+ else
+ args = { :recurse => recurse, :links => :follow }
+ end
+ args[:ignore] = ignore if ignore
+ fs = Puppet::FileServing::Fileset.new(abspath, args)
+ ary = fs.files.collect do |file|
+ if file == "."
+ file = "/"
+ else
+ file = File.join("/", file )
+ end
+ stat = fs.stat(File.join(abspath, file))
+ next if stat.nil?
+ [ file, stat.ftype ]
+ end
- def mod_file_path(mod, relpath, client = nil)
- File.join(mod, PLUGINS, relpath)
- end
+ ary.compact
+ end
- def file_path(relpath, client = nil)
- return nil unless mod = valid_modules(client).find { |m| m.plugin(relpath) }
- mod.plugin(relpath)
- end
+ end
- # create a list of files by merging all modules
- def list(relpath, recurse, ignore, client = nil)
- result = []
- valid_modules(client).each do |mod|
- if modpath = mod.plugin(relpath)
- if FileTest.directory?(modpath) and recurse
- ary = reclist(modpath, recurse, ignore)
- ary ||= []
- result += ary
- else
- result += [["/", File.stat(modpath).ftype]]
- end
- end
- end
- result
+ # A special mount class specifically for the plugins mount -- just
+ # has some magic to effectively do a union mount of the 'plugins'
+ # directory of all modules.
+ #
+ class PluginMount < Mount
+ def path(client)
+ ''
+ end
+
+ def mod_path_exists?(mod, relpath, client = nil)
+ ! mod.plugin(relpath).nil?
+ end
+
+ def path_exists?(relpath, client = nil)
+ !valid_modules(client).find { |mod| mod.plugin(relpath) }.nil?
+ end
+
+ def valid?
+ true
+ end
+
+ def mod_file_path(mod, relpath, client = nil)
+ File.join(mod, PLUGINS, relpath)
+ end
+
+ def file_path(relpath, client = nil)
+ return nil unless mod = valid_modules(client).find { |m| m.plugin(relpath) }
+ mod.plugin(relpath)
+ end
+
+ # create a list of files by merging all modules
+ def list(relpath, recurse, ignore, client = nil)
+ result = []
+ valid_modules(client).each do |mod|
+ if modpath = mod.plugin(relpath)
+ if FileTest.directory?(modpath) and recurse
+ ary = reclist(modpath, recurse, ignore)
+ ary ||= []
+ result += ary
+ else
+ result += [["/", File.stat(modpath).ftype]]
end
+ end
+ end
+ result
+ end
- private
- def valid_modules(client)
- Puppet::Node::Environment.new.modules.find_all { |mod| mod.exist? }
- end
+ private
+ def valid_modules(client)
+ Puppet::Node::Environment.new.modules.find_all { |mod| mod.exist? }
+ end
- def add_to_filetree(f, filetree)
- first, rest = f.split(File::SEPARATOR, 2)
- end
- end
+ def add_to_filetree(f, filetree)
+ first, rest = f.split(File::SEPARATOR, 2)
+ end
end
+ end
end
diff --git a/lib/puppet/network/handler/master.rb b/lib/puppet/network/handler/master.rb
index 6696df448..c21aafafc 100644
--- a/lib/puppet/network/handler/master.rb
+++ b/lib/puppet/network/handler/master.rb
@@ -5,85 +5,85 @@ require 'xmlrpc/server'
require 'yaml'
class Puppet::Network::Handler
- class MasterError < Puppet::Error; end
- class Master < Handler
- desc "Puppet's configuration interface. Used for all interactions related to
- generating client configurations."
+ class MasterError < Puppet::Error; end
+ class Master < Handler
+ desc "Puppet's configuration interface. Used for all interactions related to
+ generating client configurations."
- include Puppet::Util
+ include Puppet::Util
- attr_accessor :ast
- attr_reader :ca
+ attr_accessor :ast
+ attr_reader :ca
- @interface = XMLRPC::Service::Interface.new("puppetmaster") { |iface|
- iface.add_method("string getconfig(string)")
- iface.add_method("int freshness()")
- }
+ @interface = XMLRPC::Service::Interface.new("puppetmaster") { |iface|
+ iface.add_method("string getconfig(string)")
+ iface.add_method("int freshness()")
+ }
- # Tell a client whether there's a fresh config for it
- def freshness(client = nil, clientip = nil)
- # Always force a recompile. Newer clients shouldn't do this (as of April 2008).
- Time.now.to_i
- end
+ # Tell a client whether there's a fresh config for it
+ def freshness(client = nil, clientip = nil)
+ # Always force a recompile. Newer clients shouldn't do this (as of April 2008).
+ Time.now.to_i
+ end
- def initialize(hash = {})
- args = {}
+ def initialize(hash = {})
+ args = {}
- @local = hash[:Local]
+ @local = hash[:Local]
- args[:Local] = true
+ args[:Local] = true
- @ca = (hash.include?(:CA) and hash[:CA]) ? Puppet::SSLCertificates::CA.new : nil
+ @ca = (hash.include?(:CA) and hash[:CA]) ? Puppet::SSLCertificates::CA.new : nil
- # This is only used by the cfengine module, or if --loadclasses was
- # specified in +puppet+.
- args[:Classes] = hash[:Classes] if hash.include?(:Classes)
- end
+ # This is only used by the cfengine module, or if --loadclasses was
+ # specified in +puppet+.
+ args[:Classes] = hash[:Classes] if hash.include?(:Classes)
+ end
- # Call our various handlers; this handler is getting deprecated.
- def getconfig(facts, format = "marshal", client = nil, clientip = nil)
- facts = decode_facts(facts)
+ # Call our various handlers; this handler is getting deprecated.
+ def getconfig(facts, format = "marshal", client = nil, clientip = nil)
+ facts = decode_facts(facts)
- client ||= facts["hostname"]
+ client ||= facts["hostname"]
- # Pass the facts to the fact handler
- Puppet::Node::Facts.new(client, facts).save unless local?
+ # Pass the facts to the fact handler
+ Puppet::Node::Facts.new(client, facts).save unless local?
- catalog = Puppet::Resource::Catalog.find(client)
+ catalog = Puppet::Resource::Catalog.find(client)
- case format
- when "yaml"
- return CGI.escape(catalog.extract.to_yaml)
- when "marshal"
- return CGI.escape(Marshal.dump(catalog.extract))
- else
- raise "Invalid markup format '#{format}'"
- end
- end
+ case format
+ when "yaml"
+ return CGI.escape(catalog.extract.to_yaml)
+ when "marshal"
+ return CGI.escape(Marshal.dump(catalog.extract))
+ else
+ raise "Invalid markup format '#{format}'"
+ end
+ end
- #
- def decode_facts(facts)
- if @local
- # we don't need to do anything, since we should already
- # have raw objects
- Puppet.debug "Our client is local"
- else
- Puppet.debug "Our client is remote"
-
- begin
- facts = YAML.load(CGI.unescape(facts))
- rescue => detail
- raise XMLRPC::FaultException.new(
- 1, "Could not rebuild facts"
- )
- end
- end
-
- facts
+ #
+ def decode_facts(facts)
+ if @local
+ # we don't need to do anything, since we should already
+ # have raw objects
+ Puppet.debug "Our client is local"
+ else
+ Puppet.debug "Our client is remote"
+
+ begin
+ facts = YAML.load(CGI.unescape(facts))
+ rescue => detail
+ raise XMLRPC::FaultException.new(
+ 1, "Could not rebuild facts"
+ )
end
+ end
- # Translate our configuration appropriately for sending back to a client.
- def translate(config)
- end
+ facts
+ end
+
+ # Translate our configuration appropriately for sending back to a client.
+ def translate(config)
end
+ end
end
diff --git a/lib/puppet/network/handler/report.rb b/lib/puppet/network/handler/report.rb
index d935d3822..cdd6c8be4 100755
--- a/lib/puppet/network/handler/report.rb
+++ b/lib/puppet/network/handler/report.rb
@@ -3,78 +3,78 @@ require 'puppet/reports'
# A simple server for triggering a new run on a Puppet client.
class Puppet::Network::Handler
- class Report < Handler
- desc "Accepts a Puppet transaction report and processes it."
+ class Report < Handler
+ desc "Accepts a Puppet transaction report and processes it."
- @interface = XMLRPC::Service::Interface.new("puppetreports") { |iface|
- iface.add_method("string report(array)")
- }
+ @interface = XMLRPC::Service::Interface.new("puppetreports") { |iface|
+ iface.add_method("string report(array)")
+ }
- # Add a new report type.
- def self.newreport(name, options = {}, &block)
- Puppet.warning "The interface for registering report types has changed; use Puppet::Reports.register_report for report type #{name}"
- Puppet::Reports.register_report(name, options, &block)
- end
+ # Add a new report type.
+ def self.newreport(name, options = {}, &block)
+ Puppet.warning "The interface for registering report types has changed; use Puppet::Reports.register_report for report type #{name}"
+ Puppet::Reports.register_report(name, options, &block)
+ end
- def initialize(*args)
- super
- Puppet.settings.use(:main, :reporting, :metrics)
- end
+ def initialize(*args)
+ super
+ Puppet.settings.use(:main, :reporting, :metrics)
+ end
- # Accept a report from a client.
- def report(report, client = nil, clientip = nil)
- # Unescape the report
- report = CGI.unescape(report) unless @local
+ # Accept a report from a client.
+ def report(report, client = nil, clientip = nil)
+ # Unescape the report
+ report = CGI.unescape(report) unless @local
- Puppet.info "Processing reports #{reports().join(", ")} for #{client}"
- begin
- process(report)
- rescue => detail
- Puppet.err "Could not process report for #{client}: #{detail}"
- puts detail.backtrace if Puppet[:trace]
- end
- end
+ Puppet.info "Processing reports #{reports().join(", ")} for #{client}"
+ begin
+ process(report)
+ rescue => detail
+ Puppet.err "Could not process report for #{client}: #{detail}"
+ puts detail.backtrace if Puppet[:trace]
+ end
+ end
- private
+ private
- # Process the report using all of the existing hooks.
- def process(yaml)
- return if Puppet[:reports] == "none"
+ # Process the report using all of the existing hooks.
+ def process(yaml)
+ return if Puppet[:reports] == "none"
- # First convert the report to real objects
- begin
- report = YAML.load(yaml)
- rescue => detail
- Puppet.warning "Could not load report: #{detail}"
- return
- end
+ # First convert the report to real objects
+ begin
+ report = YAML.load(yaml)
+ rescue => detail
+ Puppet.warning "Could not load report: #{detail}"
+ return
+ end
- # Used for those reports that accept yaml
- client = report.host
+ # Used for those reports that accept yaml
+ client = report.host
- reports.each do |name|
- if mod = Puppet::Reports.report(name)
- # We have to use a dup because we're including a module in the
- # report.
- newrep = report.dup
- begin
- newrep.extend(mod)
- newrep.process
- rescue => detail
- puts detail.backtrace if Puppet[:trace]
- Puppet.err "Report #{name} failed: #{detail}"
- end
- else
- Puppet.warning "No report named '#{name}'"
- end
- end
+ reports.each do |name|
+ if mod = Puppet::Reports.report(name)
+ # We have to use a dup because we're including a module in the
+ # report.
+ newrep = report.dup
+ begin
+ newrep.extend(mod)
+ newrep.process
+ rescue => detail
+ puts detail.backtrace if Puppet[:trace]
+ Puppet.err "Report #{name} failed: #{detail}"
+ end
+ else
+ Puppet.warning "No report named '#{name}'"
end
+ end
+ end
- # Handle the parsing of the reports attribute.
- def reports
- # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
- x = Puppet[:reports].gsub(/(^\s+)|(\s+$)/, '').split(/\s*,\s*/)
- end
+ # Handle the parsing of the reports attribute.
+ def reports
+ # LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
+ x = Puppet[:reports].gsub(/(^\s+)|(\s+$)/, '').split(/\s*,\s*/)
end
+ end
end
diff --git a/lib/puppet/network/handler/runner.rb b/lib/puppet/network/handler/runner.rb
index bc1a07ac5..b02d3a548 100755
--- a/lib/puppet/network/handler/runner.rb
+++ b/lib/puppet/network/handler/runner.rb
@@ -1,31 +1,31 @@
require 'puppet/run'
class Puppet::Network::Handler
- class MissingMasterError < RuntimeError; end # Cannot find the master client
- # A simple server for triggering a new run on a Puppet client.
- class Runner < Handler
- desc "An interface for triggering client configuration runs."
+ class MissingMasterError < RuntimeError; end # Cannot find the master client
+ # A simple server for triggering a new run on a Puppet client.
+ class Runner < Handler
+ desc "An interface for triggering client configuration runs."
- @interface = XMLRPC::Service::Interface.new("puppetrunner") { |iface|
- iface.add_method("string run(string, string)")
- }
+ @interface = XMLRPC::Service::Interface.new("puppetrunner") { |iface|
+ iface.add_method("string run(string, string)")
+ }
- side :client
+ side :client
- # Run the client configuration right now, optionally specifying
- # tags and whether to ignore schedules
- def run(tags = nil, ignoreschedules = false, fg = true, client = nil, clientip = nil)
- options = {}
- options[:tags] = tags if tags
- options[:ignoreschedules] = ignoreschedules if ignoreschedules
- options[:background] = !fg
+ # Run the client configuration right now, optionally specifying
+ # tags and whether to ignore schedules
+ def run(tags = nil, ignoreschedules = false, fg = true, client = nil, clientip = nil)
+ options = {}
+ options[:tags] = tags if tags
+ options[:ignoreschedules] = ignoreschedules if ignoreschedules
+ options[:background] = !fg
- runner = Puppet::Run.new(options)
+ runner = Puppet::Run.new(options)
- runner.run
+ runner.run
- runner.status
- end
+ runner.status
end
+ end
end
diff --git a/lib/puppet/network/handler/status.rb b/lib/puppet/network/handler/status.rb
index fe6c23dc3..ec6a402a6 100644
--- a/lib/puppet/network/handler/status.rb
+++ b/lib/puppet/network/handler/status.rb
@@ -1,16 +1,16 @@
class Puppet::Network::Handler
- class Status < Handler
- desc "A simple interface for testing Puppet connectivity."
+ class Status < Handler
+ desc "A simple interface for testing Puppet connectivity."
- side :client
+ side :client
- @interface = XMLRPC::Service::Interface.new("status") { |iface|
- iface.add_method("int status()")
- }
+ @interface = XMLRPC::Service::Interface.new("status") { |iface|
+ iface.add_method("int status()")
+ }
- def status(client = nil, clientip = nil)
- 1
- end
+ def status(client = nil, clientip = nil)
+ 1
end
+ end
end