puppet 2.6.12 → 2.6.13
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CHANGELOG +30 -0
- data/CONTRIBUTING.md +299 -0
- data/conf/redhat/puppet.spec +4 -1
- data/ext/upload_facts.rb +120 -0
- data/lib/puppet.rb +1 -1
- data/lib/puppet/application/inspect.rb +5 -2
- data/lib/puppet/application/queue.rb +11 -1
- data/lib/puppet/application/resource.rb +3 -0
- data/lib/puppet/defaults.rb +2 -1
- data/lib/puppet/indirector/facts/inventory_service.rb +20 -0
- data/lib/puppet/indirector/report/processor.rb +2 -0
- data/lib/puppet/network/handler/filebucket.rb +2 -0
- data/lib/puppet/network/handler/fileserver.rb +1 -0
- data/lib/puppet/network/handler/master.rb +1 -0
- data/lib/puppet/network/handler/report.rb +2 -0
- data/lib/puppet/network/handler/runner.rb +1 -0
- data/lib/puppet/network/handler/status.rb +2 -0
- data/lib/puppet/network/http_server.rb +3 -0
- data/lib/puppet/network/http_server/mongrel.rb +129 -0
- data/lib/puppet/provider/exec/posix.rb +6 -3
- data/lib/puppet/provider/exec/shell.rb +11 -2
- data/lib/puppet/resource/catalog.rb +6 -3
- data/lib/puppet/ssl/host.rb +2 -0
- data/lib/puppet/type/cron.rb +13 -12
- data/lib/puppet/type/file.rb +2 -2
- data/lib/puppet/type/file/source.rb +1 -1
- data/lib/puppet/type/user.rb +8 -0
- data/lib/puppet/util.rb +16 -41
- data/lib/puppet/util/settings.rb +1 -1
- data/lib/puppet/util/suidmanager.rb +48 -14
- data/spec/unit/application/inspect_spec.rb +5 -0
- data/spec/unit/application/resource_spec.rb +25 -0
- data/spec/unit/configurer_spec.rb +5 -0
- data/spec/unit/indirector/facts/inventory_service_spec.rb +22 -0
- data/spec/unit/indirector/report/processor_spec.rb +7 -5
- data/spec/unit/resource/catalog_spec.rb +54 -7
- data/spec/unit/ssl/host_spec.rb +58 -9
- data/spec/unit/type/file_spec.rb +6 -0
- data/spec/unit/type/user_spec.rb +8 -0
- data/spec/unit/util/settings_spec.rb +11 -0
- data/spec/unit/util/suidmanager_spec.rb +210 -0
- metadata +11 -5
- data/test/puppet/tc_suidmanager.rb +0 -120
data/lib/puppet.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
require 'puppet'
|
2
1
|
require 'puppet/application'
|
3
|
-
require 'puppet/file_bucket/dipper'
|
4
2
|
|
5
3
|
class Puppet::Application::Inspect < Puppet::Application
|
6
4
|
|
@@ -97,6 +95,11 @@ Licensed under the GNU General Public License version 2
|
|
97
95
|
Puppet::Resource::Catalog.terminus_class = :yaml
|
98
96
|
end
|
99
97
|
|
98
|
+
def preinit
|
99
|
+
require 'puppet'
|
100
|
+
require 'puppet/file_bucket/dipper'
|
101
|
+
end
|
102
|
+
|
100
103
|
def run_command
|
101
104
|
benchmark(:notice, "Finished inspection") do
|
102
105
|
retrieval_starttime = Time.now
|
@@ -10,7 +10,6 @@ class Puppet::Application::Queue < Puppet::Application
|
|
10
10
|
require 'puppet/daemon'
|
11
11
|
@daemon = Puppet::Daemon.new
|
12
12
|
@daemon.argv = ARGV.dup
|
13
|
-
Puppet::Util::Log.newdestination(:console)
|
14
13
|
|
15
14
|
# Do an initial trap, so that cancels don't get a stack trace.
|
16
15
|
|
@@ -37,6 +36,16 @@ class Puppet::Application::Queue < Puppet::Application
|
|
37
36
|
option("--debug","-d")
|
38
37
|
option("--verbose","-v")
|
39
38
|
|
39
|
+
option("--logdest DEST", "-l DEST") do |arg|
|
40
|
+
begin
|
41
|
+
Puppet::Util::Log.newdestination(arg)
|
42
|
+
options[:setdest] = true
|
43
|
+
rescue => detail
|
44
|
+
puts detail.backtrace if Puppet[:debug]
|
45
|
+
$stderr.puts detail.to_s
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
40
49
|
def main
|
41
50
|
require 'puppet/indirector/catalog/queue' # provides Puppet::Indirector::Queue.subscribe
|
42
51
|
Puppet.notice "Starting puppetqd #{Puppet.version}"
|
@@ -67,6 +76,7 @@ class Puppet::Application::Queue < Puppet::Application
|
|
67
76
|
Puppet::Util::Log.level = :info
|
68
77
|
end
|
69
78
|
end
|
79
|
+
Puppet::Util::Log.newdestination(:syslog) unless options[:setdest]
|
70
80
|
end
|
71
81
|
|
72
82
|
def setup
|
@@ -81,6 +81,9 @@ class Puppet::Application::Resource < Puppet::Application
|
|
81
81
|
[ Puppet::Resource.new( type, name, :parameters => params ).save( key ) ]
|
82
82
|
end
|
83
83
|
else
|
84
|
+
if type == "file"
|
85
|
+
raise "Listing all file instances is not supported. Please specify a file or directory, e.g. puppet resource file /etc"
|
86
|
+
end
|
84
87
|
Puppet::Resource.search( key, {} )
|
85
88
|
end.map(&format).join("\n")
|
86
89
|
|
data/lib/puppet/defaults.rb
CHANGED
@@ -124,7 +124,8 @@ module Puppet
|
|
124
124
|
:desc => "The node facts terminus.",
|
125
125
|
:hook => proc do |value|
|
126
126
|
require 'puppet/node/facts'
|
127
|
-
if
|
127
|
+
# Cache to YAML if we're uploading facts away
|
128
|
+
if %w[rest inventory_service].include? value.to_s
|
128
129
|
Puppet::Node::Facts.cache_class = :yaml
|
129
130
|
end
|
130
131
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'puppet/node/facts'
|
2
|
+
require 'puppet/indirector/rest'
|
3
|
+
|
4
|
+
class Puppet::Node::Facts::InventoryService < Puppet::Indirector::REST
|
5
|
+
desc "Find and save facts about nodes using a remote inventory service."
|
6
|
+
use_server_setting(:inventory_server)
|
7
|
+
use_port_setting(:inventory_port)
|
8
|
+
|
9
|
+
# We don't want failing to upload to the inventory service to cause any
|
10
|
+
# failures, so we just suppress them and warn.
|
11
|
+
def save(request)
|
12
|
+
begin
|
13
|
+
super
|
14
|
+
true
|
15
|
+
rescue => e
|
16
|
+
Puppet.warning "Could not upload facts for #{request.key} to inventory service: #{e.to_s}"
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -20,9 +20,11 @@ class Puppet::Transaction::Report::Processor < Puppet::Indirector::Code
|
|
20
20
|
# LAK:NOTE This isn't necessarily the best design, but it's backward
|
21
21
|
# compatible and that's good enough for now.
|
22
22
|
def process(report)
|
23
|
+
Puppet.debug "Recieved report to process from #{report.host}"
|
23
24
|
return if Puppet[:reports] == "none"
|
24
25
|
|
25
26
|
reports.each do |name|
|
27
|
+
Puppet.debug "Processing report from #{report.host} with processor #{name}"
|
26
28
|
if mod = Puppet::Reports.report(name)
|
27
29
|
# We have to use a dup because we're including a module in the
|
28
30
|
# report.
|
@@ -0,0 +1,129 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: 06-11-14-mongrel_xmlrpc.rb
|
3
|
+
# Author: Manuel Holtgrewe <purestorm at ggnore.net>
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006 Manuel Holtgrewe, 2007 Luke Kanies
|
6
|
+
#
|
7
|
+
# This file is based heavily on a file retrieved from
|
8
|
+
# http://ttt.ggnore.net/2006/11/15/xmlrpc-with-mongrel-and-ruby-off-rails/
|
9
|
+
|
10
|
+
require 'rubygems'
|
11
|
+
require 'mongrel'
|
12
|
+
require 'xmlrpc/server'
|
13
|
+
require 'puppet/network/xmlrpc/server'
|
14
|
+
require 'puppet/network/http_server'
|
15
|
+
require 'puppet/network/client_request'
|
16
|
+
require 'puppet/network/handler'
|
17
|
+
|
18
|
+
require 'resolv'
|
19
|
+
|
20
|
+
# This handler can be hooked into Mongrel to accept HTTP requests. After
|
21
|
+
# checking whether the request itself is sane, the handler forwards it
|
22
|
+
# to an internal instance of XMLRPC::BasicServer to process it.
|
23
|
+
#
|
24
|
+
# You can access the server by calling the Handler's "xmlrpc_server"
|
25
|
+
# attribute accessor method and add XMLRPC handlers there. For example:
|
26
|
+
#
|
27
|
+
# <pre>
|
28
|
+
# handler = XmlRpcHandler.new
|
29
|
+
# handler.xmlrpc_server.add_handler("my.add") { |a, b| a.to_i + b.to_i }
|
30
|
+
# </pre>
|
31
|
+
module Puppet::Network
|
32
|
+
class HTTPServer::Mongrel < ::Mongrel::HttpHandler
|
33
|
+
attr_reader :xmlrpc_server
|
34
|
+
|
35
|
+
def initialize(handlers)
|
36
|
+
if Puppet[:debug]
|
37
|
+
$mongrel_debug_client = true
|
38
|
+
Puppet.debug 'Mongrel client debugging enabled. [$mongrel_debug_client = true].'
|
39
|
+
end
|
40
|
+
# Create a new instance of BasicServer. We are supposed to subclass it
|
41
|
+
# but that does not make sense since we would not introduce any new
|
42
|
+
# behaviour and we have to subclass Mongrel::HttpHandler so our handler
|
43
|
+
# works for Mongrel.
|
44
|
+
@xmlrpc_server = Puppet::Network::XMLRPCServer.new
|
45
|
+
handlers.each do |name|
|
46
|
+
unless handler = Puppet::Network::Handler.handler(name)
|
47
|
+
raise ArgumentError, "Invalid handler #{name}"
|
48
|
+
end
|
49
|
+
@xmlrpc_server.add_handler(handler.interface, handler.new({}))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# This method produces the same results as XMLRPC::CGIServer.serve
|
54
|
+
# from Ruby's stdlib XMLRPC implementation.
|
55
|
+
def process(request, response)
|
56
|
+
# Make sure this has been a POST as required for XMLRPC.
|
57
|
+
request_method = request.params[Mongrel::Const::REQUEST_METHOD] || Mongrel::Const::GET
|
58
|
+
if request_method != "POST"
|
59
|
+
response.start(405) { |head, out| out.write("Method Not Allowed") }
|
60
|
+
return
|
61
|
+
end
|
62
|
+
|
63
|
+
# Make sure the user has sent text/xml data.
|
64
|
+
request_mime = request.params["CONTENT_TYPE"] || "text/plain"
|
65
|
+
if parse_content_type(request_mime).first != "text/xml"
|
66
|
+
response.start(400) { |head, out| out.write("Bad Request") }
|
67
|
+
return
|
68
|
+
end
|
69
|
+
|
70
|
+
# Make sure there is data in the body at all.
|
71
|
+
length = request.params[Mongrel::Const::CONTENT_LENGTH].to_i
|
72
|
+
if length <= 0
|
73
|
+
response.start(411) { |head, out| out.write("Length Required") }
|
74
|
+
return
|
75
|
+
end
|
76
|
+
|
77
|
+
# Check the body to be valid.
|
78
|
+
if request.body.nil? or request.body.size != length
|
79
|
+
response.start(400) { |head, out| out.write("Bad Request") }
|
80
|
+
return
|
81
|
+
end
|
82
|
+
|
83
|
+
info = client_info(request)
|
84
|
+
|
85
|
+
# All checks above passed through
|
86
|
+
response.start(200) do |head, out|
|
87
|
+
head["Content-Type"] = "text/xml; charset=utf-8"
|
88
|
+
begin
|
89
|
+
out.write(@xmlrpc_server.process(request.body, info))
|
90
|
+
rescue => detail
|
91
|
+
puts detail.backtrace
|
92
|
+
raise
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def client_info(request)
|
100
|
+
params = request.params
|
101
|
+
ip = params["HTTP_X_FORWARDED_FOR"] ? params["HTTP_X_FORWARDED_FOR"].split(',').last.strip : params["REMOTE_ADDR"]
|
102
|
+
# JJM #906 The following dn.match regular expression is forgiving
|
103
|
+
# enough to match the two Distinguished Name string contents
|
104
|
+
# coming from Apache, Pound or other reverse SSL proxies.
|
105
|
+
if dn = params[Puppet[:ssl_client_header]] and dn_matchdata = dn.match(/^.*?CN\s*=\s*(.*)/)
|
106
|
+
client = dn_matchdata[1].to_str
|
107
|
+
valid = (params[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
|
108
|
+
else
|
109
|
+
begin
|
110
|
+
client = Resolv.getname(ip)
|
111
|
+
rescue => detail
|
112
|
+
Puppet.err "Could not resolve #{ip}: #{detail}"
|
113
|
+
client = "unknown"
|
114
|
+
end
|
115
|
+
valid = false
|
116
|
+
end
|
117
|
+
|
118
|
+
info = Puppet::Network::ClientRequest.new(client, ip, valid)
|
119
|
+
|
120
|
+
info
|
121
|
+
end
|
122
|
+
|
123
|
+
# Taken from XMLRPC::ParseContentType
|
124
|
+
def parse_content_type(str)
|
125
|
+
a, *b = str.split(";")
|
126
|
+
return a.strip, *b
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -4,9 +4,12 @@ Puppet::Type.type(:exec).provide :posix do
|
|
4
4
|
confine :feature => :posix
|
5
5
|
defaultfor :feature => :posix
|
6
6
|
|
7
|
-
desc
|
8
|
-
|
9
|
-
|
7
|
+
desc <<-EOT
|
8
|
+
Executes external binaries directly, without passing through a shell or
|
9
|
+
performing any interpolation. This is a safer and more predictable way
|
10
|
+
to execute most commands, but prevents the use of globbing and shell
|
11
|
+
built-ins (including control logic like "for" and "if" statements).
|
12
|
+
EOT
|
10
13
|
|
11
14
|
def run(command, check = false)
|
12
15
|
output = nil
|
@@ -3,8 +3,17 @@ Puppet::Type.type(:exec).provide :shell, :parent => :posix do
|
|
3
3
|
|
4
4
|
confine :feature => :posix
|
5
5
|
|
6
|
-
desc
|
7
|
-
|
6
|
+
desc <<-EOT
|
7
|
+
Passes the provided command through `/bin/sh`; only available on
|
8
|
+
POSIX systems. This allows the use of shell globbing and built-ins, and
|
9
|
+
does not require that the path to a command be fully-qualified. Although
|
10
|
+
this can be more convenient than the `posix` provider, it also means that
|
11
|
+
you need to be more careful with escaping; as ever, with great power comes
|
12
|
+
etc. etc.
|
13
|
+
|
14
|
+
This provider closely resembles the behavior of the `exec` type
|
15
|
+
in Puppet 0.25.x.
|
16
|
+
EOT
|
8
17
|
|
9
18
|
def run(command, check = false)
|
10
19
|
command = %Q{/bin/sh -c "#{command.gsub(/"/,'\"')}"}
|
@@ -98,7 +98,7 @@ class Puppet::Resource::Catalog < Puppet::SimpleGraph
|
|
98
98
|
resource.ref =~ /^(.+)\[/
|
99
99
|
class_name = $1 || resource.class.name
|
100
100
|
|
101
|
-
newref = [class_name, key]
|
101
|
+
newref = [class_name, key].flatten
|
102
102
|
|
103
103
|
if key.is_a? String
|
104
104
|
ref_string = "#{class_name}[#{key}]"
|
@@ -111,7 +111,10 @@ class Puppet::Resource::Catalog < Puppet::SimpleGraph
|
|
111
111
|
# isn't sufficient.
|
112
112
|
if existing = @resource_table[newref]
|
113
113
|
return if existing == resource
|
114
|
-
|
114
|
+
resource_definition = " at #{resource.file}:#{resource.line}" if resource.file and resource.line
|
115
|
+
existing_definition = " at #{existing.file}:#{existing.line}" if existing.file and existing.line
|
116
|
+
msg = "Cannot alias #{resource.ref} to #{key.inspect}#{resource_definition}; resource #{newref.inspect} already defined#{existing_definition}"
|
117
|
+
raise ArgumentError, msg
|
115
118
|
end
|
116
119
|
@resource_table[newref] = resource
|
117
120
|
@aliases[resource.ref] ||= []
|
@@ -377,7 +380,7 @@ class Puppet::Resource::Catalog < Puppet::SimpleGraph
|
|
377
380
|
res = Puppet::Resource.new(nil, type)
|
378
381
|
end
|
379
382
|
title_key = [res.type, res.title.to_s]
|
380
|
-
uniqueness_key = [res.type, res.uniqueness_key]
|
383
|
+
uniqueness_key = [res.type, res.uniqueness_key].flatten
|
381
384
|
@resource_table[title_key] || @resource_table[uniqueness_key]
|
382
385
|
end
|
383
386
|
|
data/lib/puppet/ssl/host.rb
CHANGED
@@ -151,6 +151,8 @@ class Puppet::SSL::Host
|
|
151
151
|
# ...add our configured dns_alt_names
|
152
152
|
if Puppet[:dns_alt_names] and Puppet[:dns_alt_names] != ''
|
153
153
|
options[:dns_alt_names] ||= Puppet[:dns_alt_names]
|
154
|
+
elsif Puppet::SSL::CertificateAuthority.ca? and fqdn = Facter.value(:fqdn) and domain = Facter.value(:domain)
|
155
|
+
options[:dns_alt_names] = "puppet, #{fqdn}, puppet.#{domain}"
|
154
156
|
end
|
155
157
|
end
|
156
158
|
|
data/lib/puppet/type/cron.rb
CHANGED
@@ -3,11 +3,12 @@ require 'facter'
|
|
3
3
|
require 'puppet/util/filetype'
|
4
4
|
|
5
5
|
Puppet::Type.newtype(:cron) do
|
6
|
-
@doc =
|
7
|
-
and
|
8
|
-
|
9
|
-
minute. While the name of the cron
|
10
|
-
job, it is used by Puppet to store and
|
6
|
+
@doc = <<-EOT
|
7
|
+
Installs and manages cron jobs. Every cron resource requires a command
|
8
|
+
and user attribute, as well as at least one periodic attribute (hour,
|
9
|
+
minute, month, monthday, weekday, or special). While the name of the cron
|
10
|
+
job is not part of the actual job, it is used by Puppet to store and
|
11
|
+
retrieve it.
|
11
12
|
|
12
13
|
If you specify a cron job that matches an existing job in every way
|
13
14
|
except name, then the jobs will be considered equivalent and the
|
@@ -18,30 +19,30 @@ Puppet::Type.newtype(:cron) do
|
|
18
19
|
Example:
|
19
20
|
|
20
21
|
cron { logrotate:
|
21
|
-
command =>
|
22
|
+
command => "/usr/sbin/logrotate",
|
22
23
|
user => root,
|
23
24
|
hour => 2,
|
24
25
|
minute => 0
|
25
26
|
}
|
26
27
|
|
27
|
-
Note that all
|
28
|
+
Note that all periodic attributes can be specified as an array of values:
|
28
29
|
|
29
30
|
cron { logrotate:
|
30
|
-
command =>
|
31
|
+
command => "/usr/sbin/logrotate",
|
31
32
|
user => root,
|
32
33
|
hour => [2, 4]
|
33
34
|
}
|
34
35
|
|
35
|
-
|
36
|
-
your `cron` daemon supports
|
36
|
+
...or using ranges or the step syntax `*/2` (although there's no guarantee
|
37
|
+
that your `cron` daemon supports these):
|
37
38
|
|
38
39
|
cron { logrotate:
|
39
|
-
command =>
|
40
|
+
command => "/usr/sbin/logrotate",
|
40
41
|
user => root,
|
41
42
|
hour => ['2-4'],
|
42
43
|
minute => '*/10'
|
43
44
|
}
|
44
|
-
|
45
|
+
EOT
|
45
46
|
ensurable
|
46
47
|
|
47
48
|
# A base class for all of the Cron parameters, since they all have
|
data/lib/puppet/type/file.rb
CHANGED
@@ -309,8 +309,8 @@ Puppet::Type.newtype(:file) do
|
|
309
309
|
super(path.gsub(/\/+/, '/').sub(/\/$/, ''))
|
310
310
|
end
|
311
311
|
|
312
|
-
def self.instances
|
313
|
-
return
|
312
|
+
def self.instances
|
313
|
+
return []
|
314
314
|
end
|
315
315
|
|
316
316
|
@depthfirst = false
|