puppet 2.7.9 → 2.7.11
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 +413 -0
- data/README_DEVELOPER.md +28 -0
- data/conf/redhat/puppet.spec +10 -1
- data/conf/solaris/pkginfo +1 -1
- data/conf/suse/puppet.spec +7 -4
- data/ext/envpuppet.bat +13 -0
- data/ext/rack/files/apache2.conf +4 -0
- data/install.rb +4 -8
- data/lib/puppet.rb +1 -1
- data/lib/puppet/agent.rb +7 -0
- data/lib/puppet/agent/disabler.rb +27 -0
- data/lib/puppet/agent/locker.rb +0 -10
- data/lib/puppet/application.rb +3 -0
- data/lib/puppet/application/agent.rb +13 -3
- data/lib/puppet/application/apply.rb +6 -6
- data/lib/puppet/application/cert.rb +5 -5
- data/lib/puppet/application/instrumentation_data.rb +4 -0
- data/lib/puppet/application/instrumentation_listener.rb +4 -0
- data/lib/puppet/application/instrumentation_probe.rb +4 -0
- data/lib/puppet/configurer.rb +3 -1
- data/lib/puppet/configurer/downloader.rb +4 -2
- data/lib/puppet/configurer/fact_handler.rb +0 -21
- data/lib/puppet/daemon.rb +3 -4
- data/lib/puppet/defaults.rb +2 -2
- data/lib/puppet/face/instrumentation_data.rb +28 -0
- data/lib/puppet/face/instrumentation_listener.rb +96 -0
- data/lib/puppet/face/instrumentation_probe.rb +77 -0
- data/lib/puppet/face/module/list.rb +64 -0
- data/lib/puppet/face/module/uninstall.rb +50 -0
- data/lib/puppet/face/node/clean.rb +1 -4
- data/lib/puppet/feature/base.rb +1 -0
- data/lib/puppet/file_serving/content.rb +1 -1
- data/lib/puppet/indirector/facts/facter.rb +20 -7
- data/lib/puppet/indirector/facts/inventory_active_record.rb +14 -11
- data/lib/puppet/indirector/indirection.rb +7 -0
- data/lib/puppet/indirector/instrumentation_data.rb +3 -0
- data/lib/puppet/indirector/instrumentation_data/local.rb +19 -0
- data/lib/puppet/indirector/instrumentation_data/rest.rb +5 -0
- data/lib/puppet/indirector/instrumentation_listener.rb +3 -0
- data/lib/puppet/indirector/instrumentation_listener/local.rb +23 -0
- data/lib/puppet/indirector/instrumentation_listener/rest.rb +5 -0
- data/lib/puppet/indirector/instrumentation_probe.rb +3 -0
- data/lib/puppet/indirector/instrumentation_probe/local.rb +24 -0
- data/lib/puppet/indirector/instrumentation_probe/rest.rb +5 -0
- data/lib/puppet/indirector/rest.rb +1 -1
- data/lib/puppet/module.rb +13 -17
- data/lib/puppet/module_tool/applications.rb +1 -0
- data/lib/puppet/module_tool/applications/uninstaller.rb +33 -0
- data/lib/puppet/module_tool/contents_description.rb +1 -1
- data/lib/puppet/network/server.rb +2 -3
- data/lib/puppet/node/environment.rb +16 -3
- data/lib/puppet/parser/ast/leaf.rb +1 -1
- data/lib/puppet/parser/functions/create_resources.rb +1 -1
- data/lib/puppet/parser/type_loader.rb +1 -1
- data/lib/puppet/property.rb +46 -14
- data/lib/puppet/provider.rb +13 -4
- data/lib/puppet/provider/augeas/augeas.rb +6 -4
- data/lib/puppet/provider/group/pw.rb +24 -10
- data/lib/puppet/provider/nameservice/directoryservice.rb +146 -37
- data/lib/puppet/provider/package/pip.rb +1 -1
- data/lib/puppet/provider/package/yum.rb +1 -2
- data/lib/puppet/provider/service/debian.rb +14 -0
- data/lib/puppet/provider/service/launchd.rb +1 -1
- data/lib/puppet/provider/service/smf.rb +2 -2
- data/lib/puppet/provider/user/pw.rb +56 -2
- data/lib/puppet/provider/user/user_role_add.rb +32 -22
- data/lib/puppet/provider/user/windows_adsi.rb +1 -0
- data/lib/puppet/rails/benchmark.rb +1 -1
- data/lib/puppet/reports/store.rb +8 -1
- data/lib/puppet/resource/catalog.rb +5 -1
- data/lib/puppet/simple_graph.rb +11 -14
- data/lib/puppet/transaction.rb +10 -4
- data/lib/puppet/transaction/report.rb +9 -3
- data/lib/puppet/type.rb +19 -7
- data/lib/puppet/type/exec.rb +1 -1
- data/lib/puppet/type/file.rb +4 -1
- data/lib/puppet/type/file/ensure.rb +5 -1
- data/lib/puppet/type/file/mode.rb +45 -10
- data/lib/puppet/type/file/source.rb +4 -0
- data/lib/puppet/type/host.rb +17 -3
- data/lib/puppet/type/k5login.rb +3 -2
- data/lib/puppet/type/schedule.rb +3 -2
- data/lib/puppet/util.rb +83 -27
- data/lib/puppet/util/anonymous_filelock.rb +36 -0
- data/lib/puppet/util/docs.rb +18 -2
- data/lib/puppet/util/instrumentation.rb +173 -0
- data/lib/puppet/util/instrumentation/data.rb +34 -0
- data/lib/puppet/util/instrumentation/indirection_probe.rb +29 -0
- data/lib/puppet/util/instrumentation/instrumentable.rb +143 -0
- data/lib/puppet/util/instrumentation/listener.rb +60 -0
- data/lib/puppet/util/instrumentation/listeners/log.rb +29 -0
- data/lib/puppet/util/instrumentation/listeners/performance.rb +30 -0
- data/lib/puppet/util/monkey_patches.rb +8 -0
- data/lib/puppet/util/pidlock.rb +21 -25
- data/lib/puppet/util/rdoc/parser.rb +2 -2
- data/lib/puppet/util/reference.rb +8 -23
- data/lib/puppet/util/retryaction.rb +48 -0
- data/lib/puppet/util/suidmanager.rb +70 -39
- data/lib/puppet/util/symbolic_file_mode.rb +140 -0
- data/spec/integration/configurer_spec.rb +5 -0
- data/spec/integration/indirector/direct_file_server_spec.rb +1 -1
- data/spec/integration/indirector/file_content/file_server_spec.rb +7 -7
- data/spec/integration/provider/package_spec.rb +7 -0
- data/spec/unit/agent/disabler_spec.rb +60 -0
- data/spec/unit/agent/locker_spec.rb +0 -12
- data/spec/unit/agent_spec.rb +8 -0
- data/spec/unit/application/agent_spec.rb +38 -1
- data/spec/unit/application/apply_spec.rb +34 -40
- data/spec/unit/application/cert_spec.rb +1 -1
- data/spec/unit/application_spec.rb +6 -0
- data/spec/unit/configurer/downloader_spec.rb +29 -10
- data/spec/unit/configurer/fact_handler_spec.rb +5 -29
- data/spec/unit/configurer_spec.rb +8 -8
- data/spec/unit/daemon_spec.rb +12 -26
- data/spec/unit/face/instrumentation_data.rb +7 -0
- data/spec/unit/face/instrumentation_listener.rb +38 -0
- data/spec/unit/face/instrumentation_probe.rb +21 -0
- data/spec/unit/face/node_spec.rb +111 -111
- data/spec/unit/file_serving/content_spec.rb +2 -2
- data/spec/unit/indirector/facts/facter_spec.rb +25 -3
- data/spec/unit/indirector/facts/inventory_active_record_spec.rb +14 -4
- data/spec/unit/indirector/instrumentation_data/local_spec.rb +52 -0
- data/spec/unit/indirector/instrumentation_data/rest_spec.rb +11 -0
- data/spec/unit/indirector/instrumentation_listener/local_spec.rb +65 -0
- data/spec/unit/indirector/instrumentation_listener/rest_spec.rb +11 -0
- data/spec/unit/indirector/instrumentation_probe/local_spec.rb +65 -0
- data/spec/unit/indirector/instrumentation_probe/rest_spec.rb +11 -0
- data/spec/unit/module_spec.rb +39 -125
- data/spec/unit/module_tool/uninstaller_spec.rb +44 -0
- data/spec/unit/network/server_spec.rb +2 -20
- data/spec/unit/node/environment_spec.rb +76 -58
- data/spec/unit/parser/ast/asthash_spec.rb +1 -2
- data/spec/unit/parser/ast/leaf_spec.rb +16 -0
- data/spec/unit/property/keyvalue_spec.rb +5 -2
- data/spec/unit/property_spec.rb +260 -159
- data/spec/unit/provider/augeas/augeas_spec.rb +2 -2
- data/spec/unit/provider/group/pw_spec.rb +81 -0
- data/spec/unit/provider/nameservice/directoryservice_spec.rb +102 -0
- data/spec/unit/provider/package/pip_spec.rb +7 -0
- data/spec/unit/provider/package/yum_spec.rb +45 -1
- data/spec/unit/provider/service/debian_spec.rb +15 -0
- data/spec/unit/provider/service/launchd_spec.rb +48 -43
- data/spec/unit/provider/service/smf_spec.rb +3 -3
- data/spec/unit/provider/user/pw_spec.rb +183 -0
- data/spec/unit/provider/user/user_role_add_spec.rb +46 -39
- data/spec/unit/provider/user/windows_adsi_spec.rb +1 -0
- data/spec/unit/provider_spec.rb +32 -0
- data/spec/unit/reports/store_spec.rb +19 -1
- data/spec/unit/simple_graph_spec.rb +34 -19
- data/spec/unit/ssl/certificate_factory_spec.rb +3 -3
- data/spec/unit/transaction/report_spec.rb +29 -1
- data/spec/unit/transaction_spec.rb +32 -46
- data/spec/unit/type/file/mode_spec.rb +1 -1
- data/spec/unit/type/file/source_spec.rb +28 -3
- data/spec/unit/type/file_spec.rb +17 -16
- data/spec/unit/type/host_spec.rb +527 -0
- data/spec/unit/type/k5login_spec.rb +115 -0
- data/spec/unit/type/schedule_spec.rb +6 -6
- data/spec/unit/type_spec.rb +51 -0
- data/spec/unit/util/anonymous_filelock_spec.rb +78 -0
- data/spec/unit/util/execution_stub_spec.rb +2 -1
- data/spec/unit/util/instrumentation/data_spec.rb +44 -0
- data/spec/unit/util/instrumentation/indirection_probe_spec.rb +19 -0
- data/spec/unit/util/instrumentation/instrumentable_spec.rb +186 -0
- data/spec/unit/util/instrumentation/listener_spec.rb +100 -0
- data/spec/unit/util/instrumentation/listeners/log_spec.rb +34 -0
- data/spec/unit/util/instrumentation/listeners/performance_spec.rb +36 -0
- data/spec/unit/util/instrumentation_spec.rb +181 -0
- data/spec/unit/util/pidlock_spec.rb +208 -0
- data/spec/unit/util/rdoc/parser_spec.rb +1 -1
- data/spec/unit/util/reference_spec.rb +16 -6
- data/spec/unit/util/retryaction_spec.rb +62 -0
- data/spec/unit/util/suidmanager_spec.rb +101 -83
- data/spec/unit/util/symbolic_file_mode_spec.rb +182 -0
- data/spec/unit/util_spec.rb +126 -0
- data/tasks/rake/apple.rake +176 -0
- data/tasks/rake/templates/prototype.plist.erb +38 -0
- metadata +61 -13
- data/lib/puppet/application/module.rb +0 -3
- data/lib/puppet/face/module.rb +0 -12
- data/spec/unit/face/module/build_spec.rb +0 -30
- data/spec/unit/face/module/changes_spec.rb +0 -30
- data/spec/unit/face/module/clean_spec.rb +0 -30
- data/spec/unit/face/module/generate_spec.rb +0 -30
- data/spec/unit/face/module/install_spec.rb +0 -75
- data/spec/unit/face/module/search_spec.rb +0 -40
- data/test/util/pidlock.rb +0 -126
@@ -132,6 +132,10 @@ module Puppet
|
|
132
132
|
next if metadata_method == :checksum and metadata.ftype == "directory"
|
133
133
|
next if metadata_method == :checksum and metadata.ftype == "link" and metadata.links == :manage
|
134
134
|
|
135
|
+
if Puppet.features.microsoft_windows?
|
136
|
+
next if [:owner, :group].include?(metadata_method) and !local?
|
137
|
+
end
|
138
|
+
|
135
139
|
if resource[param_name].nil? or resource[param_name] == :absent
|
136
140
|
resource[param_name] = metadata.send(metadata_method)
|
137
141
|
end
|
data/lib/puppet/type/host.rb
CHANGED
@@ -7,12 +7,26 @@ module Puppet
|
|
7
7
|
newproperty(:ip) do
|
8
8
|
desc "The host's IP address, IPv4 or IPv6."
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
|
11
|
+
def valid_v4?(addr)
|
12
|
+
if /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ =~ addr
|
13
|
+
return $~.captures.all? {|i| i = i.to_i; i >= 0 and i <= 255 }
|
13
14
|
end
|
15
|
+
return false
|
14
16
|
end
|
15
17
|
|
18
|
+
def valid_v6?(addr)
|
19
|
+
# http://forums.dartware.com/viewtopic.php?t=452
|
20
|
+
# ...and, yes, it is this hard. Doing it programatically is harder.
|
21
|
+
return true if addr =~ /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/
|
22
|
+
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
|
26
|
+
validate do |value|
|
27
|
+
return true if valid_v4?(value) or valid_v6?(value)
|
28
|
+
raise Puppet::Error, "Invalid IP address #{value.inspect}"
|
29
|
+
end
|
16
30
|
end
|
17
31
|
|
18
32
|
# for now we use OrderedList to indicate that the order does matter.
|
data/lib/puppet/type/k5login.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# Plug-in type for handling k5login files
|
2
|
+
require 'puppet/util'
|
2
3
|
|
3
4
|
Puppet::Type.newtype(:k5login) do
|
4
5
|
@doc = "Manage the `.k5login` file for a user. Specify the full path to
|
@@ -79,8 +80,8 @@ Puppet::Type.newtype(:k5login) do
|
|
79
80
|
|
80
81
|
private
|
81
82
|
def write(value)
|
82
|
-
Puppet::Util.
|
83
|
-
f.puts value
|
83
|
+
Puppet::Util.replace_file(@resource[:name], 0644) do |f|
|
84
|
+
f.puts value
|
84
85
|
end
|
85
86
|
end
|
86
87
|
end
|
data/lib/puppet/type/schedule.rb
CHANGED
@@ -81,7 +81,8 @@ module Puppet
|
|
81
81
|
}
|
82
82
|
|
83
83
|
This is mostly useful for restricting certain resources to being
|
84
|
-
applied in maintenance windows or during off-peak hours.
|
84
|
+
applied in maintenance windows or during off-peak hours. Multiple
|
85
|
+
ranges can be applied in array context.
|
85
86
|
EOT
|
86
87
|
|
87
88
|
# This is lame; properties all use arrays as values, but parameters don't.
|
@@ -178,7 +179,7 @@ module Puppet
|
|
178
179
|
|
179
180
|
#self.info limits.inspect
|
180
181
|
#self.notice now
|
181
|
-
return now.between?(*limits)
|
182
|
+
return true if now.between?(*limits)
|
182
183
|
end
|
183
184
|
|
184
185
|
# Else, return false, since our current time isn't between
|
data/lib/puppet/util.rb
CHANGED
@@ -2,12 +2,13 @@
|
|
2
2
|
|
3
3
|
require 'English'
|
4
4
|
require 'puppet/util/monkey_patches'
|
5
|
-
require 'sync'
|
6
|
-
require 'tempfile'
|
7
5
|
require 'puppet/external/lock'
|
8
|
-
require 'monitor'
|
9
6
|
require 'puppet/util/execution_stub'
|
10
7
|
require 'uri'
|
8
|
+
require 'sync'
|
9
|
+
require 'monitor'
|
10
|
+
require 'tempfile'
|
11
|
+
require 'pathname'
|
11
12
|
|
12
13
|
module Puppet
|
13
14
|
# A command failed to execute.
|
@@ -314,8 +315,7 @@ module Util
|
|
314
315
|
|
315
316
|
3.upto(256){|fd| IO::new(fd).close rescue nil}
|
316
317
|
|
317
|
-
Puppet::Util::SUIDManager.
|
318
|
-
Puppet::Util::SUIDManager.change_user(arguments[:uid], true) if arguments[:uid]
|
318
|
+
Puppet::Util::SUIDManager.change_privileges(arguments[:uid], arguments[:gid], true)
|
319
319
|
|
320
320
|
ENV['LANG'] = ENV['LC_ALL'] = ENV['LC_MESSAGES'] = ENV['LANGUAGE'] = 'C'
|
321
321
|
Kernel.exec(*command)
|
@@ -481,33 +481,89 @@ module Util
|
|
481
481
|
|
482
482
|
module_function :memory, :thinmark
|
483
483
|
|
484
|
-
def secure_open(file,must_be_w,&block)
|
485
|
-
raise Puppet::DevError,"secure_open only works with mode 'w'" unless must_be_w == 'w'
|
486
|
-
raise Puppet::DevError,"secure_open only requires a block" unless block_given?
|
487
|
-
Puppet.warning "#{file} was a symlink to #{File.readlink(file)}" if File.symlink?(file)
|
488
|
-
if File.exists?(file) or File.symlink?(file)
|
489
|
-
wait = File.symlink?(file) ? 5.0 : 0.1
|
490
|
-
File.delete(file)
|
491
|
-
sleep wait # give it a chance to reappear, just in case someone is actively trying something.
|
492
|
-
end
|
493
|
-
begin
|
494
|
-
File.open(file,File::CREAT|File::EXCL|File::TRUNC|File::WRONLY,&block)
|
495
|
-
rescue Errno::EEXIST
|
496
|
-
desc = File.symlink?(file) ? "symlink to #{File.readlink(file)}" : File.stat(file).ftype
|
497
|
-
puts "Warning: #{file} was apparently created by another process (as"
|
498
|
-
puts "a #{desc}) as soon as it was deleted by this process. Someone may be trying"
|
499
|
-
puts "to do something objectionable (such as tricking you into overwriting system"
|
500
|
-
puts "files if you are running as root)."
|
501
|
-
raise
|
502
|
-
end
|
503
|
-
end
|
504
|
-
module_function :secure_open
|
505
|
-
|
506
484
|
# Because IO#binread is only available in 1.9
|
507
485
|
def binread(file)
|
508
486
|
File.open(file, 'rb') { |f| f.read }
|
509
487
|
end
|
510
488
|
module_function :binread
|
489
|
+
|
490
|
+
# Replace a file, securely. This takes a block, and passes it the file
|
491
|
+
# handle of a file open for writing. Write the replacement content inside
|
492
|
+
# the block and it will safely replace the target file.
|
493
|
+
#
|
494
|
+
# This method will make no changes to the target file until the content is
|
495
|
+
# successfully written and the block returns without raising an error.
|
496
|
+
#
|
497
|
+
# As far as possible the state of the existing file, such as mode, is
|
498
|
+
# preserved. This works hard to avoid loss of any metadata, but will result
|
499
|
+
# in an inode change for the file.
|
500
|
+
#
|
501
|
+
# Arguments: `filename`, `default_mode`
|
502
|
+
#
|
503
|
+
# The filename is the file we are going to replace.
|
504
|
+
#
|
505
|
+
# The default_mode is the mode to use when the target file doesn't already
|
506
|
+
# exist; if the file is present we copy the existing mode/owner/group values
|
507
|
+
# across.
|
508
|
+
def replace_file(file, default_mode, &block)
|
509
|
+
raise Puppet::DevError, "replace_file requires a block" unless block_given?
|
510
|
+
raise Puppet::DevError, "replace_file is non-functional on Windows" if Puppet.features.microsoft_windows?
|
511
|
+
|
512
|
+
file = Pathname(file)
|
513
|
+
tempfile = Tempfile.new(file.basename.to_s, file.dirname.to_s)
|
514
|
+
|
515
|
+
file_exists = file.exist?
|
516
|
+
|
517
|
+
# If the file exists, use its current mode/owner/group. If it doesn't, use
|
518
|
+
# the supplied mode, and default to current user/group.
|
519
|
+
if file_exists
|
520
|
+
stat = file.lstat
|
521
|
+
|
522
|
+
# We only care about the four lowest-order octets. Higher octets are
|
523
|
+
# filesystem-specific.
|
524
|
+
mode = stat.mode & 07777
|
525
|
+
uid = stat.uid
|
526
|
+
gid = stat.gid
|
527
|
+
else
|
528
|
+
mode = default_mode
|
529
|
+
uid = Process.euid
|
530
|
+
gid = Process.egid
|
531
|
+
end
|
532
|
+
|
533
|
+
# Set properties of the temporary file before we write the content, because
|
534
|
+
# Tempfile doesn't promise to be safe from reading by other people, just
|
535
|
+
# that it avoids races around creating the file.
|
536
|
+
tempfile.chmod(mode)
|
537
|
+
tempfile.chown(uid, gid)
|
538
|
+
|
539
|
+
# OK, now allow the caller to write the content of the file.
|
540
|
+
yield tempfile
|
541
|
+
|
542
|
+
# Now, make sure the data (which includes the mode) is safe on disk.
|
543
|
+
tempfile.flush
|
544
|
+
begin
|
545
|
+
tempfile.fsync
|
546
|
+
rescue NotImplementedError
|
547
|
+
# fsync may not be implemented by Ruby on all platforms, but
|
548
|
+
# there is absolutely no recovery path if we detect that. So, we just
|
549
|
+
# ignore the return code.
|
550
|
+
#
|
551
|
+
# However, don't be fooled: that is accepting that we are running in
|
552
|
+
# an unsafe fashion. If you are porting to a new platform don't stub
|
553
|
+
# that out.
|
554
|
+
end
|
555
|
+
|
556
|
+
tempfile.close
|
557
|
+
|
558
|
+
File.rename(tempfile.path, file)
|
559
|
+
|
560
|
+
# Ideally, we would now fsync the directory as well, but Ruby doesn't
|
561
|
+
# have support for that, and it doesn't matter /that/ much...
|
562
|
+
|
563
|
+
# Return something true, and possibly useful.
|
564
|
+
file
|
565
|
+
end
|
566
|
+
module_function :replace_file
|
511
567
|
end
|
512
568
|
end
|
513
569
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
class Puppet::Util::AnonymousFilelock
|
3
|
+
attr_reader :lockfile
|
4
|
+
|
5
|
+
def initialize(lockfile)
|
6
|
+
@lockfile = lockfile
|
7
|
+
end
|
8
|
+
|
9
|
+
def anonymous?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def lock(msg = '')
|
14
|
+
return false if locked?
|
15
|
+
|
16
|
+
File.open(@lockfile, 'w') { |fd| fd.print(msg) }
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def unlock
|
21
|
+
if locked?
|
22
|
+
File.unlink(@lockfile)
|
23
|
+
true
|
24
|
+
else
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def locked?
|
30
|
+
File.exists? @lockfile
|
31
|
+
end
|
32
|
+
|
33
|
+
def message
|
34
|
+
return File.read(@lockfile) if locked?
|
35
|
+
end
|
36
|
+
end
|
data/lib/puppet/util/docs.rb
CHANGED
@@ -20,10 +20,10 @@ module Puppet::Util::Docs
|
|
20
20
|
def doc
|
21
21
|
extra = methods.find_all { |m| m.to_s =~ /^dochook_.+/ }.sort.collect { |m|
|
22
22
|
self.send(m)
|
23
|
-
}.join(" ")
|
23
|
+
}.delete_if {|r| r.nil? }.join(" ")
|
24
24
|
|
25
25
|
if @doc
|
26
|
-
@doc + extra
|
26
|
+
@doc + (extra.empty? ? '' : "\n\n" + extra)
|
27
27
|
else
|
28
28
|
extra
|
29
29
|
end
|
@@ -73,6 +73,22 @@ module Puppet::Util::Docs
|
|
73
73
|
value.to_s + (" " * (length - value.to_s.length))
|
74
74
|
end
|
75
75
|
|
76
|
+
HEADER_LEVELS = [nil, "#", "##", "###", "####", "#####"]
|
77
|
+
|
78
|
+
def markdown_header(name, level)
|
79
|
+
"#{HEADER_LEVELS[level]} #{name}\n\n"
|
80
|
+
end
|
81
|
+
|
82
|
+
def markdown_definitionlist(term, definition)
|
83
|
+
lines = scrub(definition).split("\n")
|
84
|
+
str = "#{term}\n: #{lines.shift}\n"
|
85
|
+
lines.each do |line|
|
86
|
+
str << " " if line =~ /\S/
|
87
|
+
str << "#{line}\n"
|
88
|
+
end
|
89
|
+
str << "\n"
|
90
|
+
end
|
91
|
+
|
76
92
|
# Handle the inline indentation in the docs.
|
77
93
|
def scrub(text)
|
78
94
|
# Stupid markdown
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'puppet'
|
2
|
+
require 'puppet/util/classgen'
|
3
|
+
require 'puppet/util/instance_loader'
|
4
|
+
|
5
|
+
class Puppet::Util::Instrumentation
|
6
|
+
extend Puppet::Util::ClassGen
|
7
|
+
extend Puppet::Util::InstanceLoader
|
8
|
+
extend MonitorMixin
|
9
|
+
|
10
|
+
# we're using a ruby lazy autoloader to prevent a loop when requiring listeners
|
11
|
+
# since this class sets up an indirection which is also used in Puppet::Indirector::Indirection
|
12
|
+
# which is used to setup indirections...
|
13
|
+
autoload :Listener, 'puppet/util/instrumentation/listener'
|
14
|
+
autoload :Data, 'puppet/util/instrumentation/data'
|
15
|
+
|
16
|
+
# Set up autoloading and retrieving of instrumentation listeners.
|
17
|
+
instance_load :listener, 'puppet/util/instrumentation/listeners'
|
18
|
+
|
19
|
+
class << self
|
20
|
+
attr_accessor :listeners, :listeners_of
|
21
|
+
end
|
22
|
+
|
23
|
+
# instrumentation layer
|
24
|
+
|
25
|
+
# Triggers an instrumentation
|
26
|
+
#
|
27
|
+
# Call this method around the instrumentation point
|
28
|
+
# Puppet::Util::Instrumentation.instrument(:my_long_computation) do
|
29
|
+
# ... a long computation
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# This will send an event to all the listeners of "my_long_computation".
|
33
|
+
# Note: this method uses ruby yield directive to call the instrumented code.
|
34
|
+
# It is usually way slower than calling start and stop directly around the instrumented code.
|
35
|
+
# For high traffic code path, it is thus advisable to not use this method.
|
36
|
+
def self.instrument(label, data = {})
|
37
|
+
id = self.start(label, data)
|
38
|
+
yield
|
39
|
+
ensure
|
40
|
+
self.stop(label, id, data)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Triggers a "start" instrumentation event
|
44
|
+
#
|
45
|
+
# Important note:
|
46
|
+
# For proper use, the data hash instance used for start should also
|
47
|
+
# be used when calling stop. The idea is to use the current scope
|
48
|
+
# where start is called to retain a reference to 'data' so that it is possible
|
49
|
+
# to send it back to stop.
|
50
|
+
# This way listeners can match start and stop events more easily.
|
51
|
+
def self.start(label, data)
|
52
|
+
data[:started] = Time.now
|
53
|
+
publish(label, :start, data)
|
54
|
+
data[:id] = next_id
|
55
|
+
end
|
56
|
+
|
57
|
+
# Triggers a "stop" instrumentation event
|
58
|
+
def self.stop(label, id, data)
|
59
|
+
data[:finished] = Time.now
|
60
|
+
publish(label, :stop, data)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.publish(label, event, data)
|
64
|
+
each_listener(label) do |k,l|
|
65
|
+
l.notify(label, event, data)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.listeners
|
70
|
+
@listeners.values
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.each_listener(label)
|
74
|
+
synchronize {
|
75
|
+
@listeners_of[label] ||= @listeners.select do |k,l|
|
76
|
+
l.listen_to?(label)
|
77
|
+
end
|
78
|
+
}.each do |l|
|
79
|
+
yield l
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Adds a new listener
|
84
|
+
#
|
85
|
+
# Usage:
|
86
|
+
# Puppet::Util::Instrumentation.new_listener(:my_instrumentation, pattern) do
|
87
|
+
#
|
88
|
+
# def notify(label, data)
|
89
|
+
# ... do something for data...
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# It is possible to use a "pattern". The listener will be notified only
|
94
|
+
# if the pattern match the label of the event.
|
95
|
+
# The pattern can be a symbol, a string or a regex.
|
96
|
+
# If no pattern is provided, then the listener will be called for every events
|
97
|
+
def self.new_listener(name, options = {}, &block)
|
98
|
+
Puppet.debug "new listener called #{name}"
|
99
|
+
name = symbolize(name)
|
100
|
+
listener = genclass(name, :hash => instance_hash(:listener), :block => block)
|
101
|
+
listener.send(:define_method, :name) do
|
102
|
+
name
|
103
|
+
end
|
104
|
+
subscribe(listener.new, options[:label_pattern], options[:event])
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.subscribe(listener, label_pattern, event)
|
108
|
+
synchronize {
|
109
|
+
raise "Listener #{listener.name} is already subscribed" if @listeners.include?(listener.name)
|
110
|
+
Puppet.debug "registering instrumentation listener #{listener.name}"
|
111
|
+
@listeners[listener.name] = Listener.new(listener, label_pattern, event)
|
112
|
+
listener.subscribed if listener.respond_to?(:subscribed)
|
113
|
+
rehash
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.unsubscribe(listener)
|
118
|
+
synchronize {
|
119
|
+
Puppet.warning("#{listener.name} hasn't been registered but asked to be unregistered") unless @listeners.include?(listener.name)
|
120
|
+
Puppet.info "unregistering instrumentation listener #{listener.name}"
|
121
|
+
@listeners.delete(listener.name)
|
122
|
+
listener.unsubscribed if listener.respond_to?(:unsubscribed)
|
123
|
+
rehash
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.init
|
128
|
+
# let's init our probe indirection
|
129
|
+
require 'puppet/util/instrumentation/indirection_probe'
|
130
|
+
synchronize {
|
131
|
+
@listeners ||= {}
|
132
|
+
@listeners_of ||= {}
|
133
|
+
instance_loader(:listener).loadall
|
134
|
+
}
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.clear
|
138
|
+
synchronize {
|
139
|
+
@listeners = {}
|
140
|
+
@listeners_of = {}
|
141
|
+
@id = 0
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.[](key)
|
146
|
+
synchronize {
|
147
|
+
key = symbolize(key)
|
148
|
+
@listeners[key]
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.[]=(key, value)
|
153
|
+
synchronize {
|
154
|
+
key = symbolize(key)
|
155
|
+
@listeners[key] = value
|
156
|
+
rehash
|
157
|
+
}
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
# should be called only under the guard
|
163
|
+
# self.synchronize
|
164
|
+
def self.rehash
|
165
|
+
@listeners_of = {}
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.next_id
|
169
|
+
synchronize {
|
170
|
+
@id = (@id || 0) + 1
|
171
|
+
}
|
172
|
+
end
|
173
|
+
end
|