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.

Files changed (187) hide show
  1. data/CHANGELOG +413 -0
  2. data/README_DEVELOPER.md +28 -0
  3. data/conf/redhat/puppet.spec +10 -1
  4. data/conf/solaris/pkginfo +1 -1
  5. data/conf/suse/puppet.spec +7 -4
  6. data/ext/envpuppet.bat +13 -0
  7. data/ext/rack/files/apache2.conf +4 -0
  8. data/install.rb +4 -8
  9. data/lib/puppet.rb +1 -1
  10. data/lib/puppet/agent.rb +7 -0
  11. data/lib/puppet/agent/disabler.rb +27 -0
  12. data/lib/puppet/agent/locker.rb +0 -10
  13. data/lib/puppet/application.rb +3 -0
  14. data/lib/puppet/application/agent.rb +13 -3
  15. data/lib/puppet/application/apply.rb +6 -6
  16. data/lib/puppet/application/cert.rb +5 -5
  17. data/lib/puppet/application/instrumentation_data.rb +4 -0
  18. data/lib/puppet/application/instrumentation_listener.rb +4 -0
  19. data/lib/puppet/application/instrumentation_probe.rb +4 -0
  20. data/lib/puppet/configurer.rb +3 -1
  21. data/lib/puppet/configurer/downloader.rb +4 -2
  22. data/lib/puppet/configurer/fact_handler.rb +0 -21
  23. data/lib/puppet/daemon.rb +3 -4
  24. data/lib/puppet/defaults.rb +2 -2
  25. data/lib/puppet/face/instrumentation_data.rb +28 -0
  26. data/lib/puppet/face/instrumentation_listener.rb +96 -0
  27. data/lib/puppet/face/instrumentation_probe.rb +77 -0
  28. data/lib/puppet/face/module/list.rb +64 -0
  29. data/lib/puppet/face/module/uninstall.rb +50 -0
  30. data/lib/puppet/face/node/clean.rb +1 -4
  31. data/lib/puppet/feature/base.rb +1 -0
  32. data/lib/puppet/file_serving/content.rb +1 -1
  33. data/lib/puppet/indirector/facts/facter.rb +20 -7
  34. data/lib/puppet/indirector/facts/inventory_active_record.rb +14 -11
  35. data/lib/puppet/indirector/indirection.rb +7 -0
  36. data/lib/puppet/indirector/instrumentation_data.rb +3 -0
  37. data/lib/puppet/indirector/instrumentation_data/local.rb +19 -0
  38. data/lib/puppet/indirector/instrumentation_data/rest.rb +5 -0
  39. data/lib/puppet/indirector/instrumentation_listener.rb +3 -0
  40. data/lib/puppet/indirector/instrumentation_listener/local.rb +23 -0
  41. data/lib/puppet/indirector/instrumentation_listener/rest.rb +5 -0
  42. data/lib/puppet/indirector/instrumentation_probe.rb +3 -0
  43. data/lib/puppet/indirector/instrumentation_probe/local.rb +24 -0
  44. data/lib/puppet/indirector/instrumentation_probe/rest.rb +5 -0
  45. data/lib/puppet/indirector/rest.rb +1 -1
  46. data/lib/puppet/module.rb +13 -17
  47. data/lib/puppet/module_tool/applications.rb +1 -0
  48. data/lib/puppet/module_tool/applications/uninstaller.rb +33 -0
  49. data/lib/puppet/module_tool/contents_description.rb +1 -1
  50. data/lib/puppet/network/server.rb +2 -3
  51. data/lib/puppet/node/environment.rb +16 -3
  52. data/lib/puppet/parser/ast/leaf.rb +1 -1
  53. data/lib/puppet/parser/functions/create_resources.rb +1 -1
  54. data/lib/puppet/parser/type_loader.rb +1 -1
  55. data/lib/puppet/property.rb +46 -14
  56. data/lib/puppet/provider.rb +13 -4
  57. data/lib/puppet/provider/augeas/augeas.rb +6 -4
  58. data/lib/puppet/provider/group/pw.rb +24 -10
  59. data/lib/puppet/provider/nameservice/directoryservice.rb +146 -37
  60. data/lib/puppet/provider/package/pip.rb +1 -1
  61. data/lib/puppet/provider/package/yum.rb +1 -2
  62. data/lib/puppet/provider/service/debian.rb +14 -0
  63. data/lib/puppet/provider/service/launchd.rb +1 -1
  64. data/lib/puppet/provider/service/smf.rb +2 -2
  65. data/lib/puppet/provider/user/pw.rb +56 -2
  66. data/lib/puppet/provider/user/user_role_add.rb +32 -22
  67. data/lib/puppet/provider/user/windows_adsi.rb +1 -0
  68. data/lib/puppet/rails/benchmark.rb +1 -1
  69. data/lib/puppet/reports/store.rb +8 -1
  70. data/lib/puppet/resource/catalog.rb +5 -1
  71. data/lib/puppet/simple_graph.rb +11 -14
  72. data/lib/puppet/transaction.rb +10 -4
  73. data/lib/puppet/transaction/report.rb +9 -3
  74. data/lib/puppet/type.rb +19 -7
  75. data/lib/puppet/type/exec.rb +1 -1
  76. data/lib/puppet/type/file.rb +4 -1
  77. data/lib/puppet/type/file/ensure.rb +5 -1
  78. data/lib/puppet/type/file/mode.rb +45 -10
  79. data/lib/puppet/type/file/source.rb +4 -0
  80. data/lib/puppet/type/host.rb +17 -3
  81. data/lib/puppet/type/k5login.rb +3 -2
  82. data/lib/puppet/type/schedule.rb +3 -2
  83. data/lib/puppet/util.rb +83 -27
  84. data/lib/puppet/util/anonymous_filelock.rb +36 -0
  85. data/lib/puppet/util/docs.rb +18 -2
  86. data/lib/puppet/util/instrumentation.rb +173 -0
  87. data/lib/puppet/util/instrumentation/data.rb +34 -0
  88. data/lib/puppet/util/instrumentation/indirection_probe.rb +29 -0
  89. data/lib/puppet/util/instrumentation/instrumentable.rb +143 -0
  90. data/lib/puppet/util/instrumentation/listener.rb +60 -0
  91. data/lib/puppet/util/instrumentation/listeners/log.rb +29 -0
  92. data/lib/puppet/util/instrumentation/listeners/performance.rb +30 -0
  93. data/lib/puppet/util/monkey_patches.rb +8 -0
  94. data/lib/puppet/util/pidlock.rb +21 -25
  95. data/lib/puppet/util/rdoc/parser.rb +2 -2
  96. data/lib/puppet/util/reference.rb +8 -23
  97. data/lib/puppet/util/retryaction.rb +48 -0
  98. data/lib/puppet/util/suidmanager.rb +70 -39
  99. data/lib/puppet/util/symbolic_file_mode.rb +140 -0
  100. data/spec/integration/configurer_spec.rb +5 -0
  101. data/spec/integration/indirector/direct_file_server_spec.rb +1 -1
  102. data/spec/integration/indirector/file_content/file_server_spec.rb +7 -7
  103. data/spec/integration/provider/package_spec.rb +7 -0
  104. data/spec/unit/agent/disabler_spec.rb +60 -0
  105. data/spec/unit/agent/locker_spec.rb +0 -12
  106. data/spec/unit/agent_spec.rb +8 -0
  107. data/spec/unit/application/agent_spec.rb +38 -1
  108. data/spec/unit/application/apply_spec.rb +34 -40
  109. data/spec/unit/application/cert_spec.rb +1 -1
  110. data/spec/unit/application_spec.rb +6 -0
  111. data/spec/unit/configurer/downloader_spec.rb +29 -10
  112. data/spec/unit/configurer/fact_handler_spec.rb +5 -29
  113. data/spec/unit/configurer_spec.rb +8 -8
  114. data/spec/unit/daemon_spec.rb +12 -26
  115. data/spec/unit/face/instrumentation_data.rb +7 -0
  116. data/spec/unit/face/instrumentation_listener.rb +38 -0
  117. data/spec/unit/face/instrumentation_probe.rb +21 -0
  118. data/spec/unit/face/node_spec.rb +111 -111
  119. data/spec/unit/file_serving/content_spec.rb +2 -2
  120. data/spec/unit/indirector/facts/facter_spec.rb +25 -3
  121. data/spec/unit/indirector/facts/inventory_active_record_spec.rb +14 -4
  122. data/spec/unit/indirector/instrumentation_data/local_spec.rb +52 -0
  123. data/spec/unit/indirector/instrumentation_data/rest_spec.rb +11 -0
  124. data/spec/unit/indirector/instrumentation_listener/local_spec.rb +65 -0
  125. data/spec/unit/indirector/instrumentation_listener/rest_spec.rb +11 -0
  126. data/spec/unit/indirector/instrumentation_probe/local_spec.rb +65 -0
  127. data/spec/unit/indirector/instrumentation_probe/rest_spec.rb +11 -0
  128. data/spec/unit/module_spec.rb +39 -125
  129. data/spec/unit/module_tool/uninstaller_spec.rb +44 -0
  130. data/spec/unit/network/server_spec.rb +2 -20
  131. data/spec/unit/node/environment_spec.rb +76 -58
  132. data/spec/unit/parser/ast/asthash_spec.rb +1 -2
  133. data/spec/unit/parser/ast/leaf_spec.rb +16 -0
  134. data/spec/unit/property/keyvalue_spec.rb +5 -2
  135. data/spec/unit/property_spec.rb +260 -159
  136. data/spec/unit/provider/augeas/augeas_spec.rb +2 -2
  137. data/spec/unit/provider/group/pw_spec.rb +81 -0
  138. data/spec/unit/provider/nameservice/directoryservice_spec.rb +102 -0
  139. data/spec/unit/provider/package/pip_spec.rb +7 -0
  140. data/spec/unit/provider/package/yum_spec.rb +45 -1
  141. data/spec/unit/provider/service/debian_spec.rb +15 -0
  142. data/spec/unit/provider/service/launchd_spec.rb +48 -43
  143. data/spec/unit/provider/service/smf_spec.rb +3 -3
  144. data/spec/unit/provider/user/pw_spec.rb +183 -0
  145. data/spec/unit/provider/user/user_role_add_spec.rb +46 -39
  146. data/spec/unit/provider/user/windows_adsi_spec.rb +1 -0
  147. data/spec/unit/provider_spec.rb +32 -0
  148. data/spec/unit/reports/store_spec.rb +19 -1
  149. data/spec/unit/simple_graph_spec.rb +34 -19
  150. data/spec/unit/ssl/certificate_factory_spec.rb +3 -3
  151. data/spec/unit/transaction/report_spec.rb +29 -1
  152. data/spec/unit/transaction_spec.rb +32 -46
  153. data/spec/unit/type/file/mode_spec.rb +1 -1
  154. data/spec/unit/type/file/source_spec.rb +28 -3
  155. data/spec/unit/type/file_spec.rb +17 -16
  156. data/spec/unit/type/host_spec.rb +527 -0
  157. data/spec/unit/type/k5login_spec.rb +115 -0
  158. data/spec/unit/type/schedule_spec.rb +6 -6
  159. data/spec/unit/type_spec.rb +51 -0
  160. data/spec/unit/util/anonymous_filelock_spec.rb +78 -0
  161. data/spec/unit/util/execution_stub_spec.rb +2 -1
  162. data/spec/unit/util/instrumentation/data_spec.rb +44 -0
  163. data/spec/unit/util/instrumentation/indirection_probe_spec.rb +19 -0
  164. data/spec/unit/util/instrumentation/instrumentable_spec.rb +186 -0
  165. data/spec/unit/util/instrumentation/listener_spec.rb +100 -0
  166. data/spec/unit/util/instrumentation/listeners/log_spec.rb +34 -0
  167. data/spec/unit/util/instrumentation/listeners/performance_spec.rb +36 -0
  168. data/spec/unit/util/instrumentation_spec.rb +181 -0
  169. data/spec/unit/util/pidlock_spec.rb +208 -0
  170. data/spec/unit/util/rdoc/parser_spec.rb +1 -1
  171. data/spec/unit/util/reference_spec.rb +16 -6
  172. data/spec/unit/util/retryaction_spec.rb +62 -0
  173. data/spec/unit/util/suidmanager_spec.rb +101 -83
  174. data/spec/unit/util/symbolic_file_mode_spec.rb +182 -0
  175. data/spec/unit/util_spec.rb +126 -0
  176. data/tasks/rake/apple.rake +176 -0
  177. data/tasks/rake/templates/prototype.plist.erb +38 -0
  178. metadata +61 -13
  179. data/lib/puppet/application/module.rb +0 -3
  180. data/lib/puppet/face/module.rb +0 -12
  181. data/spec/unit/face/module/build_spec.rb +0 -30
  182. data/spec/unit/face/module/changes_spec.rb +0 -30
  183. data/spec/unit/face/module/clean_spec.rb +0 -30
  184. data/spec/unit/face/module/generate_spec.rb +0 -30
  185. data/spec/unit/face/module/install_spec.rb +0 -75
  186. data/spec/unit/face/module/search_spec.rb +0 -40
  187. 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
@@ -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
- validate do |value|
11
- unless value =~ /^((([0-9a-fA-F]+:){7}[0-9a-fA-F]+)|(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?::(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?)|((25[0-5]|2[0-4][\d]|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})$/
12
- raise Puppet::Error, "Invalid IP address"
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.
@@ -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.secure_open(@resource[:name], "w") do |f|
83
- f.puts value.join("\n")
83
+ Puppet::Util.replace_file(@resource[:name], 0644) do |f|
84
+ f.puts value
84
85
  end
85
86
  end
86
87
  end
@@ -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
@@ -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.change_group(arguments[:gid], true) if arguments[:gid]
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
@@ -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