puppet 0.24.1 → 0.24.2

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 (266) hide show
  1. data/CHANGELOG +94 -0
  2. data/Rakefile +0 -4
  3. data/bin/puppet +18 -10
  4. data/bin/puppetd +1 -1
  5. data/bin/puppetdoc +14 -4
  6. data/bin/puppetmasterd +1 -1
  7. data/bin/puppetrun +3 -8
  8. data/bin/ralsh +12 -11
  9. data/conf/freebsd/puppetd +1 -1
  10. data/conf/freebsd/puppetmasterd +1 -1
  11. data/conf/gentoo/puppet/puppet.conf +29 -0
  12. data/conf/namespaceauth.conf +20 -0
  13. data/conf/redhat/puppet.spec +4 -1
  14. data/conf/solaris/smf/puppetd.xml +1 -1
  15. data/conf/solaris/smf/puppetmasterd.xml +1 -1
  16. data/conf/suse/puppet.spec +10 -8
  17. data/examples/root/etc/puppet/{puppetmasterd.conf → puppet.conf} +6 -3
  18. data/ext/logcheck/puppet +7 -0
  19. data/ext/puppet-test +28 -5
  20. data/lib/puppet.rb +2 -1
  21. data/lib/puppet/defaults.rb +12 -5
  22. data/lib/puppet/dsl.rb +43 -45
  23. data/lib/puppet/external/{gratr/rdot.rb → dot.rb} +0 -0
  24. data/lib/puppet/external/nagios.rb +50 -0
  25. data/lib/puppet/external/nagios/base.rb +421 -0
  26. data/lib/puppet/external/nagios/parser.rb +816 -0
  27. data/lib/puppet/file_serving/file_base.rb +16 -3
  28. data/lib/puppet/file_serving/metadata.rb +29 -11
  29. data/lib/puppet/indirector/terminus.rb +1 -0
  30. data/lib/puppet/metatype/closure.rb +4 -0
  31. data/lib/puppet/metatype/evaluation.rb +2 -17
  32. data/lib/puppet/metatype/metaparams.rb +1 -1
  33. data/lib/puppet/network.rb +3 -0
  34. data/lib/puppet/network/client.rb +4 -5
  35. data/lib/puppet/network/client/master.rb +10 -7
  36. data/lib/puppet/network/handler/fileserver.rb +22 -45
  37. data/lib/puppet/network/http_pool.rb +3 -0
  38. data/lib/puppet/network/http_server/mongrel.rb +7 -1
  39. data/lib/puppet/network/http_server/webrick.rb +4 -3
  40. data/lib/puppet/network/xmlrpc/client.rb +12 -1
  41. data/lib/puppet/node/catalog.rb +51 -40
  42. data/lib/puppet/parser/ast.rb +27 -49
  43. data/lib/puppet/parser/ast/astarray.rb +5 -24
  44. data/lib/puppet/parser/ast/caseopt.rb +4 -4
  45. data/lib/puppet/parser/ast/casestatement.rb +4 -5
  46. data/lib/puppet/parser/ast/collection.rb +3 -5
  47. data/lib/puppet/parser/ast/collexpr.rb +3 -5
  48. data/lib/puppet/parser/ast/definition.rb +148 -159
  49. data/lib/puppet/parser/ast/else.rb +2 -3
  50. data/lib/puppet/parser/ast/function.rb +3 -10
  51. data/lib/puppet/parser/ast/hostclass.rb +66 -59
  52. data/lib/puppet/parser/ast/ifstatement.rb +4 -5
  53. data/lib/puppet/parser/ast/leaf.rb +6 -6
  54. data/lib/puppet/parser/ast/node.rb +26 -58
  55. data/lib/puppet/parser/ast/resource.rb +5 -7
  56. data/lib/puppet/parser/ast/resource_defaults.rb +2 -4
  57. data/lib/puppet/parser/ast/resource_override.rb +4 -6
  58. data/lib/puppet/parser/ast/resource_reference.rb +2 -4
  59. data/lib/puppet/parser/ast/resourceparam.rb +2 -4
  60. data/lib/puppet/parser/ast/selector.rb +5 -6
  61. data/lib/puppet/parser/ast/tag.rb +2 -4
  62. data/lib/puppet/parser/ast/vardef.rb +3 -4
  63. data/lib/puppet/parser/collector.rb +5 -5
  64. data/lib/puppet/parser/{compile.rb → compiler.rb} +69 -107
  65. data/lib/puppet/parser/functions.rb +3 -3
  66. data/lib/puppet/parser/interpreter.rb +32 -23
  67. data/lib/puppet/parser/lexer.rb +391 -282
  68. data/lib/puppet/parser/parser.rb +5 -4
  69. data/lib/puppet/parser/parser_support.rb +3 -6
  70. data/lib/puppet/parser/resource.rb +24 -36
  71. data/lib/puppet/parser/resource/param.rb +1 -1
  72. data/lib/puppet/parser/resource/reference.rb +7 -3
  73. data/lib/puppet/parser/scope.rb +12 -7
  74. data/lib/puppet/parser/templatewrapper.rb +1 -1
  75. data/lib/puppet/pgraph.rb +9 -98
  76. data/lib/puppet/provider/interface/redhat.rb +65 -65
  77. data/lib/puppet/provider/mount/parsed.rb +1 -1
  78. data/lib/puppet/provider/naginator.rb +55 -0
  79. data/lib/puppet/provider/nameservice/directoryservice.rb +6 -7
  80. data/lib/puppet/provider/package/fink.rb +0 -2
  81. data/lib/puppet/provider/package/gem.rb +9 -5
  82. data/lib/puppet/provider/package/openbsd.rb +1 -1
  83. data/lib/puppet/provider/package/pkgdmg.rb +3 -8
  84. data/lib/puppet/provider/package/portage.rb +4 -4
  85. data/lib/puppet/provider/package/yumhelper.py +8 -6
  86. data/lib/puppet/provider/parsedfile.rb +7 -1
  87. data/lib/puppet/provider/service/debian.rb +2 -0
  88. data/lib/puppet/provider/service/gentoo.rb +4 -0
  89. data/lib/puppet/provider/service/init.rb +1 -1
  90. data/lib/puppet/provider/sshkey/parsed.rb +2 -0
  91. data/lib/puppet/provider/user/useradd.rb +1 -1
  92. data/lib/puppet/rails.rb +4 -0
  93. data/lib/puppet/rails/database/001_add_created_at_to_all_tables.rb +17 -0
  94. data/lib/puppet/rails/fact_value.rb +4 -0
  95. data/lib/puppet/rails/host.rb +1 -2
  96. data/lib/puppet/rails/param_value.rb +4 -0
  97. data/lib/puppet/rails/resource_tag.rb +4 -0
  98. data/lib/puppet/rails/source_file.rb +4 -1
  99. data/lib/puppet/relationship.rb +5 -1
  100. data/lib/puppet/reports/tagmail.rb +12 -1
  101. data/lib/puppet/resource_reference.rb +1 -1
  102. data/lib/puppet/simple_graph.rb +78 -11
  103. data/lib/puppet/sslcertificates.rb +1 -1
  104. data/lib/puppet/sslcertificates/ca.rb +3 -3
  105. data/lib/puppet/transaction.rb +7 -4
  106. data/lib/puppet/transportable.rb +1 -1
  107. data/lib/puppet/type.rb +3 -10
  108. data/lib/puppet/type/cron.rb +18 -0
  109. data/lib/puppet/type/exec.rb +18 -12
  110. data/lib/puppet/type/{pfile.rb → file.rb} +66 -84
  111. data/lib/puppet/type/file/checksum.rb +271 -0
  112. data/lib/puppet/type/{pfile → file}/content.rb +10 -15
  113. data/lib/puppet/type/{pfile → file}/ensure.rb +15 -8
  114. data/lib/puppet/type/{pfile → file}/group.rb +0 -0
  115. data/lib/puppet/type/{pfile → file}/mode.rb +0 -0
  116. data/lib/puppet/type/{pfile → file}/owner.rb +0 -0
  117. data/lib/puppet/type/{pfile → file}/source.rb +34 -48
  118. data/lib/puppet/type/{pfile → file}/target.rb +0 -0
  119. data/lib/puppet/type/{pfile → file}/type.rb +0 -0
  120. data/lib/puppet/type/{pfilebucket.rb → filebucket.rb} +0 -0
  121. data/lib/puppet/type/host.rb +13 -0
  122. data/lib/puppet/type/mailalias.rb +1 -1
  123. data/lib/puppet/type/nagios_command.rb +3 -0
  124. data/lib/puppet/type/nagios_contact.rb +3 -0
  125. data/lib/puppet/type/nagios_contactgroup.rb +3 -0
  126. data/lib/puppet/type/nagios_host.rb +3 -0
  127. data/lib/puppet/type/nagios_hostextinfo.rb +3 -0
  128. data/lib/puppet/type/nagios_hostgroup.rb +3 -0
  129. data/lib/puppet/type/nagios_hostgroupescalation.rb +3 -0
  130. data/lib/puppet/type/nagios_service.rb +3 -0
  131. data/lib/puppet/type/nagios_servicedependency.rb +3 -0
  132. data/lib/puppet/type/nagios_serviceescalation.rb +3 -0
  133. data/lib/puppet/type/nagios_serviceextinfo.rb +3 -0
  134. data/lib/puppet/type/nagios_timeperiod.rb +3 -0
  135. data/lib/puppet/type/package.rb +4 -12
  136. data/lib/puppet/type/service.rb +9 -0
  137. data/lib/puppet/type/sshkey.rb +3 -3
  138. data/lib/puppet/util/autoload.rb +5 -5
  139. data/lib/puppet/util/checksums.rb +51 -13
  140. data/lib/puppet/util/constant_inflector.rb +14 -0
  141. data/lib/puppet/util/filetype.rb +1 -1
  142. data/lib/puppet/util/graph.rb +3 -9
  143. data/lib/puppet/util/nagios_maker.rb +57 -0
  144. data/lib/puppet/util/settings.rb +19 -16
  145. data/lib/puppet/util/tagging.rb +39 -0
  146. data/test/executables/puppetbin.rb +17 -0
  147. data/test/language/ast.rb +8 -58
  148. data/test/language/ast/casestatement.rb +3 -3
  149. data/test/language/ast/resource.rb +6 -7
  150. data/test/language/ast/resource_reference.rb +12 -12
  151. data/test/language/ast/selector.rb +2 -2
  152. data/test/language/ast/variable.rb +2 -2
  153. data/test/language/functions.rb +24 -24
  154. data/test/language/parser.rb +20 -8
  155. data/test/language/resource.rb +5 -42
  156. data/test/language/scope.rb +21 -37
  157. data/test/language/snippets.rb +7 -0
  158. data/test/lib/puppettest.rb +28 -14
  159. data/test/lib/puppettest/parsertesting.rb +10 -10
  160. data/test/lib/puppettest/support/resources.rb +1 -1
  161. data/test/network/client/master.rb +10 -0
  162. data/test/network/handler/fileserver.rb +51 -49
  163. data/test/network/server/webrick.rb +1 -1
  164. data/test/other/dsl.rb +3 -4
  165. data/test/other/transactions.rb +6 -4
  166. data/test/rails/ast.rb +2 -2
  167. data/test/rails/configuration.rb +1 -1
  168. data/test/rails/railsparameter.rb +2 -0
  169. data/test/rails/railsresource.rb +1 -0
  170. data/test/ral/manager/type.rb +4 -4
  171. data/test/ral/providers/cron/crontab.rb +3 -1
  172. data/test/ral/providers/package.rb +1 -1
  173. data/test/ral/{types → type}/basic.rb +2 -2
  174. data/test/ral/{types → type}/cron.rb +0 -0
  175. data/test/ral/{types → type}/exec.rb +42 -2
  176. data/test/ral/{types → type}/file.rb +34 -79
  177. data/test/ral/{types → type}/file/target.rb +0 -0
  178. data/test/ral/{types → type}/filebucket.rb +0 -0
  179. data/test/ral/{types → type}/fileignoresource.rb +0 -0
  180. data/test/ral/{types → type}/filesources.rb +8 -27
  181. data/test/ral/{types → type}/group.rb +0 -0
  182. data/test/ral/{types → type}/host.rb +16 -0
  183. data/test/ral/{types → type}/mailalias.rb +0 -0
  184. data/test/ral/{types → type}/parameter.rb +0 -0
  185. data/test/ral/{types → type}/port.rb +0 -0
  186. data/test/ral/{types → type}/property.rb +0 -0
  187. data/test/ral/{types → type}/resources.rb +0 -0
  188. data/test/ral/{types → type}/service.rb +0 -0
  189. data/test/ral/{types → type}/sshkey.rb +0 -0
  190. data/test/ral/{types → type}/tidy.rb +1 -0
  191. data/test/ral/{types → type}/user.rb +0 -0
  192. data/test/ral/{types → type}/yumrepo.rb +0 -0
  193. data/test/ral/{types → type}/zone.rb +0 -0
  194. data/test/util/autoload.rb +24 -5
  195. metadata +60 -107
  196. data/conf/gentoo/puppet/puppetca.conf +0 -29
  197. data/conf/gentoo/puppet/puppetd.conf +0 -29
  198. data/conf/gentoo/puppet/puppetmasterd.conf +0 -29
  199. data/examples/root/etc/puppet/puppetd.conf +0 -4
  200. data/lib/puppet/external/gratr.rb +0 -33
  201. data/lib/puppet/external/gratr/adjacency_graph.rb +0 -257
  202. data/lib/puppet/external/gratr/base.rb +0 -34
  203. data/lib/puppet/external/gratr/biconnected.rb +0 -116
  204. data/lib/puppet/external/gratr/chinese_postman.rb +0 -123
  205. data/lib/puppet/external/gratr/common.rb +0 -73
  206. data/lib/puppet/external/gratr/comparability.rb +0 -92
  207. data/lib/puppet/external/gratr/digraph.rb +0 -116
  208. data/lib/puppet/external/gratr/digraph_distance.rb +0 -185
  209. data/lib/puppet/external/gratr/dot.rb +0 -90
  210. data/lib/puppet/external/gratr/edge.rb +0 -145
  211. data/lib/puppet/external/gratr/graph.rb +0 -303
  212. data/lib/puppet/external/gratr/graph_api.rb +0 -83
  213. data/lib/puppet/external/gratr/import.rb +0 -44
  214. data/lib/puppet/external/gratr/labels.rb +0 -90
  215. data/lib/puppet/external/gratr/maximum_flow.rb +0 -64
  216. data/lib/puppet/external/gratr/search.rb +0 -409
  217. data/lib/puppet/external/gratr/strong_components.rb +0 -127
  218. data/lib/puppet/external/gratr/undirected_graph.rb +0 -153
  219. data/lib/puppet/rails/external/tagging/acts_as_taggable.rb +0 -62
  220. data/lib/puppet/rails/external/tagging/init.rb +0 -5
  221. data/lib/puppet/rails/external/tagging/tag.rb +0 -50
  222. data/lib/puppet/rails/external/tagging/tagging.rb +0 -12
  223. data/lib/puppet/rails/puppet_class.rb +0 -6
  224. data/lib/puppet/reference/node_source.rb +0 -9
  225. data/lib/puppet/reference/report.rb +0 -21
  226. data/lib/puppet/type/pfile/checksum.rb +0 -326
  227. data/test/language/ast/definition.rb +0 -166
  228. data/test/language/ast/hostclass.rb +0 -184
  229. data/test/language/compile.rb +0 -569
  230. data/test/language/lexer.rb +0 -276
  231. data/test/lib/mocha.rb +0 -19
  232. data/test/lib/mocha/any_instance_method.rb +0 -35
  233. data/test/lib/mocha/auto_verify.rb +0 -113
  234. data/test/lib/mocha/central.rb +0 -35
  235. data/test/lib/mocha/class_method.rb +0 -62
  236. data/test/lib/mocha/deprecation.rb +0 -22
  237. data/test/lib/mocha/exception_raiser.rb +0 -17
  238. data/test/lib/mocha/expectation.rb +0 -378
  239. data/test/lib/mocha/expectation_error.rb +0 -6
  240. data/test/lib/mocha/infinite_range.rb +0 -25
  241. data/test/lib/mocha/inspect.rb +0 -39
  242. data/test/lib/mocha/instance_method.rb +0 -8
  243. data/test/lib/mocha/is_a.rb +0 -9
  244. data/test/lib/mocha/metaclass.rb +0 -7
  245. data/test/lib/mocha/missing_expectation.rb +0 -27
  246. data/test/lib/mocha/mock.rb +0 -207
  247. data/test/lib/mocha/multiple_yields.rb +0 -20
  248. data/test/lib/mocha/no_yields.rb +0 -11
  249. data/test/lib/mocha/object.rb +0 -110
  250. data/test/lib/mocha/parameter_matchers.rb +0 -9
  251. data/test/lib/mocha/parameter_matchers/all_of.rb +0 -39
  252. data/test/lib/mocha/parameter_matchers/any_of.rb +0 -44
  253. data/test/lib/mocha/parameter_matchers/anything.rb +0 -30
  254. data/test/lib/mocha/parameter_matchers/has_entry.rb +0 -39
  255. data/test/lib/mocha/parameter_matchers/has_key.rb +0 -39
  256. data/test/lib/mocha/parameter_matchers/has_value.rb +0 -39
  257. data/test/lib/mocha/parameter_matchers/includes.rb +0 -37
  258. data/test/lib/mocha/pretty_parameters.rb +0 -28
  259. data/test/lib/mocha/return_values.rb +0 -31
  260. data/test/lib/mocha/setup_and_teardown.rb +0 -23
  261. data/test/lib/mocha/single_return_value.rb +0 -24
  262. data/test/lib/mocha/single_yield.rb +0 -18
  263. data/test/lib/mocha/standalone.rb +0 -32
  264. data/test/lib/mocha/stub.rb +0 -18
  265. data/test/lib/mocha/test_case_adapter.rb +0 -49
  266. data/test/lib/mocha/yield_parameters.rb +0 -31
