summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/executables/client/certhandler.rb70
-rw-r--r--lib/puppet/indirector/indirection.rb2
-rw-r--r--lib/puppet/indirector/request.rb25
-rw-r--r--lib/puppet/network/handler/master.rb24
-rw-r--r--lib/puppet/network/http/handler.rb55
-rw-r--r--lib/puppet/network/http/mongrel/rest.rb41
-rw-r--r--lib/puppet/network/http/webrick/rest.rb51
-rw-r--r--lib/puppet/node.rb59
-rw-r--r--lib/puppet/parser/collector.rb6
-rw-r--r--lib/puppet/parser/grammar.ra4
-rw-r--r--lib/puppet/parser/parser.rb8
-rw-r--r--lib/puppet/provider/package/pkgdmg.rb61
-rw-r--r--lib/puppet/rails/database/001_add_created_at_to_all_tables.rb28
-rw-r--r--lib/puppet/sslcertificates/ca.rb13
-rw-r--r--lib/puppet/util/resource_template.rb61
15 files changed, 317 insertions, 191 deletions
diff --git a/lib/puppet/executables/client/certhandler.rb b/lib/puppet/executables/client/certhandler.rb
new file mode 100644
index 000000000..6f23de0e3
--- /dev/null
+++ b/lib/puppet/executables/client/certhandler.rb
@@ -0,0 +1,70 @@
+
+module Puppet
+ module Executables
+ module Client
+ class CertHandler
+ attr_writer :wait_for_cert, :one_time
+
+ attr_reader :caclient
+
+ def initialize(wait_time, is_one_time)
+ @wait_for_cert = wait_time
+ @one_time = is_one_time
+ @new_cert = false
+
+ @caclient = Puppet::Network::Client.ca.new()
+ end
+
+ def read_retrieve
+ #NOTE: ACS this is checking that a file exists, maybe next time just do that?
+ unless read_cert
+ # If we don't already have the certificate, then create a client to
+ # request one. Use the special ca stuff, don't use the normal server and port.
+ retrieve_cert
+ end
+
+ !@new_cert
+ end
+
+ def retrieve_cert
+ while true do
+ begin
+ if caclient.request_cert
+ break if read_new_cert
+ else
+ Puppet.notice "Did not receive certificate"
+ if @one_time
+ Puppet.notice "Set to run 'one time'; exiting with no certificate"
+ exit(1)
+ end
+ end
+ rescue StandardError => detail
+ Puppet.err "Could not request certificate: %s" % detail.to_s
+ exit(23) if @one_time
+ end
+
+ sleep @wait_for_cert
+ end
+ end
+
+ def read_cert
+ caclient.read_cert
+ end
+
+ def read_new_cert
+ if caclient.read_cert
+ # If we read it in, then we need to get rid of our existing http connection.
+ # The @new_cert flag will help us do that
+ @new_cert = true
+ Puppet.notice "Got signed certificate"
+ else
+ Puppet.err "Could not read certificates after retrieving them"
+ exit(34) if @one_time
+ end
+
+ return @new_cert
+ end
+ end
+ end
+ end
+end
diff --git a/lib/puppet/indirector/indirection.rb b/lib/puppet/indirector/indirection.rb
index c70259304..a9fff75b8 100644
--- a/lib/puppet/indirector/indirection.rb
+++ b/lib/puppet/indirector/indirection.rb
@@ -256,7 +256,7 @@ class Puppet::Indirector::Indirection
def check_authorization(request, terminus)
# At this point, we're assuming authorization makes no sense without
# client information.
- return unless request.options[:node]
+ return unless request.node
# This is only to authorize via a terminus-specific authorization hook.
return unless terminus.respond_to?(:authorized?)
diff --git a/lib/puppet/indirector/request.rb b/lib/puppet/indirector/request.rb
index 68b7ee160..98fa38885 100644
--- a/lib/puppet/indirector/request.rb
+++ b/lib/puppet/indirector/request.rb
@@ -3,10 +3,29 @@ require 'puppet/indirector'
# Provide any attributes or functionality needed for indirected
# instances.
class Puppet::Indirector::Request
- attr_accessor :indirection_name, :key, :method, :options, :instance
+ attr_accessor :indirection_name, :key, :method, :options, :instance, :node, :ip, :authenticated
+
+ # Is this an authenticated request?
+ def authenticated?
+ # Double negative, so we just get true or false
+ ! ! authenticated
+ end
def initialize(indirection_name, method, key, options = {})
- @indirection_name, @method, @options = indirection_name, method, (options || {})
+ options ||= {}
+ raise ArgumentError, "Request options must be a hash, not %s" % options.class unless options.is_a?(Hash)
+
+ @indirection_name, @method = indirection_name, method
+
+ @options = options.inject({}) do |result, ary|
+ param, value = ary
+ if respond_to?(param.to_s + "=")
+ send(param.to_s + "=", value)
+ else
+ result[param] = value
+ end
+ result
+ end
if key.is_a?(String) or key.is_a?(Symbol)
@key = key
@@ -14,8 +33,6 @@ class Puppet::Indirector::Request
@instance = key
@key = @instance.name
end
-
- raise ArgumentError, "Request options must be a hash, not %s" % @options.class unless @options.is_a?(Hash)
end
# Look up the indirection based on the name provided.
diff --git a/lib/puppet/network/handler/master.rb b/lib/puppet/network/handler/master.rb
index 851ccc7b2..a050b089b 100644
--- a/lib/puppet/network/handler/master.rb
+++ b/lib/puppet/network/handler/master.rb
@@ -56,7 +56,8 @@ class Puppet::Network::Handler
# Call our various handlers; this handler is getting deprecated.
def getconfig(facts, format = "marshal", client = nil, clientip = nil)
facts = decode_facts(facts)
- client, clientip = clientname(client, clientip, facts)
+
+ client ||= facts["hostname"]
# Pass the facts to the fact handler
Puppet::Node::Facts.new(client, facts).save unless local?
@@ -66,27 +67,6 @@ class Puppet::Network::Handler
return translate(catalog.extract)
end
- private
-
- # Manipulate the client name as appropriate.
- def clientname(name, ip, facts)
- # Always use the hostname from Facter.
- client = facts["hostname"]
- clientip = facts["ipaddress"]
- if Puppet[:node_name] == 'cert'
- if name
- client = name
- facts["fqdn"] = client
- facts["hostname"], facts["domain"] = client.split('.', 2)
- end
- if ip
- clientip = ip
- end
- end
-
- return client, clientip
- end
-
#
def decode_facts(facts)
if @local
diff --git a/lib/puppet/network/http/handler.rb b/lib/puppet/network/http/handler.rb
index c05d4907f..3c14c8a40 100644
--- a/lib/puppet/network/http/handler.rb
+++ b/lib/puppet/network/http/handler.rb
@@ -1,30 +1,30 @@
module Puppet::Network::HTTP::Handler
-
+
def initialize_for_puppet(args = {})
raise ArgumentError unless @server = args[:server]
raise ArgumentError unless @handler = args[:handler]
@model = find_model_for_handler(@handler)
end
-
+
# handle an HTTP request
def process(request, response)
return do_find(request, response) if get?(request) and singular?(request)
return do_search(request, response) if get?(request) and plural?(request)
return do_destroy(request, response) if delete?(request) and singular?(request)
- return do_save(request, response) if put?(request) and singular?(request)
+ return do_save(request, response) if put?(request) and singular?(request)
raise ArgumentError, "Did not understand HTTP #{http_method(request)} request for '#{path(request)}'"
rescue Exception => e
return do_exception(request, response, e)
end
-
+
private
def model
@model
end
-
+
def do_find(request, response)
- key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path}]")
+ key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path(request)}]")
args = params(request)
result = model.find(key, args).to_yaml
encode_result(request, response, result)
@@ -37,7 +37,7 @@ module Puppet::Network::HTTP::Handler
end
def do_destroy(request, response)
- key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path}]")
+ key = request_key(request) || raise(ArgumentError, "Could not locate lookup key in request path [#{path(request)}]")
args = params(request)
result = model.destroy(key, args)
encode_result(request, response, YAML.dump(result))
@@ -46,70 +46,73 @@ module Puppet::Network::HTTP::Handler
def do_save(request, response)
data = body(request).to_s
raise ArgumentError, "No data to save" if !data or data.empty?
- # args = params(request)
+ args = params(request)
obj = model.from_yaml(data)
- result = save_object(obj).to_yaml
+ result = save_object(obj, args).to_yaml
encode_result(request, response, result)
end
-
- def save_object(obj)
- obj.save
+
+ # LAK:NOTE This has to be here for testing; it's a stub-point so
+ # we keep infinite recursion from happening.
+ def save_object(object, args)
+ object.save(args)
end
-
+
def do_exception(request, response, exception, status=404)
encode_result(request, response, exception.to_yaml, status)
end
-
+
def find_model_for_handler(handler)
Puppet::Indirector::Indirection.model(handler) ||
raise(ArgumentError, "Cannot locate indirection [#{handler}].")
end
-
+
def get?(request)
http_method(request) == 'GET'
end
-
+
def put?(request)
http_method(request) == 'PUT'
end
-
+
def delete?(request)
http_method(request) == 'DELETE'
end
-
+
def singular?(request)
%r{/#{@handler.to_s}$}.match(path(request))
end
-
+
def plural?(request)
%r{/#{@handler.to_s}s$}.match(path(request))
end
-
+
# methods to be overridden by the including web server class
+
def register_handler
raise NotImplementedError
end
-
+
def http_method(request)
raise NotImplementedError
end
-
+
def path(request)
raise NotImplementedError
end
-
+
def request_key(request)
raise NotImplementedError
end
-
+
def body(request)
raise NotImplementedError
end
-
+
def params(request)
raise NotImplementedError
end
-
+
def encode_result(request, response, result, status = 200)
raise NotImplementedError
end
diff --git a/lib/puppet/network/http/mongrel/rest.rb b/lib/puppet/network/http/mongrel/rest.rb
index a471a62bf..520ad67f0 100644
--- a/lib/puppet/network/http/mongrel/rest.rb
+++ b/lib/puppet/network/http/mongrel/rest.rb
@@ -3,45 +3,64 @@ require 'puppet/network/http/handler'
class Puppet::Network::HTTP::MongrelREST < Mongrel::HttpHandler
include Puppet::Network::HTTP::Handler
-
+
def initialize(args={})
super()
initialize_for_puppet(args)
end
+ # Return the query params for this request. We had to expose this method for
+ # testing purposes.
+ def params(request)
+ Mongrel::HttpRequest.query_parse(request.params["QUERY_STRING"]).merge(client_info(request))
+ end
+
private
-
+
# which HTTP verb was used in this request
def http_method(request)
request.params[Mongrel::Const::REQUEST_METHOD]
end
-
+
# what path was requested?
def path(request)
# LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
x = '/' + request.params[Mongrel::Const::REQUEST_PATH].split('/')[1]
end
-
+
# return the key included in the request path
def request_key(request)
# LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
x = request.params[Mongrel::Const::REQUEST_PATH].split('/')[2]
end
-
+
# return the request body
def body(request)
request.body
end
-
- # return the query params for this request
- def params(request)
- Mongrel::HttpRequest.query_parse(request.params["QUERY_STRING"])
- end
-
+
# produce the body of the response
def encode_result(request, response, result, status = 200)
response.start(status) do |head, body|
body.write(result)
end
end
+
+ def client_info(request)
+ result = {}
+ params = request.params
+ result[:ip] = params["REMOTE_ADDR"]
+
+ # JJM #906 The following dn.match regular expression is forgiving
+ # enough to match the two Distinguished Name string contents
+ # coming from Apache, Pound or other reverse SSL proxies.
+ if dn = params[Puppet[:ssl_client_header]] and dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/)
+ result[:node] = dn_matchdata[1].to_str
+ result[:authenticated] = (params[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
+ else
+ result[:authenticated] = false
+ end
+
+ return result
+ end
end
diff --git a/lib/puppet/network/http/webrick/rest.rb b/lib/puppet/network/http/webrick/rest.rb
index b43912196..a235fb4f3 100644
--- a/lib/puppet/network/http/webrick/rest.rb
+++ b/lib/puppet/network/http/webrick/rest.rb
@@ -1,46 +1,67 @@
require 'puppet/network/http/handler'
class Puppet::Network::HTTP::WEBrickREST < WEBrick::HTTPServlet::AbstractServlet
-
+
include Puppet::Network::HTTP::Handler
-
+
def initialize(server, handler)
- raise ArgumentError, "server is required" unless server
- super(server)
- initialize_for_puppet(:server => server, :handler => handler)
+ raise ArgumentError, "server is required" unless server
+ super(server)
+ initialize_for_puppet(:server => server, :handler => handler)
+ end
+
+ # We had to expose this method for testing purposes.
+ def params(request)
+ result = request.query
+ result.merge(client_information(request))
end
# WEBrick uses a service() method to respond to requests. Simply delegate to the handler response() method.
def service(request, response)
process(request, response)
end
-
+
private
-
+
def http_method(request)
request.request_method
end
-
+
def path(request)
# LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
x = '/' + request.path.split('/')[1]
end
-
+
def request_key(request)
# LAK:NOTE See http://snurl.com/21zf8 [groups_google_com]
x = request.path.split('/')[2]
end
-
+
def body(request)
request.body
end
-
- def params(request)
- request.query
- end
-
+
def encode_result(request, response, result, status = 200)
response.status = status
response.body = result
end
+
+ # Retrieve node/cert/ip information from the request object.
+ def client_information(request)
+ result = {}
+ if peer = request.peeraddr and ip = peer[3]
+ result[:ip] = ip
+ end
+
+ # If they have a certificate (which will almost always be true)
+ # then we get the hostname from the cert, instead of via IP
+ # info
+ result[:authenticated] = false
+ if cert = request.client_cert and nameary = cert.subject.to_a.find { |ary| ary[0] == "CN" }
+ result[:node] = nameary[1]
+ result[:authenticated] = true
+ end
+
+ result
+ end
end
diff --git a/lib/puppet/node.rb b/lib/puppet/node.rb
index 252ab961e..1d2041201 100644
--- a/lib/puppet/node.rb
+++ b/lib/puppet/node.rb
@@ -18,9 +18,8 @@ class Puppet::Node
def self.find_by_any_name(key)
return nil unless key
- facts = node_facts(key)
node = nil
- names = node_names(key, facts)
+ names = node_names(key)
names.each do |name|
name = name.to_s if name.is_a?(Symbol)
break if node = find(name)
@@ -34,13 +33,16 @@ class Puppet::Node
end
end
- if node
- node.names = names
+ return nil unless node
- return node
- else
- return nil
- end
+ node.names = names
+
+ # This is critical, because it forces our node's name to always
+ # be the key, which is nearly always the node's certificate.
+ # This is how the node instance is linked to the Facts instance,
+ # so it quite matters.
+ node.name = key
+ return node
end
private
@@ -60,33 +62,34 @@ class Puppet::Node
facts ||= node_facts(key)
names = []
- if hostname = facts["hostname"]
- unless hostname == key
- names << hostname
+ # First, get the fqdn
+ unless fqdn = facts["fqdn"]
+ if domain = facts["domain"]
+ fqdn = facts["hostname"] + "." + facts["domain"]
end
- else
- hostname = key
- end
-
- if fqdn = facts["fqdn"]
- hostname = fqdn
- names << fqdn
end
- # Make sure both the fqdn and the short name of the
- # host can be used in the manifest
- if hostname =~ /\./
- names << hostname.sub(/\..+/,'')
- elsif domain = facts['domain']
- names << hostname + "." + domain
+ # Now that we (might) have the fqdn, add each piece to the name
+ # list to search, in order of longest to shortest.
+ if fqdn
+ list = fqdn.split(".")
+ tmp = []
+ list.each_with_index do |short, i|
+ tmp << list[0..i].join(".")
+ end
+ names += tmp.reverse
end
- # Sort the names inversely by name length.
- names.sort! { |a,b| b.length <=> a.length }
-
# And make sure the key is first, since that's the most
# likely usage.
- ([key] + names).uniq
+ # The key is usually the Certificate CN, but it can be
+ # set to the 'facter' hostname instead.
+ if Puppet[:node_name] == 'cert'
+ names.unshift key
+ else
+ names.unshift facts["hostname"]
+ end
+ names.uniq
end
public
diff --git a/lib/puppet/parser/collector.rb b/lib/puppet/parser/collector.rb
index 2699dc6e1..bcba9528e 100644
--- a/lib/puppet/parser/collector.rb
+++ b/lib/puppet/parser/collector.rb
@@ -6,6 +6,12 @@ class Puppet::Parser::Collector
# Call the collection method, mark all of the returned objects as non-virtual,
# and then delete this object from the list of collections to evaluate.
def evaluate
+ # Shortcut if we're not using storeconfigs and they're trying to collect
+ # exported resources.
+ if form == :exported and Puppet[:storeconfigs] != true
+ Puppet.warning "Not collecting exported resources without storeconfigs"
+ return false
+ end
if self.resources
if objects = collect_resources and ! objects.empty?
return objects
diff --git a/lib/puppet/parser/grammar.ra b/lib/puppet/parser/grammar.ra
index 484efe83c..a2f6729ee 100644
--- a/lib/puppet/parser/grammar.ra
+++ b/lib/puppet/parser/grammar.ra
@@ -152,7 +152,7 @@ virtualresource: at resource {
type = val[0]
if (type == :exported and ! Puppet[:storeconfigs]) and ! Puppet[:parseonly]
- error "You cannot collect without storeconfigs being set"
+ Puppet.warning addcontext("You cannot collect without storeconfigs being set")
end
if val[1].is_a? AST::ResourceDefaults
@@ -193,7 +193,7 @@ collection: classref collectrhand {
args[:form] = val[1]
end
if args[:form] == :exported and ! Puppet[:storeconfigs] and ! Puppet[:parseonly]
- error "You cannot collect exported resources without storeconfigs being set"
+ Puppet.warning addcontext("You cannot collect exported resources without storeconfigs being set; the collection will be ignored")
end
result = ast AST::Collection, args
}
diff --git a/lib/puppet/parser/parser.rb b/lib/puppet/parser/parser.rb
index e27a209fc..3d7f21dca 100644
--- a/lib/puppet/parser/parser.rb
+++ b/lib/puppet/parser/parser.rb
@@ -29,7 +29,7 @@ module Puppet
class Parser < Racc::Parser
-module_eval <<'..end grammar.ra modeval..idfef5d70c9f', 'grammar.ra', 638
+module_eval <<'..end grammar.ra modeval..id9145566289', 'grammar.ra', 638
# It got too annoying having code in a file that needs to be compiled.
require 'puppet/parser/parser_support'
@@ -41,7 +41,7 @@ require 'puppet/parser/parser_support'
# $Id$
-..end grammar.ra modeval..idfef5d70c9f
+..end grammar.ra modeval..id9145566289
##### racc 1.4.5 generates ###
@@ -958,7 +958,7 @@ module_eval <<'.,.,', 'grammar.ra', 174
type = val[0]
if (type == :exported and ! Puppet[:storeconfigs]) and ! Puppet[:parseonly]
- error "You cannot collect without storeconfigs being set"
+ Puppet.warning addcontext("You cannot collect without storeconfigs being set")
end
if val[1].is_a? AST::ResourceDefaults
@@ -1011,7 +1011,7 @@ module_eval <<'.,.,', 'grammar.ra', 199
args[:form] = val[1]
end
if args[:form] == :exported and ! Puppet[:storeconfigs] and ! Puppet[:parseonly]
- error "You cannot collect exported resources without storeconfigs being set"
+ Puppet.warning addcontext("You cannot collect exported resources without storeconfigs being set; the collection will be ignored")
end
result = ast AST::Collection, args
result
diff --git a/lib/puppet/provider/package/pkgdmg.rb b/lib/puppet/provider/package/pkgdmg.rb
index 2614d0950..134be5a65 100644
--- a/lib/puppet/provider/package/pkgdmg.rb
+++ b/lib/puppet/provider/package/pkgdmg.rb
@@ -28,66 +28,7 @@
require 'puppet/provider/package'
Puppet::Type.type(:package).provide :pkgdmg, :parent => Puppet::Provider::Package do
- desc "Package management based on Apple's Installer.app and DiskUtility.app
-
-Author: Jeff McCune <jeff@northstarlabs.net>
-
-Please direct questions about this provider to the puppet-users mailing list.
-
-This package works by checking the contents of a DMG image for Apple pkg or
-mpkg files. Any number of pkg or mpkg files may exist in the root directory of
-the DMG file system. Sub directories are not checked for packages.
-
-This provider always assumes the label (formerly called 'name') attribute
-declared in the manifest will always exactly match the file name (without
-path) of the DMG file itself. Therefore, if you want to install packages in
-'Foobar.pkg.dmg' you must explicitly specify the label::
-
- package { Foobar.pkg.dmg: ensure => installed, provider => pkgdmg }
-
-Only the dmg file name itself is used when puppet determines if the packages
-contained within are currently installed. For example, if a package resource
-named 'Foobar.pkg.dmg' is named for installation and contains multiple
-packages, this provider will install all packages in the root directory of
-this file system, then create a small cookie for the whole bundle, located at
-/var/db/.puppet_pkgdmg_installed_Foobar.pkg.dmg
-
-As a result, if you change the contents of the DMG file in any way, Puppet
-will not update or re-install the packages contained within unless you change
-the file name of the DMG wrapper itself. Therefore, if you use this provider,
-I recommend you name the DMG wrapper files in a manner that lends itself to
-incremental version changes. I include some version or date string in the DMG
-name, like so::
-
- Firefox-2.0.0.3-1.pkg.dmg
-
-If I realize I've mis-packaged this DMG, then I have the option to increment
-the package version, yielding Firefox-2.0.0.3-2.pkg.dmg.
-
-This provider allows you to host DMG files within an FTP or HTTP server. This
-is primarily how the author provider distributes software. Any URL mechanism
-curl or Ruby's open-uri module supports is supported by this provider. Curl
-supported URL's yield much faster data throughput than open-uri, so I
-recommend HTTP, HTTPS, or FTP for source package repositories.
-
-Because the provider assumes packages will be transfered via CURL, a two stage
-process occurs. First, if a URL is detected, curl is invoked to transfer the
-file into a temporary directory. If no URL is present, the provider skips
-straight to step 2. In step two, the source file is mounted, then packages
-installed, and finally the DMG file is removed.
-
-If this is a problem for you, please patch the code, or bug Jeff to fix this.
-
-Example usage::
-
- package { Thunderbird-2.0.0.4-1.pkg.dmg:
- provider => pkgdmg, ensure => present
- source => 'http://0.0.0.0:8000/packages/Thunderbird-2.0.0.4-1.pkg.dmg',
- }
-
-**WARNING**: Because I assume files will be downloaded to /tmp, the current
-implementation attempts to delete DMG files if you install directly from the
-file system and not via a URL method."
+ desc "Package management based on Apple's Installer.app and DiskUtility.app. This package works by checking the contents of a DMG image for Apple pkg or mpkg files. Any number of pkg or mpkg files may exist in the root directory of the DMG file system. Sub directories are not checked for packages. See `the wiki docs </trac/puppet/wiki/DmgPackages>` for more detail."
confine :exists => "/Library/Receipts"
commands :installer => "/usr/sbin/installer"
diff --git a/lib/puppet/rails/database/001_add_created_at_to_all_tables.rb b/lib/puppet/rails/database/001_add_created_at_to_all_tables.rb
index 71ee6aeed..d1035b0db 100644
--- a/lib/puppet/rails/database/001_add_created_at_to_all_tables.rb
+++ b/lib/puppet/rails/database/001_add_created_at_to_all_tables.rb
@@ -1,17 +1,17 @@
class AddCreatedAtToAllTables < ActiveRecord::Migration
- def self.up
- ActiveRecord::Base.connection.tables.each do |t|
- unless ActiveRecord::Base.connection.columns(t).collect {|c| c.name}.include?("created_at")
- add_column t.to_s, :created_at, :datetime
- end
- end
- end
+ def self.up
+ ActiveRecord::Base.connection.tables.each do |t|
+ unless ActiveRecord::Base.connection.columns(t).collect {|c| c.name}.include?("created_at")
+ add_column t.to_s, :created_at, :datetime
+ end
+ end
+ end
- def self.down
- ActiveRecord::Base.connection.tables.each do |t|
- unless ActiveRecord::Base.connection.columns(t).collect {|c| c.name}.include?("created_at")
- remove_column t.to_s, :created_at
- end
- end
- end
+ def self.down
+ ActiveRecord::Base.connection.tables.each do |t|
+ unless ActiveRecord::Base.connection.columns(t).collect {|c| c.name}.include?("created_at")
+ remove_column t.to_s, :created_at
+ end
+ end
+ end
end
diff --git a/lib/puppet/sslcertificates/ca.rb b/lib/puppet/sslcertificates/ca.rb
index 7386318f4..2a16a32ba 100644
--- a/lib/puppet/sslcertificates/ca.rb
+++ b/lib/puppet/sslcertificates/ca.rb
@@ -97,7 +97,7 @@ class Puppet::SSLCertificates::CA
if @config[:capass] and File.readable?(@config[:capass])
return File.read(@config[:capass])
else
- raise Puppet::Error, "Could not read CA passfile %s" % @config[:capass]
+ raise Puppet::Error, "Could not decrypt CA key with password: %s" % detail
end
end
@@ -379,9 +379,14 @@ class Puppet::SSLCertificates::CA
def sign_with_key(signable, digest = OpenSSL::Digest::SHA1.new)
cakey = nil
if @config[:password]
- cakey = OpenSSL::PKey::RSA.new(
- File.read(@config[:cakey]), @config[:password]
- )
+ begin
+ cakey = OpenSSL::PKey::RSA.new(
+ File.read(@config[:cakey]), @config[:password]
+ )
+ rescue
+ raise Puppet::Error,
+ "Decrypt of CA private key with password stored in @config[:capass] not possible"
+ end
else
cakey = OpenSSL::PKey::RSA.new(
File.read(@config[:cakey])
diff --git a/lib/puppet/util/resource_template.rb b/lib/puppet/util/resource_template.rb
new file mode 100644
index 000000000..53066a192
--- /dev/null
+++ b/lib/puppet/util/resource_template.rb
@@ -0,0 +1,61 @@
+require 'puppet/util'
+require 'puppet/util/logging'
+require 'erb'
+
+# A template wrapper that evaluates a template in the
+# context of a resource, allowing the resource attributes
+# to be looked up from within the template.
+# This provides functionality essentially equivalent to
+# the language's template() function. You pass your file
+# path and the resource you want to use into the initialization
+# method, then call result() on the instance, and you get back
+# a chunk of text.
+# The resource's parameters are available as instance variables
+# (as opposed to the language, where we use a method_missing trick).
+# For example, say you have a resource that generates a file. You would
+# need to implement the following style of `generate` method:
+#
+# def generate
+# template = Puppet::Util::ResourceTemplate.new("/path/to/template", self)
+#
+# return Puppet::Type.type(:file).create :path => "/my/file",
+# :content => template.evaluate
+# end
+#
+# This generated file gets added to the catalog (which is what `generate` does),
+# and its content is the result of the template. You need to use instance
+# variables in your template, so if your template just needs to have the name
+# of the generating resource, it would just have:
+#
+# <%= @name %>
+#
+# Since the ResourceTemplate class sets as instance variables all of the resource's
+# parameters.
+#
+# Note that this example uses the generating resource as its source of
+# parameters, which is generally most useful, since it allows you to configure
+# the generated resource via the generating resource.
+class Puppet::Util::ResourceTemplate
+ include Puppet::Util::Logging
+
+ def evaluate
+ set_resource_variables
+ ERB.new(File.read(@file), 0, "-").result(binding)
+ end
+
+ def initialize(file, resource)
+ raise ArgumentError, "Template %s does not exist" % file unless FileTest.exist?(file)
+ @file = file
+ @resource = resource
+ end
+
+ private
+
+ def set_resource_variables
+ @resource.to_hash.each do |param, value|
+ var = "@#{param.to_s}"
+ instance_variable_set(var, value)
+ end
+ end
+end
+