@@ -211,10 +211,7 @@ module Puppet
211
211
  log the output when the command reports an error. Values are
212
212
  **true**, *false*, *on_failure*, and any legal log level."
213
213
 
214
- values = [:true, :false, :on_failure]
215
- # And all of the log levels
216
- Puppet::Util::Log.eachlevel { |level| values << level }
217
- newvalues(*values)
214
+ newvalues(:true, :false, :on_failure)
218
215
  end
219
216
 
220
217
  newparam(:refresh) do
@@ -229,6 +226,15 @@ module Puppet
229
226
  end
230
227
 
231
228
  newparam(:env) do
229
+ desc "This parameter is deprecated. Use 'environment' instead."
230
+
231
+ munge do |value|
232
+ warning "'env' is deprecated on exec; use 'environment' instead."
233
+ resource[:environment] = value
234
+ end
235
+ end
236
+
237
+ newparam(:environment) do
232
238
  desc "Any additional environment variables you want to set for a
233
239
  command. Note that if you use this to set PATH, it will override
234
240
  the ``path`` attribute. Multiple environment variables should be
@@ -279,7 +285,7 @@ module Puppet
279
285
  # Rebuild the database, but only when the file changes
280
286
  exec { newaliases:
281
287
  path => [\"/usr/bin\", \"/usr/sbin\"],
282
- subscribe => file[\"/etc/aliases\"],
288
+ subscribe => File[\"/etc/aliases\"],
283
289
  refreshonly => true
284
290
  }
285
291
 
@@ -554,32 +560,32 @@ module Puppet
554
560
  begin
555
561
  # Do our chdir
556
562
  Dir.chdir(dir) do
557
- env = {}
563
+ environment = {}
558
564
 
559
565
  if self[:path]
560
- env[:PATH] = self[:path].join(":")
566
+ environment[:PATH] = self[:path].join(":")
561
567
  end
562
568
 
563
- if envlist = self[:env]
569
+ if envlist = self[:environment]
564
570
  envlist = [envlist] unless envlist.is_a? Array
565
571
  envlist.each do |setting|
566
572
  if setting =~ /^(\w+)=((.|\n)+)$/
567
573
  name = $1
568
574
  value = $2
569
- if env.include? name
575
+ if environment.include? name
570
576
  warning(
571
577
  "Overriding environment setting '%s' with '%s'" %
572
578
  [name, value]
573
579
  )
574
580
  end
575
- env[name] = value
581
+ environment[name] = value
576
582
  else
577
- warning "Cannot understand env setting %s" % setting.inspect
583
+ warning "Cannot understand environment setting %s" % setting.inspect
578
584
  end
579
585
  end
580
586
  end
581
587
 
582
- withenv env do
588
+ withenv environment do
583
589
  Timeout::timeout(self[:timeout]) do
584
590
  output, status = Puppet::Util::SUIDManager.run_and_capture(
585
591
  [command], self[:user], self[:group]
@@ -5,10 +5,12 @@ require 'uri'
5
5
  require 'fileutils'
6
6
  require 'puppet/network/handler'
7
7
  require 'puppet/util/diff'
8
+ require 'puppet/util/checksums'
8
9
 
9
10
  module Puppet
10
11
  newtype(:file) do
11
12
  include Puppet::Util::MethodHelper
13
+ include Puppet::Util::Checksums
12
14
  @doc = "Manages local files, including setting ownership and
13
15
  permissions, creation of both files and directories, and
14
16
  retrieving entire files from remote servers. As Puppet matures, it
@@ -173,11 +175,9 @@ module Puppet
173
175
  recursion), and ``follow`` will manage the file to which the
174
176
  link points."
175
177
 
176
- newvalues(:follow, :manage, :ignore)
178
+ newvalues(:follow, :manage)
177
179
 
178
- # :ignore and :manage behave equivalently on local files,
179
- # but don't copy remote links
180
- defaultto :ignore
180
+ defaultto :manage
181
181
  end
182
182
 
183
183
  newparam(:purge, :boolean => true) do
@@ -460,7 +460,9 @@ module Puppet
460
460
  super
461
461
 
462
462
  # Get rid of any duplicate slashes, and remove any trailing slashes.
463
- @title = @title.gsub(/\/+/, "/").sub(/\/$/, "")
463
+ @title = @title.gsub(/\/+/, "/")
464
+
465
+ @title.sub!(/\/$/, "") unless @title == "/"
464
466
 
465
467
  # Clean out as many references to any file paths as possible.
466
468
  # This was the source of many, many bugs.
@@ -640,7 +642,6 @@ module Puppet
640
642
  # :file.
641
643
  return nil unless child = catalog.create_implicit_resource(self.class.name, args)
642
644
  rescue => detail
643
- puts detail.backtrace
644
645
  self.notice "Cannot manage: %s" % [detail]
645
646
  return nil
646
647
  end
@@ -648,7 +649,7 @@ module Puppet
648
649
 
649
650
  # LAK:FIXME This shouldn't be necessary, but as long as we're
650
651
  # modeling the relationship graph specifically, it is.
651
- catalog.relationship_graph.add_edge! self, child
652
+ catalog.relationship_graph.add_edge self, child
652
653
 
653
654
  return child
654
655
  end
@@ -767,11 +768,8 @@ module Puppet
767
768
  begin
768
769
  File.unlink(newfile)
769
770
  rescue => detail
770
- if Puppet[:trace]
771
- puts detail.backtrace
772
- end
773
- self.err "Could not remove old backup: %s" %
774
- detail
771
+ puts detail.backtrace if Puppet[:trace]
772
+ self.err "Could not remove old backup: %s" % detail
775
773
  return false
776
774
  end
777
775
  end
@@ -781,9 +779,7 @@ module Puppet
781
779
  def remove_existing(should)
782
780
  return unless s = stat(true)
783
781
 
784
- unless handlebackup
785
- self.fail "Could not back up; will not replace"
786
- end
782
+ self.fail "Could not back up; will not replace" unless handlebackup
787
783
 
788
784
  unless should.to_s == "link"
789
785
  return if s.ftype.to_s == should.to_s
@@ -792,8 +788,7 @@ module Puppet
792
788
  case s.ftype
793
789
  when "directory":
794
790
  if self[:force] == :true
795
- debug "Removing existing directory for replacement with %s" %
796
- should
791
+ debug "Removing existing directory for replacement with %s" % should
797
792
  FileUtils.rmtree(self[:path])
798
793
  else
799
794
  notice "Not removing directory; use 'force' to override"
@@ -977,7 +972,7 @@ module Puppet
977
972
  end
978
973
 
979
974
  def uri2obj(source)
980
- sourceobj = FileSource.new
975
+ sourceobj = Puppet::Type::File::FileSource.new
981
976
  path = nil
982
977
  unless source
983
978
  devfail "Got a nil source"
@@ -1033,54 +1028,38 @@ module Puppet
1033
1028
  return [sourceobj, path.sub(/\/\//, '/')]
1034
1029
  end
1035
1030
 
1036
- # Write out the file. We open the file correctly, with all of the
1037
- # uid and mode and such, and then yield the file handle for actual
1038
- # writing.
1039
- def write(property, usetmp = true)
1040
- mode = self.should(:mode)
1031
+ # Write out the file. Requires the content to be written,
1032
+ # the property name for logging, and the checksum for validation.
1033
+ def write(content, property, checksum = nil)
1034
+ if validate = validate_checksum?
1035
+ # Use the appropriate checksum type -- md5, md5lite, etc.
1036
+ sumtype = property(:checksum).checktype
1037
+ checksum ||= "{#{sumtype}}" + property(:checksum).send(sumtype, content)
1038
+ end
1041
1039
 
1042
1040
  remove_existing(:file)
1043
1041
 
1044
- # The temporary file
1045
- path = nil
1046
- if usetmp
1047
- path = self[:path] + ".puppettmp"
1048
- else
1049
- path = self[:path]
1050
- end
1051
-
1052
- # As the correct user and group
1053
- write_if_writable(File.dirname(path)) do
1054
- f = nil
1055
- # Open our file with the correct modes
1056
- if mode
1057
- Puppet::Util.withumask(000) do
1058
- f = File.open(path,
1059
- File::CREAT|File::WRONLY|File::TRUNC, mode)
1060
- end
1061
- else
1062
- f = File.open(path, File::CREAT|File::WRONLY|File::TRUNC)
1063
- end
1042
+ use_temporary_file = (content.length != 0)
1043
+ path = self[:path]
1044
+ path += ".puppettmp" if use_temporary_file
1064
1045
 
1065
- # Yield it
1066
- yield f
1046
+ mode = self.should(:mode) # might be nil
1047
+ umask = mode ? 000 : 022
1067
1048
 
1068
- f.flush
1069
- f.close
1049
+ Puppet::Util.withumask(umask) do
1050
+ File.open(path, File::CREAT|File::WRONLY|File::TRUNC, mode) { |f| f.print content }
1070
1051
  end
1071
1052
 
1072
1053
  # And put our new file in place
1073
- if usetmp
1054
+ if use_temporary_file # This is only not true when our file is empty.
1074
1055
  begin
1056
+ fail_if_checksum_is_wrong(path, checksum) if validate
1075
1057
  File.rename(path, self[:path])
1076
1058
  rescue => detail
1077
- self.err "Could not rename tmp %s for replacing: %s" %
1078
- [self[:path], detail]
1059
+ self.err "Could not rename tmp %s for replacing: %s" % [self[:path], detail]
1079
1060
  ensure
1080
1061
  # Make sure the created file gets removed
1081
- if FileTest.exists?(path)
1082
- File.unlink(path)
1083
- end
1062
+ File.unlink(path) if FileTest.exists?(path)
1084
1063
  end
1085
1064
  end
1086
1065
 
@@ -1088,32 +1067,35 @@ module Puppet
1088
1067
  property_fix
1089
1068
 
1090
1069
  # And then update our checksum, so the next run doesn't find it.
1091
- # FIXME This is extra work, because it's going to read the whole
1092
- # file back in again.
1093
- self.setchecksum
1094
-
1070
+ self.setchecksum(checksum)
1095
1071
  end
1096
-
1097
- # Run the block as the specified user if the dir is writeable, else
1098
- # run it as root (or the current user).
1099
- def write_if_writable(dir)
1100
- yield
1101
- # We're getting different behaviors from different versions of ruby, so...
1102
- # asroot = true
1103
- # Puppet::Util::SUIDManager.asuser(asuser(), self.should(:group)) do
1104
- # if FileTest.writable?(dir)
1105
- # asroot = false
1106
- # yield
1107
- # end
1108
- # end
1109
- #
1110
- # if asroot
1111
- # yield
1112
- # end
1072
+
1073
+ # Should we validate the checksum of the file we're writing?
1074
+ def validate_checksum?
1075
+ if sumparam = @parameters[:checksum]
1076
+ return sumparam.checktype.to_s !~ /time/
1077
+ else
1078
+ return false
1079
+ end
1113
1080
  end
1114
1081
 
1115
1082
  private
1116
1083
 
1084
+ # Make sure the file we wrote out is what we think it is.
1085
+ def fail_if_checksum_is_wrong(path, checksum)
1086
+ if checksum =~ /^\{(\w+)\}.+/
1087
+ sumtype = $1
1088
+ else
1089
+ # This shouldn't happen, but if it happens to, it's nicer
1090
+ # to just use a default sumtype than fail.
1091
+ sumtype = "md5"
1092
+ end
1093
+ newsum = property(:checksum).getsum(sumtype, path)
1094
+ return if newsum == checksum
1095
+
1096
+ self.fail "File written to disk did not match checksum; discarding changes (%s vs %s)" % [checksum, newsum]
1097
+ end
1098
+
1117
1099
  # Override the parent method, because we don't want to generate changes
1118
1100
  # when the file is missing and there is no 'ensure' state.
1119
1101
  def propertychanges(currentvalues)
@@ -1150,20 +1132,20 @@ module Puppet
1150
1132
 
1151
1133
  # the filesource class can't include the path, because the path
1152
1134
  # changes for every file instance
1153
- class FileSource
1135
+ class ::Puppet::Type::File::FileSource
1154
1136
  attr_accessor :mount, :root, :server, :local
1155
1137
  end
1156
1138
 
1157
1139
  # We put all of the properties in separate files, because there are so many
1158
1140
  # of them. The order these are loaded is important, because it determines
1159
1141
  # the order they are in the property lit.
1160
- require 'puppet/type/pfile/checksum'
1161
- require 'puppet/type/pfile/content' # can create the file
1162
- require 'puppet/type/pfile/source' # can create the file
1163
- require 'puppet/type/pfile/target' # creates a different type of file
1164
- require 'puppet/type/pfile/ensure' # can create the file
1165
- require 'puppet/type/pfile/owner'
1166
- require 'puppet/type/pfile/group'
1167
- require 'puppet/type/pfile/mode'
1168
- require 'puppet/type/pfile/type'
1142
+ require 'puppet/type/file/checksum'
1143
+ require 'puppet/type/file/content' # can create the file
1144
+ require 'puppet/type/file/source' # can create the file
1145
+ require 'puppet/type/file/target' # creates a different type of file
1146
+ require 'puppet/type/file/ensure' # can create the file
1147
+ require 'puppet/type/file/owner'
1148
+ require 'puppet/type/file/group'
1149
+ require 'puppet/type/file/mode'
1150
+ require 'puppet/type/file/type'
1169
1151
  end
@@ -0,0 +1,271 @@
1
+ require 'puppet/util/checksums'
2
+
3
+ # Keep a copy of the file checksums, and notify when they change. This
4
+ # property never actually modifies the system, it only notices when the system
5
+ # changes on its own.
6
+ Puppet::Type.type(:file).newproperty(:checksum) do
7
+ include Puppet::Util::Checksums
8
+
9
+ desc "How to check whether a file has changed. This state is used internally
10
+ for file copying, but it can also be used to monitor files somewhat
11
+ like Tripwire without managing the file contents in any way. You can
12
+ specify that a file's checksum should be monitored and then subscribe to
13
+ the file from another object and receive events to signify
14
+ checksum changes, for instance."
15
+
16
+ @event = :file_changed
17
+
18
+ @unmanaged = true
19
+
20
+ @validtypes = %w{md5 md5lite timestamp mtime time}
21
+
22
+ def self.validtype?(type)
23
+ @validtypes.include?(type)
24
+ end
25
+
26
+ @validtypes.each do |ctype|
27
+ newvalue(ctype) do
28
+ handlesum()
29
+ end
30
+ end
31
+
32
+ str = @validtypes.join("|")
33
+
34
+ # This is here because Puppet sets this internally, using
35
+ # {md5}......
36
+ newvalue(/^\{#{str}\}/) do
37
+ handlesum()
38
+ end
39
+
40
+ newvalue(:nosum) do
41
+ # nothing
42
+ :nochange
43
+ end
44
+
45
+ # If they pass us a sum type, behave normally, but if they pass
46
+ # us a sum type + sum, stick the sum in the cache.
47
+ munge do |value|
48
+ if value =~ /^\{(\w+)\}(.+)$/
49
+ type = symbolize($1)
50
+ sum = $2
51
+ cache(type, sum)
52
+ return type
53
+ else
54
+ if FileTest.directory?(@resource[:path])
55
+ return :time
56
+ else
57
+ return symbolize(value)
58
+ end
59
+ end
60
+ end
61
+
62
+ # Store the checksum in the data cache, or retrieve it if only the
63
+ # sum type is provided.
64
+ def cache(type, sum = nil)
65
+ unless type
66
+ raise ArgumentError, "A type must be specified to cache a checksum"
67
+ end
68
+ type = symbolize(type)
69
+ unless state = @resource.cached(:checksums)
70
+ self.debug "Initializing checksum hash"
71
+ state = {}
72
+ @resource.cache(:checksums, state)
73
+ end
74
+
75
+ if sum
76
+ unless sum =~ /\{\w+\}/
77
+ sum = "{%s}%s" % [type, sum]
78
+ end
79
+ state[type] = sum
80
+ else
81
+ return state[type]
82
+ end
83
+ end
84
+
85
+ # Because source and content and whomever else need to set the checksum
86
+ # and do the updating, we provide a simple mechanism for doing so.
87
+ def checksum=(value)
88
+ munge(@should)
89
+ self.updatesum(value)
90
+ end
91
+
92
+ def checktype
93
+ self.should || :md5
94
+ end
95
+
96
+ # Checksums need to invert how changes are printed.
97
+ def change_to_s(currentvalue, newvalue)
98
+ begin
99
+ if currentvalue == :absent
100
+ return "defined '%s' as '%s'" %
101
+ [self.name, self.currentsum]
102
+ elsif newvalue == :absent
103
+ return "undefined %s from '%s'" %
104
+ [self.name, self.is_to_s(currentvalue)]
105
+ else
106
+ if defined? @cached and @cached
107
+ return "%s changed '%s' to '%s'" %
108
+ [self.name, @cached, self.is_to_s(currentvalue)]
109
+ else
110
+ return "%s changed '%s' to '%s'" %
111
+ [self.name, self.currentsum, self.is_to_s(currentvalue)]
112
+ end
113
+ end
114
+ rescue Puppet::Error, Puppet::DevError
115
+ raise
116
+ rescue => detail
117
+ raise Puppet::DevError, "Could not convert change %s to string: %s" %
118
+ [self.name, detail]
119
+ end
120
+ end
121
+
122
+ def currentsum
123
+ cache(checktype())
124
+ end
125
+
126
+ # Retrieve the cached sum
127
+ def getcachedsum
128
+ hash = nil
129
+ unless hash = @resource.cached(:checksums)
130
+ hash = {}
131
+ @resource.cache(:checksums, hash)
132
+ end
133
+
134
+ sumtype = self.should
135
+
136
+ if hash.include?(sumtype)
137
+ #self.notice "Found checksum %s for %s" %
138
+ # [hash[sumtype] ,@resource[:path]]
139
+ sum = hash[sumtype]
140
+
141
+ unless sum =~ /^\{\w+\}/
142
+ sum = "{%s}%s" % [sumtype, sum]
143
+ end
144
+ return sum
145
+ elsif hash.empty?
146
+ #self.notice "Could not find sum of type %s" % sumtype
147
+ return :nosum
148
+ else
149
+ #self.notice "Found checksum for %s but not of type %s" %
150
+ # [@resource[:path],sumtype]
151
+ return :nosum
152
+ end
153
+ end
154
+
155
+ # Calculate the sum from disk.
156
+ def getsum(checktype, file = nil)
157
+ sum = ""
158
+
159
+ checktype = :mtime if checktype == :timestamp
160
+ checktype = :ctime if checktype == :time
161
+
162
+ file ||= @resource[:path]
163
+
164
+ return nil unless FileTest.exist?(file)
165
+
166
+ if ! FileTest.file?(file)
167
+ checktype = :mtime
168
+ end
169
+ method = checktype.to_s + "_file"
170
+
171
+ self.fail("Invalid checksum type %s" % checktype) unless respond_to?(method)
172
+
173
+ return "{%s}%s" % [checktype, send(method, file)]
174
+ end
175
+
176
+ # At this point, we don't actually modify the system, we modify
177
+ # the stored state to reflect the current state, and then kick
178
+ # off an event to mark any changes.
179
+ def handlesum
180
+ currentvalue = self.retrieve
181
+ if currentvalue.nil?
182
+ raise Puppet::Error, "Checksum state for %s is somehow nil" %
183
+ @resource.title
184
+ end
185
+
186
+ if self.insync?(currentvalue)
187
+ self.debug "Checksum is already in sync"
188
+ return nil
189
+ end
190
+ # If we still can't retrieve a checksum, it means that
191
+ # the file still doesn't exist
192
+ if currentvalue == :absent
193
+ # if they're copying, then we won't worry about the file
194
+ # not existing yet
195
+ unless @resource.property(:source)
196
+ self.warning("File %s does not exist -- cannot checksum" % @resource[:path])
197
+ end
198
+ return nil
199
+ end
200
+
201
+ # If the sums are different, then return an event.
202
+ if self.updatesum(currentvalue)
203
+ return :file_changed
204
+ else
205
+ return nil
206
+ end
207
+ end
208
+
209
+ def insync?(currentvalue)
210
+ @should = [checktype()]
211
+ if cache(checktype())
212
+ return currentvalue == currentsum()
213
+ else
214
+ # If there's no cached sum, then we don't want to generate
215
+ # an event.
216
+ return true
217
+ end
218
+ end
219
+
220
+ # Even though they can specify multiple checksums, the insync?
221
+ # mechanism can really only test against one, so we'll just retrieve
222
+ # the first specified sum type.
223
+ def retrieve(usecache = false)
224
+ # When the 'source' is retrieving, it passes "true" here so
225
+ # that we aren't reading the file twice in quick succession, yo.
226
+ currentvalue = currentsum()
227
+ return currentvalue if usecache and currentvalue
228
+
229
+ stat = nil
230
+ return :absent unless stat = @resource.stat
231
+
232
+ if stat.ftype == "link" and @resource[:links] != :follow
233
+ self.debug "Not checksumming symlink"
234
+ # @resource.delete(:checksum)
235
+ return currentvalue
236
+ end
237
+
238
+ # Just use the first allowed check type
239
+ currentvalue = getsum(checktype())
240
+
241
+ # If there is no sum defined, then store the current value
242
+ # into the cache, so that we're not marked as being
243
+ # out of sync. We don't want to generate an event the first
244
+ # time we get a sum.
245
+ self.updatesum(currentvalue) unless cache(checktype())
246
+
247
+ # @resource.debug "checksum state is %s" % self.is
248
+ return currentvalue
249
+ end
250
+
251
+ # Store the new sum to the state db.
252
+ def updatesum(newvalue)
253
+ result = false
254
+
255
+ # if we're replacing, vs. updating
256
+ if sum = cache(checktype())
257
+ return false if newvalue == sum
258
+
259
+ self.debug "Replacing %s checksum %s with %s" % [@resource.title, sum, newvalue]
260
+ result = true
261
+ else
262
+ @resource.debug "Creating checksum %s" % newvalue
263
+ result = false
264
+ end
265
+
266
+ # Cache the sum so the log message can be right if possible.
267
+ @cached = sum
268
+ cache(checktype(), newvalue)
269
+ return result
270
+ end
271
+ end