puppet 0.24.5 → 0.24.6

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 (354) hide show
  1. data/CHANGELOG +206 -0
  2. data/Rakefile +53 -0
  3. data/bin/filebucket +0 -0
  4. data/bin/puppet +32 -11
  5. data/bin/puppetca +1 -0
  6. data/bin/puppetd +0 -0
  7. data/bin/puppetdoc +0 -0
  8. data/bin/puppetmasterd +0 -0
  9. data/bin/puppetrun +16 -8
  10. data/bin/ralsh +0 -0
  11. data/conf/debian/rules +0 -0
  12. data/conf/gentoo/init.d/puppetmaster +0 -0
  13. data/conf/osx/PackageInfo.plist +36 -0
  14. data/conf/osx/createpackage.sh +167 -0
  15. data/conf/osx/preflight +12 -0
  16. data/conf/redhat/client.init +1 -1
  17. data/conf/redhat/puppet.spec +34 -6
  18. data/conf/redhat/server.init +42 -7
  19. data/conf/redhat/server.sysconfig +22 -0
  20. data/conf/solaris/smf/svc-puppetd +0 -0
  21. data/conf/solaris/smf/svc-puppetmasterd +0 -0
  22. data/examples/etc/init.d/sleeper +0 -0
  23. data/examples/mac_dscl.pp +0 -0
  24. data/examples/mac_dscl_revert.pp +0 -0
  25. data/examples/mac_netinfo.pp +0 -0
  26. data/examples/mac_pkgdmg.pp +0 -0
  27. data/ext/bin/sleeper +0 -0
  28. data/ext/module_puppet +0 -0
  29. data/ext/nagios/check_puppet.rb +0 -0
  30. data/ext/passenger/README +63 -0
  31. data/ext/passenger/apache2.conf +29 -0
  32. data/ext/passenger/config.ru +40 -0
  33. data/ext/puppet-test +0 -0
  34. data/ext/puppetlast +6 -31
  35. data/ext/puppetstoredconfigclean.rb +87 -0
  36. data/install.rb +75 -20
  37. data/lib/puppet.rb +1 -1
  38. data/lib/puppet/daemon.rb +0 -0
  39. data/lib/puppet/defaults.rb +3 -7
  40. data/lib/puppet/external/base64.rb +0 -0
  41. data/lib/puppet/external/nagios.rb +0 -0
  42. data/lib/puppet/external/nagios/base.rb +0 -0
  43. data/lib/puppet/file_serving/fileset.rb +2 -2
  44. data/lib/puppet/file_serving/metadata.rb +3 -3
  45. data/lib/puppet/indirector/facts/facter.rb +3 -2
  46. data/lib/puppet/indirector/yaml.rb +10 -1
  47. data/lib/puppet/module.rb +36 -12
  48. data/lib/puppet/network/authstore.rb +0 -0
  49. data/lib/puppet/network/client/master.rb +12 -11
  50. data/lib/puppet/network/handler/filebucket.rb +0 -0
  51. data/lib/puppet/network/handler/fileserver.rb +38 -46
  52. data/lib/puppet/network/handler/master.rb +1 -1
  53. data/lib/puppet/network/handler/report.rb +0 -0
  54. data/lib/puppet/network/handler/resource.rb +0 -0
  55. data/lib/puppet/network/handler/runner.rb +0 -0
  56. data/lib/puppet/network/http_server/rack.rb +148 -0
  57. data/lib/puppet/network/rights.rb +0 -0
  58. data/lib/puppet/network/xmlrpc/client.rb +5 -5
  59. data/lib/puppet/node.rb +5 -9
  60. data/lib/puppet/node/environment.rb +1 -17
  61. data/lib/puppet/node/facts.rb +0 -0
  62. data/lib/puppet/parameter.rb +1 -28
  63. data/lib/puppet/parser/ast.rb +6 -0
  64. data/lib/puppet/parser/ast/arithmetic_operator.rb +41 -0
  65. data/lib/puppet/parser/ast/boolean_operator.rb +48 -0
  66. data/lib/puppet/parser/ast/collexpr.rb +6 -1
  67. data/lib/puppet/parser/ast/comparison_operator.rb +37 -0
  68. data/lib/puppet/parser/ast/minus.rb +23 -0
  69. data/lib/puppet/parser/ast/nop.rb +11 -0
  70. data/lib/puppet/parser/ast/not.rb +19 -0
  71. data/lib/puppet/parser/ast/resource_override.rb +23 -16
  72. data/lib/puppet/parser/ast/resource_reference.rb +10 -6
  73. data/lib/puppet/parser/ast/vardef.rb +2 -2
  74. data/lib/puppet/parser/collector.rb +2 -1
  75. data/lib/puppet/parser/functions.rb +7 -217
  76. data/lib/puppet/parser/functions/defined.rb +27 -0
  77. data/lib/puppet/parser/functions/fail.rb +4 -0
  78. data/lib/puppet/parser/functions/file.rb +21 -0
  79. data/lib/puppet/parser/functions/fqdn_rand.rb +15 -0
  80. data/lib/puppet/parser/functions/generate.rb +35 -0
  81. data/lib/puppet/parser/functions/include.rb +26 -0
  82. data/lib/puppet/parser/functions/realize.rb +14 -0
  83. data/lib/puppet/parser/functions/search.rb +7 -0
  84. data/lib/puppet/parser/functions/sha1.rb +6 -0
  85. data/lib/puppet/parser/functions/tag.rb +6 -0
  86. data/lib/puppet/parser/functions/tagged.rb +18 -0
  87. data/lib/puppet/parser/functions/template.rb +22 -0
  88. data/lib/puppet/parser/lexer.rb +15 -5
  89. data/lib/puppet/parser/parser.rb +1073 -715
  90. data/lib/puppet/parser/parser_support.rb +18 -13
  91. data/lib/puppet/parser/resource.rb +1 -1
  92. data/lib/puppet/parser/resource/param.rb +10 -2
  93. data/lib/puppet/parser/scope.rb +63 -5
  94. data/lib/puppet/parser/templatewrapper.rb +61 -15
  95. data/lib/puppet/property.rb +7 -1
  96. data/lib/puppet/property/keyvalue.rb +96 -0
  97. data/lib/puppet/property/list.rb +78 -0
  98. data/lib/puppet/provider/confine.rb +1 -1
  99. data/lib/puppet/provider/confine/variable.rb +10 -1
  100. data/lib/puppet/provider/cron/crontab.rb +0 -0
  101. data/lib/puppet/provider/mailalias/aliases.rb +0 -0
  102. data/lib/puppet/provider/maillist/mailman.rb +0 -0
  103. data/lib/puppet/provider/mount/parsed.rb +0 -0
  104. data/lib/puppet/provider/nameservice.rb +24 -39
  105. data/lib/puppet/provider/nameservice/directoryservice.rb +12 -3
  106. data/lib/puppet/provider/nameservice/netinfo.rb +12 -2
  107. data/lib/puppet/provider/nameservice/objectadd.rb +1 -10
  108. data/lib/puppet/provider/package/appdmg.rb +1 -1
  109. data/lib/puppet/provider/package/apple.rb +0 -0
  110. data/lib/puppet/provider/package/apt.rb +14 -21
  111. data/lib/puppet/provider/package/aptitude.rb +0 -0
  112. data/lib/puppet/provider/package/blastwave.rb +2 -0
  113. data/lib/puppet/provider/package/darwinport.rb +0 -0
  114. data/lib/puppet/provider/package/dpkg.rb +33 -51
  115. data/lib/puppet/provider/package/fink.rb +1 -1
  116. data/lib/puppet/provider/package/freebsd.rb +0 -0
  117. data/lib/puppet/provider/package/gem.rb +0 -0
  118. data/lib/puppet/provider/package/hpux.rb +46 -0
  119. data/lib/puppet/provider/package/openbsd.rb +0 -0
  120. data/lib/puppet/provider/package/pkgdmg.rb +1 -1
  121. data/lib/puppet/provider/package/portage.rb +3 -1
  122. data/lib/puppet/provider/package/ports.rb +3 -3
  123. data/lib/puppet/provider/package/rpm.rb +8 -1
  124. data/lib/puppet/provider/package/rug.rb +2 -2
  125. data/lib/puppet/provider/package/sun.rb +2 -0
  126. data/lib/puppet/provider/package/sunfreeware.rb +3 -0
  127. data/lib/puppet/provider/package/yum.rb +24 -17
  128. data/lib/puppet/provider/package/yumhelper.py +92 -11
  129. data/lib/puppet/provider/parsedfile.rb +0 -0
  130. data/lib/puppet/provider/port/parsed.rb +0 -0
  131. data/lib/puppet/provider/selboolean/getsetsebool.rb +47 -0
  132. data/lib/puppet/provider/selmodule/semodule.rb +143 -0
  133. data/lib/puppet/provider/service/base.rb +0 -0
  134. data/lib/puppet/provider/service/daemontools.rb +154 -0
  135. data/lib/puppet/provider/service/debian.rb +1 -1
  136. data/lib/puppet/provider/service/freebsd.rb +2 -0
  137. data/lib/puppet/provider/service/gentoo.rb +2 -0
  138. data/lib/puppet/provider/service/init.rb +0 -0
  139. data/lib/puppet/provider/service/redhat.rb +1 -1
  140. data/lib/puppet/provider/service/runit.rb +93 -0
  141. data/lib/puppet/provider/service/smf.rb +2 -0
  142. data/lib/puppet/provider/ssh_authorized_key/parsed.rb +7 -1
  143. data/lib/puppet/provider/sshkey/parsed.rb +0 -0
  144. data/lib/puppet/provider/user/hpux.rb +30 -0
  145. data/lib/puppet/provider/user/user_role_add.rb +156 -0
  146. data/lib/puppet/provider/user/useradd.rb +23 -14
  147. data/lib/puppet/rails/database/002_remove_duplicated_index_on_all_tables.rb +17 -0
  148. data/lib/puppet/rails/database/schema.rb +0 -8
  149. data/lib/puppet/rails/resource.rb +6 -6
  150. data/lib/puppet/reference/configuration.rb +0 -7
  151. data/lib/puppet/reports.rb +0 -0
  152. data/lib/puppet/reports/rrdgraph.rb +3 -2
  153. data/lib/puppet/sslcertificates.rb +0 -0
  154. data/lib/puppet/sslcertificates/inventory.rb +3 -2
  155. data/lib/puppet/sslcertificates/support.rb +3 -0
  156. data/lib/puppet/transaction/report.rb +1 -7
  157. data/lib/puppet/transportable.rb +10 -7
  158. data/lib/puppet/type.rb +2110 -14
  159. data/lib/puppet/type/cron.rb +0 -0
  160. data/lib/puppet/type/exec.rb +0 -0
  161. data/lib/puppet/type/file.rb +12 -2
  162. data/lib/puppet/type/file/checksum.rb +4 -0
  163. data/lib/puppet/type/file/content.rb +0 -0
  164. data/lib/puppet/type/file/ensure.rb +0 -0
  165. data/lib/puppet/type/file/group.rb +30 -43
  166. data/lib/puppet/type/file/mode.rb +0 -0
  167. data/lib/puppet/type/file/owner.rb +0 -0
  168. data/lib/puppet/type/file/selcontext.rb +104 -0
  169. data/lib/puppet/type/file/source.rb +0 -0
  170. data/lib/puppet/type/file/type.rb +0 -0
  171. data/lib/puppet/type/filebucket.rb +0 -0
  172. data/lib/puppet/type/group.rb +0 -8
  173. data/lib/puppet/type/host.rb +0 -0
  174. data/lib/puppet/type/mailalias.rb +0 -0
  175. data/lib/puppet/type/maillist.rb +0 -0
  176. data/lib/puppet/type/mount.rb +0 -0
  177. data/lib/puppet/type/package.rb +2 -2
  178. data/lib/puppet/type/port.rb +0 -0
  179. data/lib/puppet/type/schedule.rb +0 -0
  180. data/lib/puppet/type/selboolean.rb +31 -0
  181. data/lib/puppet/type/selmodule.rb +54 -0
  182. data/lib/puppet/type/ssh_authorized_key.rb +3 -3
  183. data/lib/puppet/type/sshkey.rb +0 -0
  184. data/lib/puppet/type/tidy.rb +0 -0
  185. data/lib/puppet/type/user.rb +153 -137
  186. data/lib/puppet/type/yumrepo.rb +18 -2
  187. data/lib/puppet/type/zone.rb +5 -1
  188. data/lib/puppet/util.rb +7 -7
  189. data/lib/puppet/util/filetype.rb +7 -0
  190. data/lib/puppet/util/instance_loader.rb +0 -0
  191. data/lib/puppet/util/ldap/connection.rb +11 -1
  192. data/lib/puppet/util/ldap/manager.rb +1 -1
  193. data/lib/puppet/util/loadedfile.rb +0 -0
  194. data/lib/puppet/util/log.rb +42 -43
  195. data/lib/puppet/util/metric.rb +23 -9
  196. data/lib/puppet/util/posix.rb +69 -18
  197. data/lib/puppet/util/selinux.rb +139 -0
  198. data/lib/puppet/util/settings.rb +5 -7
  199. data/lib/puppet/util/user_attr.rb +21 -0
  200. data/test/certmgr/ca.rb +0 -0
  201. data/test/certmgr/certmgr.rb +0 -0
  202. data/test/certmgr/inventory.rb +0 -0
  203. data/test/certmgr/support.rb +0 -0
  204. data/test/data/providers/ssh_authorized_key/parsed/authorized_keys1 +3 -0
  205. data/test/data/snippets/append.pp +11 -0
  206. data/test/data/snippets/arithmetic_expression.pp +8 -0
  207. data/test/data/snippets/arraytrailingcomma.pp +3 -0
  208. data/test/data/snippets/emptyifelse.pp +9 -0
  209. data/test/data/snippets/funccomma.pp +5 -0
  210. data/test/data/snippets/ifexpression.rb +6 -0
  211. data/test/data/snippets/subclass_name_duplication.pp +0 -0
  212. data/test/executables/filebucket.rb +0 -0
  213. data/test/executables/puppetbin.rb +0 -0
  214. data/test/executables/puppetca.rb +0 -0
  215. data/test/executables/puppetd.rb +0 -0
  216. data/test/executables/puppetmasterd.rb +0 -0
  217. data/test/executables/puppetmodule.rb +0 -0
  218. data/test/language/ast.rb +0 -0
  219. data/test/language/ast/casestatement.rb +0 -0
  220. data/test/language/ast/resource.rb +0 -0
  221. data/test/language/ast/resource_reference.rb +0 -28
  222. data/test/language/ast/selector.rb +0 -0
  223. data/test/language/ast/variable.rb +0 -0
  224. data/test/language/functions.rb +91 -12
  225. data/test/language/parser.rb +21 -0
  226. data/test/language/resource.rb +0 -0
  227. data/test/language/scope.rb +28 -0
  228. data/test/language/snippets.rb +14 -0
  229. data/test/language/transportable.rb +0 -0
  230. data/test/lib/puppettest.rb +0 -0
  231. data/test/lib/puppettest/reporttesting.rb +0 -2
  232. data/test/lib/puppettest/runnable_test.rb +2 -0
  233. data/test/lib/puppettest/support/resources.rb +0 -0
  234. data/test/network/authconfig.rb +0 -0
  235. data/test/network/authorization.rb +0 -0
  236. data/test/network/authstore.rb +0 -0
  237. data/test/network/client/ca.rb +0 -0
  238. data/test/network/client/client.rb +0 -0
  239. data/test/network/client/dipper.rb +0 -0
  240. data/test/network/client/master.rb +2 -6
  241. data/test/network/client/resource.rb +0 -0
  242. data/test/network/client_request.rb +0 -0
  243. data/test/network/daemon.rb +0 -0
  244. data/test/network/handler/bucket.rb +0 -0
  245. data/test/network/handler/ca.rb +0 -0
  246. data/test/network/handler/fileserver.rb +8 -0
  247. data/test/network/handler/handler.rb +0 -0
  248. data/test/network/handler/master.rb +3 -1
  249. data/test/network/handler/report.rb +0 -0
  250. data/test/network/handler/resource.rb +0 -0
  251. data/test/network/handler/runner.rb +0 -0
  252. data/test/network/rights.rb +0 -0
  253. data/test/network/server/mongrel_test.rb +0 -0
  254. data/test/network/server/webrick.rb +0 -0
  255. data/test/network/xmlrpc/client.rb +0 -0
  256. data/test/network/xmlrpc/processor.rb +0 -0
  257. data/test/network/xmlrpc/server.rb +0 -0
  258. data/test/network/xmlrpc/webrick_servlet.rb +0 -0
  259. data/test/other/dsl.rb +0 -0
  260. data/test/other/events.rb +0 -0
  261. data/test/other/overrides.rb +0 -0
  262. data/test/other/provider.rb +0 -0
  263. data/test/other/puppet.rb +0 -0
  264. data/test/other/relationships.rb +0 -0
  265. data/test/other/report.rb +2 -4
  266. data/test/other/transactions.rb +1 -1
  267. data/test/puppet/conffiles.rb +0 -0
  268. data/test/puppet/defaults.rb +0 -0
  269. data/test/puppet/errortest.rb +0 -0
  270. data/test/puppet/tc_suidmanager.rb +0 -0
  271. data/test/rails/ast.rb +0 -0
  272. data/test/rails/configuration.rb +0 -0
  273. data/test/rails/host.rb +0 -0
  274. data/test/rails/rails.rb +0 -0
  275. data/test/rails/railsparameter.rb +0 -0
  276. data/test/rails/railsresource.rb +0 -0
  277. data/test/ral/manager/attributes.rb +0 -0
  278. data/test/ral/manager/instances.rb +0 -0
  279. data/test/ral/manager/manager.rb +0 -0
  280. data/test/ral/manager/provider.rb +0 -0
  281. data/test/ral/manager/type.rb +0 -0
  282. data/test/ral/providers/cron/crontab.rb +0 -0
  283. data/test/ral/providers/group.rb +14 -13
  284. data/test/ral/providers/host/netinfo.rb +0 -0
  285. data/test/ral/providers/host/parsed.rb +0 -0
  286. data/test/ral/providers/mailalias/aliases.rb +0 -0
  287. data/test/ral/providers/mount/netinfo.rb +0 -0
  288. data/test/ral/providers/nameservice.rb +0 -0
  289. data/test/ral/providers/package.rb +0 -31
  290. data/test/ral/providers/package/aptitude.rb +1 -2
  291. data/test/ral/providers/package/aptrpm.rb +2 -2
  292. data/test/ral/providers/parsedfile.rb +0 -0
  293. data/test/ral/providers/port/parsed.rb +0 -0
  294. data/test/ral/providers/provider.rb +0 -0
  295. data/test/ral/providers/service/base.rb +0 -0
  296. data/test/ral/providers/service/debian.rb +0 -0
  297. data/test/ral/providers/sshkey/parsed.rb +0 -0
  298. data/test/ral/providers/user.rb +8 -8
  299. data/test/ral/providers/user/useradd.rb +0 -0
  300. data/test/ral/type/basic.rb +0 -0
  301. data/test/ral/type/cron.rb +0 -0
  302. data/test/ral/type/exec.rb +0 -0
  303. data/test/ral/type/file.rb +0 -0
  304. data/test/ral/type/file/target.rb +0 -0
  305. data/test/ral/type/filebucket.rb +0 -0
  306. data/test/ral/type/fileignoresource.rb +0 -0
  307. data/test/ral/type/filesources.rb +1 -3
  308. data/test/ral/type/group.rb +0 -0
  309. data/test/ral/type/host.rb +0 -0
  310. data/test/ral/type/mailalias.rb +1 -2
  311. data/test/ral/type/parameter.rb +0 -0
  312. data/test/ral/type/port.rb +0 -0
  313. data/test/ral/type/property.rb +0 -0
  314. data/test/ral/type/resources.rb +0 -0
  315. data/test/ral/type/service.rb +0 -0
  316. data/test/ral/type/sshkey.rb +0 -0
  317. data/test/ral/type/tidy.rb +0 -0
  318. data/test/ral/type/user.rb +0 -50
  319. data/test/ral/type/yumrepo.rb +7 -1
  320. data/test/ral/type/zone.rb +0 -0
  321. data/test/test +0 -0
  322. data/test/util/autoload.rb +0 -0
  323. data/test/util/classgen.rb +0 -0
  324. data/test/util/execution.rb +0 -0
  325. data/test/util/features.rb +0 -0
  326. data/test/util/fileparsing.rb +0 -0
  327. data/test/util/filetype.rb +0 -0
  328. data/test/util/inifile.rb +0 -0
  329. data/test/util/instance_loader.rb +0 -0
  330. data/test/util/log.rb +0 -59
  331. data/test/util/metrics.rb +0 -0
  332. data/test/util/package.rb +0 -0
  333. data/test/util/pidlock.rb +0 -0
  334. data/test/util/settings.rb +0 -0
  335. data/test/util/storage.rb +0 -0
  336. data/test/util/subclass_loader.rb +0 -0
  337. data/test/util/utiltest.rb +0 -0
  338. metadata +54 -19
  339. data/lib/puppet/metatype/attributes.rb +0 -685
  340. data/lib/puppet/metatype/closure.rb +0 -49
  341. data/lib/puppet/metatype/container.rb +0 -50
  342. data/lib/puppet/metatype/evaluation.rb +0 -163
  343. data/lib/puppet/metatype/instances.rb +0 -305
  344. data/lib/puppet/metatype/metaparams.rb +0 -423
  345. data/lib/puppet/metatype/providers.rb +0 -247
  346. data/lib/puppet/metatype/relationships.rb +0 -115
  347. data/lib/puppet/metatype/schedules.rb +0 -33
  348. data/lib/puppet/metatype/tags.rb +0 -38
  349. data/lib/puppet/util/plist.rb +0 -23
  350. data/lib/puppet/util/plist/generator.rb +0 -225
  351. data/lib/puppet/util/plist/parser.rb +0 -226
  352. data/test/ral/providers/package/apt.rb +0 -169
  353. data/test/ral/providers/package/dpkg.rb +0 -64
  354. data/test/util/posixtest.rb +0 -169
@@ -23,8 +23,22 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
23
23
  has_feature :manages_passwords
24
24
  end
25
25
 
26
- def addcmd
27
- cmd = [command(:add)]
26
+ def check_allow_dup
27
+ @resource.allowdupe? ? ["-o"] : []
28
+ end
29
+
30
+ def check_manage_home
31
+ cmd = []
32
+ if @resource.managehome?
33
+ cmd << "-m"
34
+ elsif %w{Fedora RedHat}.include?(Facter.value("operatingsystem"))
35
+ cmd << "-M"
36
+ end
37
+ cmd
38
+ end
39
+
40
+ def add_properties
41
+ cmd = []
28
42
  Puppet::Type.type(:user).validproperties.each do |property|
29
43
  next if property == :ensure
30
44
  # the value needs to be quoted, mostly because -c might
@@ -33,20 +47,15 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
33
47
  cmd << flag(property) << value
34
48
  end
35
49
  end
50
+ cmd
51
+ end
36
52
 
37
- if @resource.allowdupe?
38
- cmd << "-o"
39
- end
40
-
41
- if @resource.managehome?
42
- cmd << "-m"
43
- elsif %w{Fedora RedHat}.include?(Facter.value("operatingsystem"))
44
- cmd << "-M"
45
- end
46
-
53
+ def addcmd
54
+ cmd = [command(:add)]
55
+ cmd += add_properties
56
+ cmd += check_allow_dup
57
+ cmd += check_manage_home
47
58
  cmd << @resource[:name]
48
-
49
- cmd
50
59
  end
51
60
 
52
61
  # Retrieve the password using the Shadow Password library
@@ -0,0 +1,17 @@
1
+ class RemoveDuplicatedIndexOnAllTables < ActiveRecord::Migration
2
+ def self.up
3
+ ActiveRecord::Base.connection.tables.each do |t|
4
+ if ActiveRecord::Base.connection.indexes(t).collect {|c| c.columns}.include?("id")
5
+ remove_index t.to_s, :id
6
+ end
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ ActiveRecord::Base.connection.tables.each do |t|
12
+ unless ActiveRecord::Base.connection.indexes(t).collect {|c| c.columns}.include?("id")
13
+ add_index t.to_s, :id, :integer => true
14
+ end
15
+ end
16
+ end
17
+ end
@@ -16,7 +16,6 @@ class Puppet::Rails::Schema
16
16
  t.column :updated_at, :datetime
17
17
  t.column :created_at, :datetime
18
18
  end
19
- add_index :resources, :id, :integer => true
20
19
  add_index :resources, :host_id, :integer => true
21
20
  add_index :resources, :source_file_id, :integer => true
22
21
 
@@ -34,7 +33,6 @@ class Puppet::Rails::Schema
34
33
  t.column :updated_at, :datetime
35
34
  t.column :created_at, :datetime
36
35
  end
37
- add_index :source_files, :id, :integer => true
38
36
  add_index :source_files, :filename
39
37
 
40
38
  create_table :resource_tags do |t|
@@ -43,7 +41,6 @@ class Puppet::Rails::Schema
43
41
  t.column :updated_at, :datetime
44
42
  t.column :created_at, :datetime
45
43
  end
46
- add_index :resource_tags, :id, :integer => true
47
44
  add_index :resource_tags, :resource_id, :integer => true
48
45
  add_index :resource_tags, :puppet_tag_id, :integer => true
49
46
 
@@ -65,7 +62,6 @@ class Puppet::Rails::Schema
65
62
  t.column :source_file_id, :integer
66
63
  t.column :created_at, :datetime
67
64
  end
68
- add_index :hosts, :id, :integer => true
69
65
  add_index :hosts, :source_file_id, :integer => true
70
66
  add_index :hosts, :name
71
67
 
@@ -74,7 +70,6 @@ class Puppet::Rails::Schema
74
70
  t.column :updated_at, :datetime
75
71
  t.column :created_at, :datetime
76
72
  end
77
- add_index :fact_names, :id, :integer => true
78
73
  add_index :fact_names, :name
79
74
 
80
75
  create_table :fact_values do |t|
@@ -84,7 +79,6 @@ class Puppet::Rails::Schema
84
79
  t.column :updated_at, :datetime
85
80
  t.column :created_at, :datetime
86
81
  end
87
- add_index :fact_values, :id, :integer => true
88
82
  add_index :fact_values, :fact_name_id, :integer => true
89
83
  add_index :fact_values, :host_id, :integer => true
90
84
 
@@ -96,7 +90,6 @@ class Puppet::Rails::Schema
96
90
  t.column :updated_at, :datetime
97
91
  t.column :created_at, :datetime
98
92
  end
99
- add_index :param_values, :id, :integer => true
100
93
  add_index :param_values, :param_name_id, :integer => true
101
94
  add_index :param_values, :resource_id, :integer => true
102
95
 
@@ -105,7 +98,6 @@ class Puppet::Rails::Schema
105
98
  t.column :updated_at, :datetime
106
99
  t.column :created_at, :datetime
107
100
  end
108
- add_index :param_names, :id, :integer => true
109
101
  add_index :param_names, :name
110
102
  end
111
103
  end
@@ -6,12 +6,12 @@ require 'puppet/util/rails/collection_merger'
6
6
  class Puppet::Rails::Resource < ActiveRecord::Base
7
7
  include Puppet::Util::CollectionMerger
8
8
 
9
- has_many :param_values, :dependent => :destroy
10
- has_many :param_names, :through => :param_values
9
+ has_many :param_values, :dependent => :destroy, :class_name => "Puppet::Rails::ParamValue"
10
+ has_many :param_names, :through => :param_values, :class_name => "Puppet::Rails::ParamName"
11
+
12
+ has_many :resource_tags, :dependent => :destroy, :class_name => "Puppet::Rails::ResourceTag"
13
+ has_many :puppet_tags, :through => :resource_tags, :class_name => "Puppet::Rails::PuppetTag"
11
14
 
12
- has_many :resource_tags, :dependent => :destroy
13
- has_many :puppet_tags, :through => :resource_tags
14
-
15
15
  belongs_to :source_file
16
16
  belongs_to :host
17
17
 
@@ -82,7 +82,7 @@ class Puppet::Rails::Resource < ActiveRecord::Base
82
82
  end
83
83
 
84
84
  def ref
85
- "%s[%s]" % [self[:restype].capitalize, self[:title]]
85
+ "%s[%s]" % [self[:restype].split("::").collect { |s| s.capitalize }.join("::"), self[:title]]
86
86
  end
87
87
 
88
88
  # Convert our object to a resource. Do not retain whether the object
@@ -49,10 +49,6 @@ On The Command-Line
49
49
  +++++++++++++++++++
50
50
  Every Puppet executable (with the exception of ``puppetdoc``) accepts all of
51
51
  the parameters below, but not all of the arguments make sense for every executable.
52
- Each parameter has a section listed with it in parentheses; often, that section
53
- will map to an executable (e.g., ``puppetd``), in which case it probably only
54
- makes sense for that one executable. If ``main`` is listed as the section,
55
- it is most likely an option that is valid for everyone.
56
52
 
57
53
  I have tried to be as thorough as possible in the descriptions of the
58
54
  arguments, so it should be obvious whether an argument is appropriate or not.
@@ -121,9 +117,6 @@ Note that this invocation will replace the contents of any pre-existing
121
117
  `puppet.conf` file, so make a backup of your present config if it contains
122
118
  valuable information.
123
119
 
124
- All parameters will be under a single section heading matching the name of
125
- the process used to generate the configuraiton ('puppetd', in this case).
126
-
127
120
  Like the `--genconfig` argument, the executables also accept a `--genmanifest`
128
121
  argument, which will generate a manifest that can be used to manage all of
129
122
  Puppet's directories and files and prints it to standard output. This can
File without changes
@@ -90,8 +90,9 @@ Puppet::Reports.register_report(:rrdgraph) do
90
90
  of.puts "<html><head><title>Report graphs for %s</title></head><body>" %
91
91
  host
92
92
  files.each do |file|
93
- of.puts "<a href='#{File.basename(file)}'>%s</a><br/>" %
94
- File.basename(file).sub(".html",'').capitalize
93
+ of.puts "<a href='%s'>%s</a><br/>" %
94
+ [File.basename(file),
95
+ File.basename(file).sub(".html",'').capitalize]
95
96
  end
96
97
  of.puts "</body></html>"
97
98
  end
File without changes
@@ -7,8 +7,9 @@ module Puppet::SSLCertificates
7
7
  # If no inventory exists yet, build an inventory and list all the
8
8
  # certificates that have been signed so far
9
9
  def self.add(cert)
10
- unless FileTest.exists?(Puppet[:cert_inventory])
11
- inited = false
10
+ inited = false
11
+ if FileTest.exists?(Puppet[:cert_inventory])
12
+ inited = true
12
13
  end
13
14
 
14
15
  Puppet.settings.write(:cert_inventory, "a") do |f|
@@ -133,6 +133,9 @@ module Puppet::SSLCertificates::Support
133
133
  #return nil unless FileTest.directory?(dir)
134
134
 
135
135
  raise ArgumentError, "Tried to fix SSL files to a file containing uppercase" unless short.downcase == short
136
+
137
+ return false unless File.directory?(dir)
138
+
136
139
  real_file = Dir.entries(dir).reject { |f| f =~ /^\./ }.find do |other|
137
140
  other.downcase == short
138
141
  end
@@ -25,13 +25,7 @@ class Puppet::Transaction::Report
25
25
  hash[key] = []
26
26
  end
27
27
 
28
- domain = Facter.value("domain")
29
- hostname = Facter.value("hostname")
30
- if !domain || domain.empty? then
31
- @host = hostname
32
- else
33
- @host = [hostname, domain].join(".")
34
- end
28
+ @host = Puppet[:certname]
35
29
  end
36
30
 
37
31
  def name
@@ -65,13 +65,16 @@ module Puppet
65
65
  end
66
66
 
67
67
  def to_manifest
68
- "#{self.type.to_s} { \'#{self.name}\':\n%s\n}" % @params.collect { |p, v|
69
- if v.is_a? Array
70
- " #{p} => [\'#{v.join("','")}\']"
71
- else
72
- " #{p} => \'#{v}\'"
73
- end
74
- }.join(",\n")
68
+ "%s { '%s':\n%s\n}" %
69
+ [self.type.to_s, self.name,
70
+ @params.collect { |p, v|
71
+ if v.is_a? Array
72
+ " #{p} => [\'#{v.join("','")}\']"
73
+ else
74
+ " #{p} => \'#{v}\'"
75
+ end
76
+ }.join(",\n")
77
+ ]
75
78
  end
76
79
 
77
80
  def to_yaml_properties
@@ -20,20 +20,2116 @@ class Type
20
20
  include Puppet::Util::LogPaths
21
21
  include Puppet::Util::Logging
22
22
 
23
- # Nearly all of the code in this class is stored in files in the
24
- # metatype/ directory. This is a temporary measure until I get a chance
25
- # to refactor this class entirely. There's still more simplification to
26
- # do, but this works for now.
27
- require 'puppet/metatype/attributes'
28
- require 'puppet/metatype/closure'
29
- require 'puppet/metatype/container'
30
- require 'puppet/metatype/evaluation'
31
- require 'puppet/metatype/instances'
32
- require 'puppet/metatype/metaparams'
33
- require 'puppet/metatype/providers'
34
- require 'puppet/metatype/relationships'
35
- require 'puppet/metatype/schedules'
36
- require 'puppet/metatype/tags'
23
+ ###############################
24
+ # Code related to resource type attributes.
25
+ class << self
26
+ include Puppet::Util::ClassGen
27
+ include Puppet::Util::Warnings
28
+ attr_reader :properties
29
+ end
30
+
31
+ def self.states
32
+ warnonce "The states method is deprecated; use properties"
33
+ properties()
34
+ end
35
+
36
+ # All parameters, in the appropriate order. The namevar comes first,
37
+ # then the properties, then the params and metaparams in the order they
38
+ # were specified in the files.
39
+ def self.allattrs
40
+ # now get all of the arguments, in a specific order
41
+ # Cache this, since it gets called so many times
42
+ namevar = self.namevar
43
+
44
+ order = [namevar]
45
+ if self.parameters.include?(:provider)
46
+ order << :provider
47
+ end
48
+ order << [self.properties.collect { |property| property.name },
49
+ self.parameters - [:provider],
50
+ self.metaparams].flatten.reject { |param|
51
+ # we don't want our namevar in there multiple times
52
+ param == namevar
53
+ }
54
+
55
+ order.flatten!
56
+
57
+ return order
58
+ end
59
+
60
+ # Retrieve an attribute alias, if there is one.
61
+ def self.attr_alias(param)
62
+ @attr_aliases[symbolize(param)]
63
+ end
64
+
65
+ # Create an alias to an existing attribute. This will cause the aliased
66
+ # attribute to be valid when setting and retrieving values on the instance.
67
+ def self.set_attr_alias(hash)
68
+ hash.each do |new, old|
69
+ @attr_aliases[symbolize(new)] = symbolize(old)
70
+ end
71
+ end
72
+
73
+ # Find the class associated with any given attribute.
74
+ def self.attrclass(name)
75
+ @attrclasses ||= {}
76
+
77
+ # We cache the value, since this method gets called such a huge number
78
+ # of times (as in, hundreds of thousands in a given run).
79
+ unless @attrclasses.include?(name)
80
+ @attrclasses[name] = case self.attrtype(name)
81
+ when :property: @validproperties[name]
82
+ when :meta: @@metaparamhash[name]
83
+ when :param: @paramhash[name]
84
+ end
85
+ end
86
+ @attrclasses[name]
87
+ end
88
+
89
+ # What type of parameter are we dealing with? Cache the results, because
90
+ # this method gets called so many times.
91
+ def self.attrtype(attr)
92
+ @attrtypes ||= {}
93
+ unless @attrtypes.include?(attr)
94
+ @attrtypes[attr] = case
95
+ when @validproperties.include?(attr): :property
96
+ when @paramhash.include?(attr): :param
97
+ when @@metaparamhash.include?(attr): :meta
98
+ else
99
+ raise Puppet::DevError,
100
+ "Invalid attribute '%s' for class '%s'" %
101
+ [attr, self.name]
102
+ end
103
+ end
104
+
105
+ @attrtypes[attr]
106
+ end
107
+
108
+ # Copy an existing class parameter. This allows other types to avoid
109
+ # duplicating a parameter definition, and is mostly used by subclasses
110
+ # of the File class.
111
+ def self.copyparam(klass, name)
112
+ param = klass.attrclass(name)
113
+
114
+ unless param
115
+ raise Puppet::DevError, "Class %s has no param %s" % [klass, name]
116
+ end
117
+ @parameters << param
118
+ @parameters.each { |p| @paramhash[name] = p }
119
+
120
+ if param.isnamevar?
121
+ @namevar = param.name
122
+ end
123
+ end
124
+
125
+ # A similar function but one that yields the class and type.
126
+ # This is mainly so that setdefaults doesn't call quite so many functions.
127
+ def self.eachattr(*ary)
128
+ if ary.empty?
129
+ ary = nil
130
+ end
131
+
132
+ # We have to do this in a specific order, so that defaults are
133
+ # created in that order (e.g., providers should be set up before
134
+ # anything else).
135
+ allattrs.each do |name|
136
+ next unless ary.nil? or ary.include?(name)
137
+ if obj = @properties.find { |p| p.name == name }
138
+ yield obj, :property
139
+ elsif obj = @parameters.find { |p| p.name == name }
140
+ yield obj, :param
141
+ elsif obj = @@metaparams.find { |p| p.name == name }
142
+ yield obj, :meta
143
+ else
144
+ raise Puppet::DevError, "Could not find parameter %s" % name
145
+ end
146
+ end
147
+ end
148
+
149
+ def self.eachmetaparam
150
+ @@metaparams.each { |p| yield p.name }
151
+ end
152
+
153
+ # Create the 'ensure' class. This is a separate method so other types
154
+ # can easily call it and create their own 'ensure' values.
155
+ def self.ensurable(&block)
156
+ if block_given?
157
+ self.newproperty(:ensure, :parent => Puppet::Property::Ensure, &block)
158
+ else
159
+ self.newproperty(:ensure, :parent => Puppet::Property::Ensure) do
160
+ self.defaultvalues
161
+ end
162
+ end
163
+ end
164
+
165
+ # Should we add the 'ensure' property to this class?
166
+ def self.ensurable?
167
+ # If the class has all three of these methods defined, then it's
168
+ # ensurable.
169
+ ens = [:exists?, :create, :destroy].inject { |set, method|
170
+ set &&= self.public_method_defined?(method)
171
+ }
172
+
173
+ return ens
174
+ end
175
+
176
+ # Deal with any options passed into parameters.
177
+ def self.handle_param_options(name, options)
178
+ # If it's a boolean parameter, create a method to test the value easily
179
+ if options[:boolean]
180
+ define_method(name.to_s + "?") do
181
+ val = self[name]
182
+ if val == :true or val == true
183
+ return true
184
+ end
185
+ end
186
+ end
187
+
188
+ # If this param handles relationships, store that information
189
+ end
190
+
191
+ # Is the parameter in question a meta-parameter?
192
+ def self.metaparam?(param)
193
+ @@metaparamhash.include?(symbolize(param))
194
+ end
195
+
196
+ # Find the metaparameter class associated with a given metaparameter name.
197
+ def self.metaparamclass(name)
198
+ @@metaparamhash[symbolize(name)]
199
+ end
200
+
201
+ def self.metaparams
202
+ @@metaparams.collect { |param| param.name }
203
+ end
204
+
205
+ def self.metaparamdoc(metaparam)
206
+ @@metaparamhash[metaparam].doc
207
+ end
208
+
209
+ # Create a new metaparam. Requires a block and a name, stores it in the
210
+ # @parameters array, and does some basic checking on it.
211
+ def self.newmetaparam(name, options = {}, &block)
212
+ @@metaparams ||= []
213
+ @@metaparamhash ||= {}
214
+ name = symbolize(name)
215
+
216
+ param = genclass(name,
217
+ :parent => options[:parent] || Puppet::Parameter,
218
+ :prefix => "MetaParam",
219
+ :hash => @@metaparamhash,
220
+ :array => @@metaparams,
221
+ :attributes => options[:attributes],
222
+ &block
223
+ )
224
+
225
+ # Grr.
226
+ if options[:required_features]
227
+ param.required_features = options[:required_features]
228
+ end
229
+
230
+ handle_param_options(name, options)
231
+
232
+ param.metaparam = true
233
+
234
+ return param
235
+ end
236
+
237
+ # Find the namevar
238
+ def self.namevar
239
+ unless defined? @namevar
240
+ params = @parameters.find_all { |param|
241
+ param.isnamevar? or param.name == :name
242
+ }
243
+
244
+ if params.length > 1
245
+ raise Puppet::DevError, "Found multiple namevars for %s" % self.name
246
+ elsif params.length == 1
247
+ @namevar = params[0].name
248
+ else
249
+ raise Puppet::DevError, "No namevar for %s" % self.name
250
+ end
251
+ end
252
+ @namevar
253
+ end
254
+
255
+ # Create a new parameter. Requires a block and a name, stores it in the
256
+ # @parameters array, and does some basic checking on it.
257
+ def self.newparam(name, options = {}, &block)
258
+ options[:attributes] ||= {}
259
+ param = genclass(name,
260
+ :parent => options[:parent] || Puppet::Parameter,
261
+ :attributes => options[:attributes],
262
+ :block => block,
263
+ :prefix => "Parameter",
264
+ :array => @parameters,
265
+ :hash => @paramhash
266
+ )
267
+
268
+ handle_param_options(name, options)
269
+
270
+ # Grr.
271
+ if options[:required_features]
272
+ param.required_features = options[:required_features]
273
+ end
274
+
275
+ param.isnamevar if options[:namevar]
276
+
277
+ # These might be enabled later.
278
+ # define_method(name) do
279
+ # @parameters[name].value
280
+ # end
281
+ #
282
+ # define_method(name.to_s + "=") do |value|
283
+ # newparam(param, value)
284
+ # end
285
+
286
+ if param.isnamevar?
287
+ @namevar = param.name
288
+ end
289
+
290
+ return param
291
+ end
292
+
293
+ def self.newstate(name, options = {}, &block)
294
+ Puppet.warning "newstate() has been deprecrated; use newproperty(%s)" %
295
+ name
296
+ newproperty(name, options, &block)
297
+ end
298
+
299
+ # Create a new property. The first parameter must be the name of the property;
300
+ # this is how users will refer to the property when creating new instances.
301
+ # The second parameter is a hash of options; the options are:
302
+ # * <tt>:parent</tt>: The parent class for the property. Defaults to Puppet::Property.
303
+ # * <tt>:retrieve</tt>: The method to call on the provider or @parent object (if
304
+ # the provider is not set) to retrieve the current value.
305
+ def self.newproperty(name, options = {}, &block)
306
+ name = symbolize(name)
307
+
308
+ # This is here for types that might still have the old method of defining
309
+ # a parent class.
310
+ unless options.is_a? Hash
311
+ raise Puppet::DevError,
312
+ "Options must be a hash, not %s" % options.inspect
313
+ end
314
+
315
+ if @validproperties.include?(name)
316
+ raise Puppet::DevError, "Class %s already has a property named %s" %
317
+ [self.name, name]
318
+ end
319
+
320
+ if parent = options[:parent]
321
+ options.delete(:parent)
322
+ else
323
+ parent = Puppet::Property
324
+ end
325
+
326
+ # We have to create our own, new block here because we want to define
327
+ # an initial :retrieve method, if told to, and then eval the passed
328
+ # block if available.
329
+ prop = genclass(name, :parent => parent, :hash => @validproperties, :attributes => options) do
330
+ # If they've passed a retrieve method, then override the retrieve
331
+ # method on the class.
332
+ if options[:retrieve]
333
+ define_method(:retrieve) do
334
+ provider.send(options[:retrieve])
335
+ end
336
+ end
337
+
338
+ if block
339
+ class_eval(&block)
340
+ end
341
+ end
342
+
343
+ # If it's the 'ensure' property, always put it first.
344
+ if name == :ensure
345
+ @properties.unshift prop
346
+ else
347
+ @properties << prop
348
+ end
349
+
350
+ # define_method(name) do
351
+ # @parameters[name].should
352
+ # end
353
+ #
354
+ # define_method(name.to_s + "=") do |value|
355
+ # newproperty(name, :should => value)
356
+ # end
357
+
358
+ return prop
359
+ end
360
+
361
+ def self.paramdoc(param)
362
+ @paramhash[param].doc
363
+ end
364
+
365
+ # Return the parameter names
366
+ def self.parameters
367
+ return [] unless defined? @parameters
368
+ @parameters.collect { |klass| klass.name }
369
+ end
370
+
371
+ # Find the parameter class associated with a given parameter name.
372
+ def self.paramclass(name)
373
+ @paramhash[name]
374
+ end
375
+
376
+ # Return the property class associated with a name
377
+ def self.propertybyname(name)
378
+ @validproperties[name]
379
+ end
380
+
381
+ def self.validattr?(name)
382
+ name = symbolize(name)
383
+ return true if name == :name
384
+ @validattrs ||= {}
385
+
386
+ unless @validattrs.include?(name)
387
+ if self.validproperty?(name) or self.validparameter?(name) or self.metaparam?(name)
388
+ @validattrs[name] = true
389
+ else
390
+ @validattrs[name] = false
391
+ end
392
+ end
393
+
394
+ @validattrs[name]
395
+ end
396
+
397
+ # does the name reflect a valid property?
398
+ def self.validproperty?(name)
399
+ name = symbolize(name)
400
+ if @validproperties.include?(name)
401
+ return @validproperties[name]
402
+ else
403
+ return false
404
+ end
405
+ end
406
+
407
+ # Return the list of validproperties
408
+ def self.validproperties
409
+ return {} unless defined? @parameters
410
+
411
+ return @validproperties.keys
412
+ end
413
+
414
+ # does the name reflect a valid parameter?
415
+ def self.validparameter?(name)
416
+ unless defined? @parameters
417
+ raise Puppet::DevError, "Class %s has not defined parameters" % self
418
+ end
419
+ if @paramhash.include?(name) or @@metaparamhash.include?(name)
420
+ return true
421
+ else
422
+ return false
423
+ end
424
+ end
425
+
426
+ # fix any namevar => param translations
427
+ def argclean(oldhash)
428
+ # This duplication is here because it might be a transobject.
429
+ hash = oldhash.dup.to_hash
430
+
431
+ if hash.include?(:resource)
432
+ hash.delete(:resource)
433
+ end
434
+ namevar = self.class.namevar
435
+
436
+ # Do a simple translation for those cases where they've passed :name
437
+ # but that's not our namevar
438
+ if hash.include? :name and namevar != :name
439
+ if hash.include? namevar
440
+ raise ArgumentError, "Cannot provide both name and %s" % namevar
441
+ end
442
+ hash[namevar] = hash[:name]
443
+ hash.delete(:name)
444
+ end
445
+
446
+ # Make sure we have a name, one way or another
447
+ unless hash.include? namevar
448
+ if defined? @title and @title
449
+ hash[namevar] = @title
450
+ else
451
+ raise Puppet::Error, "Was not passed a namevar or title"
452
+ end
453
+ end
454
+
455
+ return hash
456
+ end
457
+
458
+ # Return either the attribute alias or the attribute.
459
+ def attr_alias(name)
460
+ name = symbolize(name)
461
+ if synonym = self.class.attr_alias(name)
462
+ return synonym
463
+ else
464
+ return name
465
+ end
466
+ end
467
+
468
+ # Are we deleting this resource?
469
+ def deleting?
470
+ obj = @parameters[:ensure] and obj.should == :absent
471
+ end
472
+
473
+ # Create a new property if it is valid but doesn't exist
474
+ # Returns: true if a new parameter was added, false otherwise
475
+ def add_property_parameter(prop_name)
476
+ if self.class.validproperty?(prop_name) && !@parameters[prop_name]
477
+ self.newattr(prop_name)
478
+ return true
479
+ end
480
+ return false
481
+ end
482
+
483
+ # abstract accessing parameters and properties, and normalize
484
+ # access to always be symbols, not strings
485
+ # This returns a value, not an object. It returns the 'is'
486
+ # value, but you can also specifically return 'is' and 'should'
487
+ # values using 'object.is(:property)' or 'object.should(:property)'.
488
+ def [](name)
489
+ name = attr_alias(name)
490
+
491
+ unless self.class.validattr?(name)
492
+ raise TypeError.new("Invalid parameter %s(%s)" % [name, name.inspect])
493
+ end
494
+
495
+ if name == :name
496
+ name = self.class.namevar
497
+ end
498
+
499
+ if obj = @parameters[name]
500
+ # Note that if this is a property, then the value is the "should" value,
501
+ # not the current value.
502
+ obj.value
503
+ else
504
+ return nil
505
+ end
506
+ end
507
+
508
+ # Abstract setting parameters and properties, and normalize
509
+ # access to always be symbols, not strings. This sets the 'should'
510
+ # value on properties, and otherwise just sets the appropriate parameter.
511
+ def []=(name,value)
512
+ name = attr_alias(name)
513
+
514
+ unless self.class.validattr?(name)
515
+ raise TypeError.new("Invalid parameter %s" % [name])
516
+ end
517
+
518
+ if name == :name
519
+ name = self.class.namevar
520
+ end
521
+ if value.nil?
522
+ raise Puppet::Error.new("Got nil value for %s" % name)
523
+ end
524
+
525
+ if obj = @parameters[name]
526
+ obj.value = value
527
+ return nil
528
+ else
529
+ self.newattr(name, :value => value)
530
+ end
531
+
532
+ nil
533
+ end
534
+
535
+ # remove a property from the object; useful in testing or in cleanup
536
+ # when an error has been encountered
537
+ def delete(attr)
538
+ attr = symbolize(attr)
539
+ if @parameters.has_key?(attr)
540
+ @parameters.delete(attr)
541
+ else
542
+ raise Puppet::DevError.new("Undefined attribute '#{attr}' in #{self}")
543
+ end
544
+ end
545
+
546
+ # iterate across the existing properties
547
+ def eachproperty
548
+ # properties() is a private method
549
+ properties().each { |property|
550
+ yield property
551
+ }
552
+ end
553
+
554
+ # retrieve the 'should' value for a specified property
555
+ def should(name)
556
+ name = attr_alias(name)
557
+ if prop = @parameters[name] and prop.is_a?(Puppet::Property)
558
+ return prop.should
559
+ else
560
+ return nil
561
+ end
562
+ end
563
+
564
+ # Create the actual attribute instance. Requires either the attribute
565
+ # name or class as the first argument, then an optional hash of
566
+ # attributes to set during initialization.
567
+ def newattr(name, options = {})
568
+ if name.is_a?(Class)
569
+ klass = name
570
+ name = klass.name
571
+ end
572
+
573
+ unless klass = self.class.attrclass(name)
574
+ raise Puppet::Error, "Resource type %s does not support parameter %s" % [self.class.name, name]
575
+ end
576
+
577
+ if @parameters.include?(name)
578
+ raise Puppet::Error, "Parameter '%s' is already defined in %s" %
579
+ [name, self.ref]
580
+ end
581
+
582
+ if provider and ! provider.class.supports_parameter?(klass)
583
+ missing = klass.required_features.find_all { |f| ! provider.class.feature?(f) }
584
+ info "Provider %s does not support features %s; not managing attribute %s" % [provider.class.name, missing.join(", "), name]
585
+ return nil
586
+ end
587
+
588
+ # Add resource information at creation time, so it's available
589
+ # during validation.
590
+ options[:resource] = self
591
+ begin
592
+ # make sure the parameter doesn't have any errors
593
+ return @parameters[name] = klass.new(options)
594
+ rescue => detail
595
+ error = Puppet::Error.new("Parameter %s failed: %s" %
596
+ [name, detail])
597
+ error.set_backtrace(detail.backtrace)
598
+ raise error
599
+ end
600
+ end
601
+
602
+ # return the value of a parameter
603
+ def parameter(name)
604
+ unless name.is_a? Symbol
605
+ name = name.intern
606
+ end
607
+ return @parameters[name].value
608
+ end
609
+
610
+ # Is the named property defined?
611
+ def propertydefined?(name)
612
+ unless name.is_a? Symbol
613
+ name = name.intern
614
+ end
615
+ return @parameters.include?(name)
616
+ end
617
+
618
+ # return an actual type by name; to return the value, use 'inst[name]'
619
+ # FIXME this method should go away
620
+ def property(name)
621
+ if obj = @parameters[symbolize(name)] and obj.is_a?(Puppet::Property)
622
+ return obj
623
+ else
624
+ return nil
625
+ end
626
+ end
627
+
628
+ # def set(name, value)
629
+ # send(name.to_s + "=", value)
630
+ # end
631
+ #
632
+ # def get(name)
633
+ # send(name)
634
+ # end
635
+
636
+ # For any parameters or properties that have defaults and have not yet been
637
+ # set, set them now. This method can be handed a list of attributes,
638
+ # and if so it will only set defaults for those attributes.
639
+ def setdefaults(*ary)
640
+ #self.class.eachattr(*ary) { |klass, type|
641
+ self.class.eachattr(*ary) { |klass, type|
642
+ # not many attributes will have defaults defined, so we short-circuit
643
+ # those away
644
+ next unless klass.method_defined?(:default)
645
+ next if @parameters[klass.name]
646
+
647
+ next unless obj = self.newattr(klass)
648
+
649
+ # We have to check for nil values, not "truth", so we allow defaults
650
+ # to false.
651
+ value = obj.default and ! value.nil?
652
+ if ! value.nil?
653
+ obj.value = value
654
+ else
655
+ @parameters.delete(obj.name)
656
+ end
657
+ }
658
+ end
659
+
660
+ # Convert our object to a hash. This just includes properties.
661
+ def to_hash
662
+ rethash = {}
663
+
664
+ @parameters.each do |name, obj|
665
+ rethash[name] = obj.value
666
+ end
667
+
668
+ rethash
669
+ end
670
+
671
+ # Return a specific value for an attribute.
672
+ def value(name)
673
+ name = attr_alias(name)
674
+
675
+ if obj = @parameters[name] and obj.respond_to?(:value)
676
+ return obj.value
677
+ else
678
+ return nil
679
+ end
680
+ end
681
+
682
+ # Meta-parameter methods: These methods deal with the results
683
+ # of specifying metaparameters
684
+
685
+ private
686
+
687
+ # Return all of the property objects, in the order specified in the
688
+ # class.
689
+ def properties
690
+ #debug "%s has %s properties" % [self,@parameters.length]
691
+ props = self.class.properties.collect { |prop|
692
+ @parameters[prop.name]
693
+ }.find_all { |p|
694
+ ! p.nil?
695
+ }.each do |prop|
696
+ unless prop.is_a?(Puppet::Property)
697
+ raise Puppet::DevError, "got a non-property %s(%s)" %
698
+ [prop.class, prop.class.name]
699
+ end
700
+ end
701
+
702
+ props
703
+ end
704
+
705
+ public
706
+
707
+ ###############################
708
+ # Code related to the closure-like behaviour of the resource classes.
709
+ attr_writer :implicit
710
+
711
+ # Is this type's name isomorphic with the object? That is, if the
712
+ # name conflicts, does it necessarily mean that the objects conflict?
713
+ # Defaults to true.
714
+ def self.isomorphic?
715
+ if defined? @isomorphic
716
+ return @isomorphic
717
+ else
718
+ return true
719
+ end
720
+ end
721
+
722
+ def implicit?
723
+ if defined? @implicit and @implicit
724
+ return true
725
+ else
726
+ return false
727
+ end
728
+ end
729
+
730
+ def isomorphic?
731
+ self.class.isomorphic?
732
+ end
733
+
734
+ # is the instance a managed instance? A 'yes' here means that
735
+ # the instance was created from the language, vs. being created
736
+ # in order resolve other questions, such as finding a package
737
+ # in a list
738
+ def managed?
739
+ # Once an object is managed, it always stays managed; but an object
740
+ # that is listed as unmanaged might become managed later in the process,
741
+ # so we have to check that every time
742
+ if defined? @managed and @managed
743
+ return @managed
744
+ else
745
+ @managed = false
746
+ properties.each { |property|
747
+ s = property.should
748
+ if s and ! property.class.unmanaged
749
+ @managed = true
750
+ break
751
+ end
752
+ }
753
+ return @managed
754
+ end
755
+ end
756
+
757
+ ###############################
758
+ # Code related to the container behaviour.
759
+ def self.depthfirst?
760
+ if defined? @depthfirst
761
+ return @depthfirst
762
+ else
763
+ return false
764
+ end
765
+ end
766
+
767
+ def depthfirst?
768
+ self.class.depthfirst?
769
+ end
770
+
771
+ # Add a hook for testing for recursion.
772
+ def parentof?(child)
773
+ if (self == child)
774
+ debug "parent is equal to child"
775
+ return true
776
+ elsif defined? @parent and @parent.parentof?(child)
777
+ debug "My parent is parent of child"
778
+ return true
779
+ else
780
+ return false
781
+ end
782
+ end
783
+
784
+ # Remove an object. The argument determines whether the object's
785
+ # subscriptions get eliminated, too.
786
+ def remove(rmdeps = true)
787
+ # This is hackish (mmm, cut and paste), but it works for now, and it's
788
+ # better than warnings.
789
+ @parameters.each do |name, obj|
790
+ obj.remove
791
+ end
792
+ @parameters.clear
793
+ self.class.delete(self)
794
+
795
+ @parent = nil
796
+
797
+ # Remove the reference to the provider.
798
+ if self.provider
799
+ @provider.clear
800
+ @provider = nil
801
+ end
802
+ end
803
+
804
+ ###############################
805
+ # Code related to evaluating the resources.
806
+
807
+ # This method is responsible for collecting property changes we always
808
+ # descend into the children before we evaluate our current properties.
809
+ # This returns any changes resulting from testing, thus 'collect' rather
810
+ # than 'each'.
811
+ def evaluate
812
+ if self.provider.is_a?(Puppet::Provider)
813
+ unless provider.class.suitable?
814
+ raise Puppet::Error, "Provider %s is not functional on this platform" % provider.class.name
815
+ end
816
+ end
817
+ #Puppet.err "Evaluating %s" % self.path.join(":")
818
+ unless defined? @evalcount
819
+ self.err "No evalcount defined on '%s' of type '%s'" %
820
+ [self.title,self.class]
821
+ @evalcount = 0
822
+ end
823
+ @evalcount += 1
824
+
825
+ if p = self.provider and p.respond_to?(:prefetch)
826
+ p.prefetch
827
+ end
828
+
829
+ # this only operates on properties, not properties + children
830
+ # it's important that we call retrieve() on the type instance,
831
+ # not directly on the property, because it allows the type to override
832
+ # the method, like pfile does
833
+ currentvalues = self.retrieve
834
+
835
+ changes = propertychanges(currentvalues).flatten
836
+
837
+ # now record how many changes we've resulted in
838
+ if changes.length > 0
839
+ self.debug "%s change(s)" %
840
+ [changes.length]
841
+ end
842
+
843
+ # If we're in noop mode, we don't want to store the checked time,
844
+ # because it will result in the resource not getting scheduled if
845
+ # someone were to apply the catalog in non-noop mode.
846
+ # We're going to go ahead and record that we checked if there were
847
+ # no changes, since it's unlikely it will affect the scheduling.
848
+ noop = noop?
849
+ if ! noop or (noop && changes.length == 0)
850
+ self.cache(:checked, Time.now)
851
+ end
852
+ return changes.flatten
853
+ end
854
+
855
+ # Flush the provider, if it supports it. This is called by the
856
+ # transaction.
857
+ def flush
858
+ if self.provider and self.provider.respond_to?(:flush)
859
+ self.provider.flush
860
+ end
861
+ end
862
+
863
+ # if all contained objects are in sync, then we're in sync
864
+ # FIXME I don't think this is used on the type instances any more,
865
+ # it's really only used for testing
866
+ def insync?(is)
867
+ insync = true
868
+
869
+ if property = @parameters[:ensure]
870
+ unless is.include? property
871
+ raise Puppet::DevError,
872
+ "The is value is not in the is array for '%s'" %
873
+ [property.name]
874
+ end
875
+ ensureis = is[property]
876
+ if property.insync?(ensureis) and property.should == :absent
877
+ return true
878
+ end
879
+ end
880
+
881
+ properties.each { |property|
882
+ unless is.include? property
883
+ raise Puppet::DevError,
884
+ "The is value is not in the is array for '%s'" %
885
+ [property.name]
886
+ end
887
+
888
+ propis = is[property]
889
+ unless property.insync?(propis)
890
+ property.debug("Not in sync: %s vs %s" %
891
+ [propis.inspect, property.should.inspect])
892
+ insync = false
893
+ #else
894
+ # property.debug("In sync")
895
+ end
896
+ }
897
+
898
+ #self.debug("%s sync status is %s" % [self,insync])
899
+ return insync
900
+ end
901
+
902
+ # retrieve the current value of all contained properties
903
+ def retrieve
904
+ return currentpropvalues
905
+ end
906
+
907
+ # Get a hash of the current properties. Returns a hash with
908
+ # the actual property instance as the key and the current value
909
+ # as the, um, value.
910
+ def currentpropvalues
911
+ # It's important to use the 'properties' method here, as it follows the order
912
+ # in which they're defined in the class. It also guarantees that 'ensure'
913
+ # is the first property, which is important for skipping 'retrieve' on
914
+ # all the properties if the resource is absent.
915
+ ensure_state = false
916
+ return properties().inject({}) do | prophash, property|
917
+ if property.name == :ensure
918
+ ensure_state = property.retrieve
919
+ prophash[property] = ensure_state
920
+ else
921
+ if ensure_state == :absent
922
+ prophash[property] = :absent
923
+ else
924
+ prophash[property] = property.retrieve
925
+ end
926
+ end
927
+ prophash
928
+ end
929
+ end
930
+
931
+ # Are we running in noop mode?
932
+ def noop?
933
+ if defined?(@noop)
934
+ @noop
935
+ else
936
+ Puppet[:noop]
937
+ end
938
+ end
939
+
940
+ def noop
941
+ noop?
942
+ end
943
+
944
+ # Retrieve the changes associated with all of the properties.
945
+ def propertychanges(currentvalues)
946
+ # If we are changing the existence of the object, then none of
947
+ # the other properties matter.
948
+ changes = []
949
+ ensureparam = @parameters[:ensure]
950
+
951
+ # This allows resource types to have 'ensure' be a parameter, which allows them to
952
+ # just pass the parameter on to other generated resources.
953
+ ensureparam = nil unless ensureparam.is_a?(Puppet::Property)
954
+ if ensureparam && !currentvalues.include?(ensureparam)
955
+ raise Puppet::DevError, "Parameter ensure defined but missing from current values"
956
+ end
957
+
958
+ if ensureparam and ! ensureparam.insync?(currentvalues[ensureparam])
959
+ changes << Puppet::Transaction::Change.new(ensureparam, currentvalues[ensureparam])
960
+ # Else, if the 'ensure' property is correctly absent, then do
961
+ # nothing
962
+ elsif ensureparam and currentvalues[ensureparam] == :absent
963
+ return []
964
+ else
965
+ changes = properties().find_all { |property|
966
+ currentvalues[property] ||= :absent
967
+ ! property.insync?(currentvalues[property])
968
+ }.collect { |property|
969
+ Puppet::Transaction::Change.new(property, currentvalues[property])
970
+ }
971
+ end
972
+
973
+ if Puppet[:debug] and changes.length > 0
974
+ self.debug("Changing " + changes.collect { |ch| ch.property.name }.join(","))
975
+ end
976
+
977
+ changes
978
+ end
979
+
980
+ ###############################
981
+ # Code related to managing resource instances.
982
+ require 'puppet/transportable'
983
+
984
+ # Make 'new' private, so people have to use create instead.
985
+ class << self
986
+ private :new
987
+ end
988
+
989
+ # retrieve a named instance of the current type
990
+ def self.[](name)
991
+ @objects[name] || @aliases[name]
992
+ end
993
+
994
+ # add an instance by name to the class list of instances
995
+ def self.[]=(name,object)
996
+ newobj = nil
997
+ if object.is_a?(Puppet::Type)
998
+ newobj = object
999
+ else
1000
+ raise Puppet::DevError, "must pass a Puppet::Type object"
1001
+ end
1002
+
1003
+ if exobj = @objects[name] and self.isomorphic?
1004
+ msg = "Object '%s[%s]' already exists" %
1005
+ [newobj.class.name, name]
1006
+
1007
+ if exobj.file and exobj.line
1008
+ msg += ("in file %s at line %s" %
1009
+ [object.file, object.line])
1010
+ end
1011
+ if object.file and object.line
1012
+ msg += ("and cannot be redefined in file %s at line %s" %
1013
+ [object.file, object.line])
1014
+ end
1015
+ error = Puppet::Error.new(msg)
1016
+ raise error
1017
+ else
1018
+ #Puppet.info("adding %s of type %s to class list" %
1019
+ # [name,object.class])
1020
+ @objects[name] = newobj
1021
+ end
1022
+ end
1023
+
1024
+ # Create an alias. We keep these in a separate hash so that we don't encounter
1025
+ # the objects multiple times when iterating over them.
1026
+ def self.alias(name, obj)
1027
+ if @objects.include?(name)
1028
+ unless @objects[name] == obj
1029
+ raise Puppet::Error.new(
1030
+ "Cannot create alias %s: object already exists" %
1031
+ [name]
1032
+ )
1033
+ end
1034
+ end
1035
+
1036
+ if @aliases.include?(name)
1037
+ unless @aliases[name] == obj
1038
+ raise Puppet::Error.new(
1039
+ "Object %s already has alias %s" %
1040
+ [@aliases[name].name, name]
1041
+ )
1042
+ end
1043
+ end
1044
+
1045
+ @aliases[name] = obj
1046
+ end
1047
+
1048
+ # remove all of the instances of a single type
1049
+ def self.clear
1050
+ if defined? @objects
1051
+ @objects.each do |name, obj|
1052
+ obj.remove(true)
1053
+ end
1054
+ @objects.clear
1055
+ end
1056
+ if defined? @aliases
1057
+ @aliases.clear
1058
+ end
1059
+ end
1060
+
1061
+ # Force users to call this, so that we can merge objects if
1062
+ # necessary.
1063
+ def self.create(args)
1064
+ # Don't modify the original hash; instead, create a duplicate and modify it.
1065
+ # We have to dup and use the ! so that it stays a TransObject if it is
1066
+ # one.
1067
+ hash = args.dup
1068
+ symbolizehash!(hash)
1069
+
1070
+ # If we're the base class, then pass the info on appropriately
1071
+ if self == Puppet::Type
1072
+ type = nil
1073
+ if hash.is_a? Puppet::TransObject
1074
+ type = hash.type
1075
+ else
1076
+ # If we're using the type to determine object type, then delete it
1077
+ if type = hash[:type]
1078
+ hash.delete(:type)
1079
+ end
1080
+ end
1081
+
1082
+ # If they've specified a type and called on the base, then
1083
+ # delegate to the subclass.
1084
+ if type
1085
+ if typeklass = self.type(type)
1086
+ return typeklass.create(hash)
1087
+ else
1088
+ raise Puppet::Error, "Unknown type %s" % type
1089
+ end
1090
+ else
1091
+ raise Puppet::Error, "No type found for %s" % hash.inspect
1092
+ end
1093
+ end
1094
+
1095
+ # Handle this new object being implicit
1096
+ implicit = hash[:implicit] || false
1097
+ if hash.include?(:implicit)
1098
+ hash.delete(:implicit)
1099
+ end
1100
+
1101
+ name = nil
1102
+ unless hash.is_a? Puppet::TransObject
1103
+ hash = self.hash2trans(hash)
1104
+ end
1105
+
1106
+ # XXX This will have to change when transobjects change to using titles
1107
+ title = hash.name
1108
+
1109
+ # if the object already exists
1110
+ if self.isomorphic? and retobj = self[title]
1111
+ # if only one of our objects is implicit, then it's easy to see
1112
+ # who wins -- the non-implicit one.
1113
+ if retobj.implicit? and ! implicit
1114
+ Puppet.notice "Removing implicit %s" % retobj.title
1115
+ # Remove all of the objects, but do not remove their subscriptions.
1116
+ retobj.remove(false)
1117
+
1118
+ # now pass through and create the new object
1119
+ elsif implicit
1120
+ Puppet.debug "Ignoring implicit %s[%s]" % [self.name, title]
1121
+ return nil
1122
+ else
1123
+ raise Puppet::Error, "%s is already being managed" % retobj.ref
1124
+ end
1125
+ end
1126
+
1127
+ # create it anew
1128
+ # if there's a failure, destroy the object if it got that far, but raise
1129
+ # the error.
1130
+ begin
1131
+ obj = new(hash)
1132
+ rescue => detail
1133
+ Puppet.err "Could not create %s: %s" % [title, detail.to_s]
1134
+ if obj
1135
+ obj.remove(true)
1136
+ elsif obj = self[title]
1137
+ obj.remove(true)
1138
+ end
1139
+ raise
1140
+ end
1141
+
1142
+ if implicit
1143
+ obj.implicit = true
1144
+ end
1145
+
1146
+ # Store the object by title
1147
+ self[obj.title] = obj
1148
+
1149
+ return obj
1150
+ end
1151
+
1152
+ # remove a specified object
1153
+ def self.delete(resource)
1154
+ return unless defined? @objects
1155
+ if @objects.include?(resource.title)
1156
+ @objects.delete(resource.title)
1157
+ end
1158
+ if @aliases.include?(resource.title)
1159
+ @aliases.delete(resource.title)
1160
+ end
1161
+ if @aliases.has_value?(resource)
1162
+ names = []
1163
+ @aliases.each do |name, otherres|
1164
+ if otherres == resource
1165
+ names << name
1166
+ end
1167
+ end
1168
+ names.each { |name| @aliases.delete(name) }
1169
+ end
1170
+ end
1171
+
1172
+ # iterate across each of the type's instances
1173
+ def self.each
1174
+ return unless defined? @objects
1175
+ @objects.each { |name,instance|
1176
+ yield instance
1177
+ }
1178
+ end
1179
+
1180
+ # does the type have an object with the given name?
1181
+ def self.has_key?(name)
1182
+ return @objects.has_key?(name)
1183
+ end
1184
+
1185
+ # Convert a hash to a TransObject.
1186
+ def self.hash2trans(hash)
1187
+ title = nil
1188
+ if hash.include? :title
1189
+ title = hash[:title]
1190
+ hash.delete(:title)
1191
+ elsif hash.include? self.namevar
1192
+ title = hash[self.namevar]
1193
+ hash.delete(self.namevar)
1194
+
1195
+ if hash.include? :name
1196
+ raise ArgumentError, "Cannot provide both name and %s to %s" %
1197
+ [self.namevar, self.name]
1198
+ end
1199
+ elsif hash[:name]
1200
+ title = hash[:name]
1201
+ hash.delete :name
1202
+ end
1203
+
1204
+ if catalog = hash[:catalog]
1205
+ hash.delete(:catalog)
1206
+ end
1207
+
1208
+ raise(Puppet::Error, "You must specify a title for objects of type %s" % self.to_s) unless title
1209
+
1210
+ if hash.include? :type
1211
+ unless self.validattr? :type
1212
+ hash.delete :type
1213
+ end
1214
+ end
1215
+
1216
+ # okay, now make a transobject out of hash
1217
+ begin
1218
+ trans = Puppet::TransObject.new(title, self.name.to_s)
1219
+ trans.catalog = catalog if catalog
1220
+ hash.each { |param, value|
1221
+ trans[param] = value
1222
+ }
1223
+ rescue => detail
1224
+ raise Puppet::Error, "Could not create %s: %s" %
1225
+ [name, detail]
1226
+ end
1227
+
1228
+ return trans
1229
+ end
1230
+
1231
+ # Retrieve all known instances. Either requires providers or must be overridden.
1232
+ def self.instances
1233
+ unless defined?(@providers) and ! @providers.empty?
1234
+ raise Puppet::DevError, "%s has no providers and has not overridden 'instances'" % self.name
1235
+ end
1236
+
1237
+ # Put the default provider first, then the rest of the suitable providers.
1238
+ provider_instances = {}
1239
+ providers_by_source.collect do |provider|
1240
+ provider.instances.collect do |instance|
1241
+ # First try to get the resource if it already exists
1242
+ # Skip instances that map to a managed resource with a different provider
1243
+ next if resource = self[instance.name] and resource.provider.class != instance.class
1244
+
1245
+ # We always want to use the "first" provider instance we find, unless the resource
1246
+ # is already managed and has a different provider set
1247
+ if other = provider_instances[instance.name]
1248
+ Puppet.warning "%s %s found in both %s and %s; skipping the %s version" %
1249
+ [self.name.to_s.capitalize, instance.name, other.class.name, instance.class.name, instance.class.name]
1250
+ next
1251
+ end
1252
+ provider_instances[instance.name] = instance
1253
+
1254
+ if resource
1255
+ resource.provider = instance
1256
+ resource
1257
+ else
1258
+ create(:name => instance.name, :provider => instance, :check => :all)
1259
+ end
1260
+ end
1261
+ end.flatten.compact
1262
+ end
1263
+
1264
+ # Return a list of one suitable provider per source, with the default provider first.
1265
+ def self.providers_by_source
1266
+ # Put the default provider first, then the rest of the suitable providers.
1267
+ sources = []
1268
+ [defaultprovider, suitableprovider].flatten.uniq.collect do |provider|
1269
+ next if sources.include?(provider.source)
1270
+
1271
+ sources << provider.source
1272
+ provider
1273
+ end.compact
1274
+ end
1275
+
1276
+ # Create the path for logging and such.
1277
+ def pathbuilder
1278
+ if p = parent
1279
+ [p.pathbuilder, self.ref].flatten
1280
+ else
1281
+ [self.ref]
1282
+ end
1283
+ end
1284
+
1285
+ ###############################
1286
+ # Add all of the meta parameters.
1287
+ newmetaparam(:noop) do
1288
+ desc "Boolean flag indicating whether work should actually
1289
+ be done."
1290
+
1291
+ newvalues(:true, :false)
1292
+ munge do |value|
1293
+ case value
1294
+ when true, :true, "true": @resource.noop = true
1295
+ when false, :false, "false": @resource.noop = false
1296
+ end
1297
+ end
1298
+ end
1299
+
1300
+ newmetaparam(:schedule) do
1301
+ desc "On what schedule the object should be managed. You must create a
1302
+ schedule object, and then reference the name of that object to use
1303
+ that for your schedule::
1304
+
1305
+ schedule { daily:
1306
+ period => daily,
1307
+ range => \"2-4\"
1308
+ }
1309
+
1310
+ exec { \"/usr/bin/apt-get update\":
1311
+ schedule => daily
1312
+ }
1313
+
1314
+ The creation of the schedule object does not need to appear in the
1315
+ configuration before objects that use it."
1316
+ end
1317
+
1318
+ newmetaparam(:check) do
1319
+ desc "Propertys which should have their values retrieved
1320
+ but which should not actually be modified. This is currently used
1321
+ internally, but will eventually be used for querying, so that you
1322
+ could specify that you wanted to check the install state of all
1323
+ packages, and then query the Puppet client daemon to get reports
1324
+ on all packages."
1325
+
1326
+ munge do |args|
1327
+ # If they've specified all, collect all known properties
1328
+ if args == :all
1329
+ args = @resource.class.properties.find_all do |property|
1330
+ # Only get properties supported by our provider
1331
+ if @resource.provider
1332
+ @resource.provider.class.supports_parameter?(property)
1333
+ else
1334
+ true
1335
+ end
1336
+ end.collect do |property|
1337
+ property.name
1338
+ end
1339
+ end
1340
+
1341
+ unless args.is_a?(Array)
1342
+ args = [args]
1343
+ end
1344
+
1345
+ unless defined? @resource
1346
+ self.devfail "No parent for %s, %s?" %
1347
+ [self.class, self.name]
1348
+ end
1349
+
1350
+ args.each { |property|
1351
+ unless property.is_a?(Symbol)
1352
+ property = property.intern
1353
+ end
1354
+ next if @resource.propertydefined?(property)
1355
+
1356
+ unless propertyklass = @resource.class.validproperty?(property)
1357
+ if @resource.class.validattr?(property)
1358
+ next
1359
+ else
1360
+ raise Puppet::Error, "%s is not a valid attribute for %s" %
1361
+ [property, self.class.name]
1362
+ end
1363
+ end
1364
+ next unless propertyklass.checkable?
1365
+ @resource.newattr(property)
1366
+ }
1367
+ end
1368
+ end
1369
+
1370
+ # We've got four relationship metaparameters, so this method is used
1371
+ # to reduce code duplication between them.
1372
+ def munge_relationship(param, values)
1373
+ # We need to support values passed in as an array or as a
1374
+ # resource reference.
1375
+ result = []
1376
+
1377
+ # 'values' could be an array or a reference. If it's an array,
1378
+ # it could be an array of references or an array of arrays.
1379
+ if values.is_a?(Puppet::Type)
1380
+ result << [values.class.name, values.title]
1381
+ else
1382
+ unless values.is_a?(Array)
1383
+ devfail "Relationships must be resource references"
1384
+ end
1385
+ if values[0].is_a?(String) or values[0].is_a?(Symbol)
1386
+ # we're a type/title array reference
1387
+ values[0] = symbolize(values[0])
1388
+ result << values
1389
+ else
1390
+ # we're an array of stuff
1391
+ values.each do |value|
1392
+ if value.is_a?(Puppet::Type)
1393
+ result << [value.class.name, value.title]
1394
+ elsif value.is_a?(Array)
1395
+ value[0] = symbolize(value[0])
1396
+ result << value
1397
+ else
1398
+ devfail "Invalid relationship %s" % value.inspect
1399
+ end
1400
+ end
1401
+ end
1402
+ end
1403
+
1404
+ if existing = self[param]
1405
+ result = existing + result
1406
+ end
1407
+
1408
+ result
1409
+ end
1410
+
1411
+ newmetaparam(:loglevel) do
1412
+ desc "Sets the level that information will be logged.
1413
+ The log levels have the biggest impact when logs are sent to
1414
+ syslog (which is currently the default)."
1415
+ defaultto :notice
1416
+
1417
+ newvalues(*Puppet::Util::Log.levels)
1418
+ newvalues(:verbose)
1419
+
1420
+ munge do |loglevel|
1421
+ val = super(loglevel)
1422
+ if val == :verbose
1423
+ val = :info
1424
+ end
1425
+ val
1426
+ end
1427
+ end
1428
+
1429
+ newmetaparam(:alias) do
1430
+ desc "Creates an alias for the object. Puppet uses this internally when you
1431
+ provide a symbolic name::
1432
+
1433
+ file { sshdconfig:
1434
+ path => $operatingsystem ? {
1435
+ solaris => \"/usr/local/etc/ssh/sshd_config\",
1436
+ default => \"/etc/ssh/sshd_config\"
1437
+ },
1438
+ source => \"...\"
1439
+ }
1440
+
1441
+ service { sshd:
1442
+ subscribe => file[sshdconfig]
1443
+ }
1444
+
1445
+ When you use this feature, the parser sets ``sshdconfig`` as the name,
1446
+ and the library sets that as an alias for the file so the dependency
1447
+ lookup for ``sshd`` works. You can use this parameter yourself,
1448
+ but note that only the library can use these aliases; for instance,
1449
+ the following code will not work::
1450
+
1451
+ file { \"/etc/ssh/sshd_config\":
1452
+ owner => root,
1453
+ group => root,
1454
+ alias => sshdconfig
1455
+ }
1456
+
1457
+ file { sshdconfig:
1458
+ mode => 644
1459
+ }
1460
+
1461
+ There's no way here for the Puppet parser to know that these two stanzas
1462
+ should be affecting the same file.
1463
+
1464
+ See the `LanguageTutorial language tutorial`:trac: for more information.
1465
+
1466
+ "
1467
+
1468
+ munge do |aliases|
1469
+ unless aliases.is_a?(Array)
1470
+ aliases = [aliases]
1471
+ end
1472
+
1473
+ raise(ArgumentError, "Cannot add aliases without a catalog") unless @resource.catalog
1474
+
1475
+ aliases.each do |other|
1476
+ if obj = @resource.catalog.resource(@resource.class.name, other)
1477
+ unless obj.object_id == @resource.object_id
1478
+ self.fail("%s can not create alias %s: object already exists" % [@resource.title, other])
1479
+ end
1480
+ next
1481
+ end
1482
+
1483
+ # LAK:FIXME Old-school, add the alias to the class.
1484
+ @resource.class.alias(other, @resource)
1485
+
1486
+ # Newschool, add it to the catalog.
1487
+ @resource.catalog.alias(@resource, other)
1488
+ end
1489
+ end
1490
+ end
1491
+
1492
+ newmetaparam(:tag) do
1493
+ desc "Add the specified tags to the associated resource. While all resources
1494
+ are automatically tagged with as much information as possible
1495
+ (e.g., each class and definition containing the resource), it can
1496
+ be useful to add your own tags to a given resource.
1497
+
1498
+ Tags are currently useful for things like applying a subset of a
1499
+ host's configuration::
1500
+
1501
+ puppetd --test --tags mytag
1502
+
1503
+ This way, when you're testing a configuration you can run just the
1504
+ portion you're testing."
1505
+
1506
+ munge do |tags|
1507
+ tags = [tags] unless tags.is_a? Array
1508
+
1509
+ tags.each do |tag|
1510
+ @resource.tag(tag)
1511
+ end
1512
+ end
1513
+ end
1514
+
1515
+ class RelationshipMetaparam < Puppet::Parameter
1516
+ class << self
1517
+ attr_accessor :direction, :events, :callback, :subclasses
1518
+ end
1519
+
1520
+ @subclasses = []
1521
+
1522
+ def self.inherited(sub)
1523
+ @subclasses << sub
1524
+ end
1525
+
1526
+ def munge(rels)
1527
+ @resource.munge_relationship(self.class.name, rels)
1528
+ end
1529
+
1530
+ def validate_relationship
1531
+ @value.each do |value|
1532
+ unless @resource.catalog.resource(*value)
1533
+ description = self.class.direction == :in ? "dependency" : "dependent"
1534
+ fail Puppet::Error, "Could not find %s %s[%s] for %s" %
1535
+ [description, value[0].to_s.capitalize, value[1], resource.ref]
1536
+ end
1537
+ end
1538
+ end
1539
+
1540
+ # Create edges from each of our relationships. :in
1541
+ # relationships are specified by the event-receivers, and :out
1542
+ # relationships are specified by the event generator. This
1543
+ # way 'source' and 'target' are consistent terms in both edges
1544
+ # and events -- that is, an event targets edges whose source matches
1545
+ # the event's source. The direction of the relationship determines
1546
+ # which resource is applied first and which resource is considered
1547
+ # to be the event generator.
1548
+ def to_edges
1549
+ @value.collect do |value|
1550
+ # we just have a name and a type, and we need to convert it
1551
+ # to an object...
1552
+ tname, name = value
1553
+ reference = Puppet::ResourceReference.new(tname, name)
1554
+
1555
+ # Either of the two retrieval attempts could have returned
1556
+ # nil.
1557
+ unless object = reference.resolve
1558
+ self.fail "Could not retrieve dependency '%s' of %s" % [reference, @resource.ref]
1559
+ end
1560
+
1561
+ # Are we requiring them, or vice versa? See the method docs
1562
+ # for futher info on this.
1563
+ if self.class.direction == :in
1564
+ source = object
1565
+ target = @resource
1566
+ else
1567
+ source = @resource
1568
+ target = object
1569
+ end
1570
+
1571
+ if method = self.class.callback
1572
+ subargs = {
1573
+ :event => self.class.events,
1574
+ :callback => method
1575
+ }
1576
+ self.debug("subscribes to %s" % [object.ref])
1577
+ else
1578
+ # If there's no callback, there's no point in even adding
1579
+ # a label.
1580
+ subargs = nil
1581
+ self.debug("requires %s" % [object.ref])
1582
+ end
1583
+
1584
+ rel = Puppet::Relationship.new(source, target, subargs)
1585
+ end
1586
+ end
1587
+ end
1588
+
1589
+ def self.relationship_params
1590
+ RelationshipMetaparam.subclasses
1591
+ end
1592
+
1593
+
1594
+ # Note that the order in which the relationships params is defined
1595
+ # matters. The labelled params (notify and subcribe) must be later,
1596
+ # so that if both params are used, those ones win. It's a hackish
1597
+ # solution, but it works.
1598
+
1599
+ newmetaparam(:require, :parent => RelationshipMetaparam, :attributes => {:direction => :in, :events => :NONE}) do
1600
+ desc "One or more objects that this object depends on.
1601
+ This is used purely for guaranteeing that changes to required objects
1602
+ happen before the dependent object. For instance::
1603
+
1604
+ # Create the destination directory before you copy things down
1605
+ file { \"/usr/local/scripts\":
1606
+ ensure => directory
1607
+ }
1608
+
1609
+ file { \"/usr/local/scripts/myscript\":
1610
+ source => \"puppet://server/module/myscript\",
1611
+ mode => 755,
1612
+ require => File[\"/usr/local/scripts\"]
1613
+ }
1614
+
1615
+ Multiple dependencies can be specified by providing a comma-seperated list
1616
+ of resources, enclosed in square brackets::
1617
+
1618
+ require => [ File[\"/usr/local\"], File[\"/usr/local/scripts\"] ]
1619
+
1620
+ Note that Puppet will autorequire everything that it can, and
1621
+ there are hooks in place so that it's easy for resources to add new
1622
+ ways to autorequire objects, so if you think Puppet could be
1623
+ smarter here, let us know.
1624
+
1625
+ In fact, the above code was redundant -- Puppet will autorequire
1626
+ any parent directories that are being managed; it will
1627
+ automatically realize that the parent directory should be created
1628
+ before the script is pulled down.
1629
+
1630
+ Currently, exec resources will autorequire their CWD (if it is
1631
+ specified) plus any fully qualified paths that appear in the
1632
+ command. For instance, if you had an ``exec`` command that ran
1633
+ the ``myscript`` mentioned above, the above code that pulls the
1634
+ file down would be automatically listed as a requirement to the
1635
+ ``exec`` code, so that you would always be running againts the
1636
+ most recent version.
1637
+ "
1638
+ end
1639
+
1640
+ newmetaparam(:subscribe, :parent => RelationshipMetaparam, :attributes => {:direction => :in, :events => :ALL_EVENTS, :callback => :refresh}) do
1641
+ desc "One or more objects that this object depends on. Changes in the
1642
+ subscribed to objects result in the dependent objects being
1643
+ refreshed (e.g., a service will get restarted). For instance::
1644
+
1645
+ class nagios {
1646
+ file { \"/etc/nagios/nagios.conf\":
1647
+ source => \"puppet://server/module/nagios.conf\",
1648
+ alias => nagconf # just to make things easier for me
1649
+ }
1650
+ service { nagios:
1651
+ running => true,
1652
+ subscribe => File[nagconf]
1653
+ }
1654
+ }
1655
+
1656
+ Currently the ``exec``, ``mount`` and ``service`` type support
1657
+ refreshing.
1658
+ "
1659
+ end
1660
+
1661
+ newmetaparam(:before, :parent => RelationshipMetaparam, :attributes => {:direction => :out, :events => :NONE}) do
1662
+ desc %{This parameter is the opposite of **require** -- it guarantees
1663
+ that the specified object is applied later than the specifying
1664
+ object::
1665
+
1666
+ file { "/var/nagios/configuration":
1667
+ source => "...",
1668
+ recurse => true,
1669
+ before => Exec["nagios-rebuid"]
1670
+ }
1671
+
1672
+ exec { "nagios-rebuild":
1673
+ command => "/usr/bin/make",
1674
+ cwd => "/var/nagios/configuration"
1675
+ }
1676
+
1677
+ This will make sure all of the files are up to date before the
1678
+ make command is run.}
1679
+ end
1680
+
1681
+ newmetaparam(:notify, :parent => RelationshipMetaparam, :attributes => {:direction => :out, :events => :ALL_EVENTS, :callback => :refresh}) do
1682
+ desc %{This parameter is the opposite of **subscribe** -- it sends events
1683
+ to the specified object::
1684
+
1685
+ file { "/etc/sshd_config":
1686
+ source => "....",
1687
+ notify => Service[sshd]
1688
+ }
1689
+
1690
+ service { sshd:
1691
+ ensure => running
1692
+ }
1693
+
1694
+ This will restart the sshd service if the sshd config file changes.}
1695
+ end
1696
+
1697
+ ###############################
1698
+ # All of the provider plumbing for the resource types.
1699
+ require 'puppet/provider'
1700
+ require 'puppet/util/provider_features'
1701
+
1702
+ # Add the feature handling module.
1703
+ extend Puppet::Util::ProviderFeatures
1704
+
1705
+ attr_reader :provider
1706
+
1707
+ # the Type class attribute accessors
1708
+ class << self
1709
+ attr_accessor :providerloader
1710
+ attr_writer :defaultprovider
1711
+ end
1712
+
1713
+ # Find the default provider.
1714
+ def self.defaultprovider
1715
+ unless defined? @defaultprovider and @defaultprovider
1716
+ suitable = suitableprovider()
1717
+
1718
+ # Find which providers are a default for this system.
1719
+ defaults = suitable.find_all { |provider| provider.default? }
1720
+
1721
+ # If we don't have any default we use suitable providers
1722
+ defaults = suitable if defaults.empty?
1723
+ max = defaults.collect { |provider| provider.defaultnum }.max
1724
+ defaults = defaults.find_all { |provider| provider.defaultnum == max }
1725
+
1726
+ retval = nil
1727
+ if defaults.length > 1
1728
+ Puppet.warning(
1729
+ "Found multiple default providers for %s: %s; using %s" %
1730
+ [self.name, defaults.collect { |i| i.name.to_s }.join(", "),
1731
+ defaults[0].name]
1732
+ )
1733
+ retval = defaults.shift
1734
+ elsif defaults.length == 1
1735
+ retval = defaults.shift
1736
+ else
1737
+ raise Puppet::DevError, "Could not find a default provider for %s" %
1738
+ self.name
1739
+ end
1740
+
1741
+ @defaultprovider = retval
1742
+ end
1743
+
1744
+ return @defaultprovider
1745
+ end
1746
+
1747
+ # Convert a hash, as provided by, um, a provider, into an instance of self.
1748
+ def self.hash2obj(hash)
1749
+ obj = nil
1750
+
1751
+ namevar = self.namevar
1752
+ unless hash.include?(namevar) and hash[namevar]
1753
+ raise Puppet::DevError, "Hash was not passed with namevar"
1754
+ end
1755
+
1756
+ # if the obj already exists with that name...
1757
+ if obj = self[hash[namevar]]
1758
+ # We're assuming here that objects with the same name
1759
+ # are the same object, which *should* be the case, assuming
1760
+ # we've set up our naming stuff correctly everywhere.
1761
+
1762
+ # Mark found objects as present
1763
+ hash.each { |param, value|
1764
+ if property = obj.property(param)
1765
+ elsif val = obj[param]
1766
+ obj[param] = val
1767
+ else
1768
+ # There is a value on disk, but it should go away
1769
+ obj[param] = :absent
1770
+ end
1771
+ }
1772
+ else
1773
+ # create a new obj, since no existing one seems to
1774
+ # match
1775
+ obj = self.create(namevar => hash[namevar])
1776
+
1777
+ # We can't just pass the hash in at object creation time,
1778
+ # because it sets the should value, not the is value.
1779
+ hash.delete(namevar)
1780
+ hash.each { |param, value|
1781
+ obj[param] = value unless obj.add_property_parameter(param)
1782
+ }
1783
+ end
1784
+
1785
+ return obj
1786
+ end
1787
+
1788
+ # Retrieve a provider by name.
1789
+ def self.provider(name)
1790
+ name = Puppet::Util.symbolize(name)
1791
+
1792
+ # If we don't have it yet, try loading it.
1793
+ unless @providers.has_key?(name)
1794
+ @providerloader.load(name)
1795
+ end
1796
+ return @providers[name]
1797
+ end
1798
+
1799
+ # Just list all of the providers.
1800
+ def self.providers
1801
+ @providers.keys
1802
+ end
1803
+
1804
+ def self.validprovider?(name)
1805
+ name = Puppet::Util.symbolize(name)
1806
+
1807
+ return (@providers.has_key?(name) && @providers[name].suitable?)
1808
+ end
1809
+
1810
+ # Create a new provider of a type. This method must be called
1811
+ # directly on the type that it's implementing.
1812
+ def self.provide(name, options = {}, &block)
1813
+ name = Puppet::Util.symbolize(name)
1814
+
1815
+ if obj = @providers[name]
1816
+ Puppet.debug "Reloading %s %s provider" % [name, self.name]
1817
+ unprovide(name)
1818
+ end
1819
+
1820
+ parent = if pname = options[:parent]
1821
+ options.delete(:parent)
1822
+ if pname.is_a? Class
1823
+ pname
1824
+ else
1825
+ if provider = self.provider(pname)
1826
+ provider
1827
+ else
1828
+ raise Puppet::DevError,
1829
+ "Could not find parent provider %s of %s" %
1830
+ [pname, name]
1831
+ end
1832
+ end
1833
+ else
1834
+ Puppet::Provider
1835
+ end
1836
+
1837
+ options[:resource_type] ||= self
1838
+
1839
+ self.providify
1840
+
1841
+ provider = genclass(name,
1842
+ :parent => parent,
1843
+ :hash => @providers,
1844
+ :prefix => "Provider",
1845
+ :block => block,
1846
+ :include => feature_module,
1847
+ :extend => feature_module,
1848
+ :attributes => options
1849
+ )
1850
+
1851
+ return provider
1852
+ end
1853
+
1854
+ # Make sure we have a :provider parameter defined. Only gets called if there
1855
+ # are providers.
1856
+ def self.providify
1857
+ return if @paramhash.has_key? :provider
1858
+
1859
+ newparam(:provider) do
1860
+ desc "The specific backend for #{self.name.to_s} to use. You will
1861
+ seldom need to specify this -- Puppet will usually discover the
1862
+ appropriate provider for your platform."
1863
+
1864
+ # This is so we can refer back to the type to get a list of
1865
+ # providers for documentation.
1866
+ class << self
1867
+ attr_accessor :parenttype
1868
+ end
1869
+
1870
+ # We need to add documentation for each provider.
1871
+ def self.doc
1872
+ @doc + " Available providers are:\n\n" + parenttype().providers.sort { |a,b|
1873
+ a.to_s <=> b.to_s
1874
+ }.collect { |i|
1875
+ "* **%s**: %s" % [i, parenttype().provider(i).doc]
1876
+ }.join("\n")
1877
+ end
1878
+
1879
+ defaultto {
1880
+ @resource.class.defaultprovider.name
1881
+ }
1882
+
1883
+ validate do |provider_class|
1884
+ provider_class = provider_class[0] if provider_class.is_a? Array
1885
+ if provider_class.is_a?(Puppet::Provider)
1886
+ provider_class = provider_class.class.name
1887
+ end
1888
+
1889
+ unless provider = @resource.class.provider(provider_class)
1890
+ raise ArgumentError, "Invalid %s provider '%s'" % [@resource.class.name, provider_class]
1891
+ end
1892
+ end
1893
+
1894
+ munge do |provider|
1895
+ provider = provider[0] if provider.is_a? Array
1896
+ if provider.is_a? String
1897
+ provider = provider.intern
1898
+ end
1899
+ @resource.provider = provider
1900
+
1901
+ if provider.is_a?(Puppet::Provider)
1902
+ provider.class.name
1903
+ else
1904
+ provider
1905
+ end
1906
+ end
1907
+ end.parenttype = self
1908
+ end
1909
+
1910
+ def self.unprovide(name)
1911
+ if @providers.has_key? name
1912
+ rmclass(name,
1913
+ :hash => @providers,
1914
+ :prefix => "Provider"
1915
+ )
1916
+ if @defaultprovider and @defaultprovider.name == name
1917
+ @defaultprovider = nil
1918
+ end
1919
+ end
1920
+ end
1921
+
1922
+ # Return an array of all of the suitable providers.
1923
+ def self.suitableprovider
1924
+ if @providers.empty?
1925
+ providerloader.loadall
1926
+ end
1927
+ @providers.find_all { |name, provider|
1928
+ provider.suitable?
1929
+ }.collect { |name, provider|
1930
+ provider
1931
+ }.reject { |p| p.name == :fake } # For testing
1932
+ end
1933
+
1934
+ def provider=(name)
1935
+ if name.is_a?(Puppet::Provider)
1936
+ @provider = name
1937
+ @provider.resource = self
1938
+ elsif klass = self.class.provider(name)
1939
+ @provider = klass.new(self)
1940
+ else
1941
+ raise ArgumentError, "Could not find %s provider of %s" %
1942
+ [name, self.class.name]
1943
+ end
1944
+ end
1945
+
1946
+ ###############################
1947
+ # All of the relationship code.
1948
+
1949
+ # Specify a block for generating a list of objects to autorequire. This
1950
+ # makes it so that you don't have to manually specify things that you clearly
1951
+ # require.
1952
+ def self.autorequire(name, &block)
1953
+ @autorequires ||= {}
1954
+ @autorequires[name] = block
1955
+ end
1956
+
1957
+ # Yield each of those autorequires in turn, yo.
1958
+ def self.eachautorequire
1959
+ @autorequires ||= {}
1960
+ @autorequires.each { |type, block|
1961
+ yield(type, block)
1962
+ }
1963
+ end
1964
+
1965
+ # Figure out of there are any objects we can automatically add as
1966
+ # dependencies.
1967
+ def autorequire
1968
+ reqs = []
1969
+ self.class.eachautorequire { |type, block|
1970
+ # Ignore any types we can't find, although that would be a bit odd.
1971
+ next unless typeobj = Puppet.type(type)
1972
+
1973
+ # Retrieve the list of names from the block.
1974
+ next unless list = self.instance_eval(&block)
1975
+ unless list.is_a?(Array)
1976
+ list = [list]
1977
+ end
1978
+
1979
+ # Collect the current prereqs
1980
+ list.each { |dep|
1981
+ obj = nil
1982
+ # Support them passing objects directly, to save some effort.
1983
+ unless dep.is_a? Puppet::Type
1984
+ # Skip autorequires that we aren't managing
1985
+ unless dep = typeobj[dep]
1986
+ next
1987
+ end
1988
+ end
1989
+
1990
+ reqs << Puppet::Relationship.new(dep, self)
1991
+ }
1992
+ }
1993
+
1994
+ return reqs
1995
+ end
1996
+
1997
+ # Build the dependencies associated with an individual object.
1998
+ def builddepends
1999
+ # Handle the requires
2000
+ self.class.relationship_params.collect do |klass|
2001
+ if param = @parameters[klass.name]
2002
+ param.to_edges
2003
+ end
2004
+ end.flatten.reject { |r| r.nil? }
2005
+ end
2006
+
2007
+ # Does this resource have a relationship with the other? We have to
2008
+ # check each object for both directions of relationship.
2009
+ def requires?(other)
2010
+ them = [other.class.name, other.title]
2011
+ me = [self.class.name, self.title]
2012
+ self.class.relationship_params.each do |param|
2013
+ case param.direction
2014
+ when :in: return true if v = self[param.name] and v.include?(them)
2015
+ when :out: return true if v = other[param.name] and v.include?(me)
2016
+ end
2017
+ end
2018
+ return false
2019
+ end
2020
+
2021
+ # we've received an event
2022
+ # we only support local events right now, so we can pass actual
2023
+ # objects around, including the transaction object
2024
+ # the assumption here is that container objects will pass received
2025
+ # methods on to contained objects
2026
+ # i.e., we don't trigger our children, our refresh() method calls
2027
+ # refresh() on our children
2028
+ def trigger(event, source)
2029
+ trans = event.transaction
2030
+ if @callbacks.include?(source)
2031
+ [:ALL_EVENTS, event.event].each { |eventname|
2032
+ if method = @callbacks[source][eventname]
2033
+ if trans.triggered?(self, method) > 0
2034
+ next
2035
+ end
2036
+ if self.respond_to?(method)
2037
+ self.send(method)
2038
+ end
2039
+
2040
+ trans.triggered(self, method)
2041
+ end
2042
+ }
2043
+ end
2044
+ end
2045
+
2046
+ # Unsubscribe from a given object, possibly with a specific event.
2047
+ def unsubscribe(object, event = nil)
2048
+ # First look through our own relationship params
2049
+ [:require, :subscribe].each do |param|
2050
+ if values = self[param]
2051
+ newvals = values.reject { |d|
2052
+ d == [object.class.name, object.title]
2053
+ }
2054
+ if newvals.length != values.length
2055
+ self.delete(param)
2056
+ self[param] = newvals
2057
+ end
2058
+ end
2059
+ end
2060
+ end
2061
+
2062
+ ###############################
2063
+ # All of the scheduling code.
2064
+
2065
+ # Look up the schedule and set it appropriately. This is done after
2066
+ # the instantiation phase, so that the schedule can be anywhere in the
2067
+ # file.
2068
+ def schedule
2069
+ unless defined? @schedule
2070
+ if name = self[:schedule]
2071
+ if sched = Puppet.type(:schedule)[name]
2072
+ @schedule = sched
2073
+ else
2074
+ self.fail "Could not find schedule %s" % name
2075
+ end
2076
+ else
2077
+ @schedule = nil
2078
+ end
2079
+ end
2080
+ @schedule
2081
+ end
2082
+
2083
+ # Check whether we are scheduled to run right now or not.
2084
+ def scheduled?
2085
+ return true if Puppet[:ignoreschedules]
2086
+ return true unless schedule = self.schedule
2087
+
2088
+ # We use 'checked' here instead of 'synced' because otherwise we'll
2089
+ # end up checking most resources most times, because they will generally
2090
+ # have been synced a long time ago (e.g., a file only gets updated
2091
+ # once a month on the server and its schedule is daily; the last sync time
2092
+ # will have been a month ago, so we'd end up checking every run).
2093
+ return schedule.match?(self.cached(:checked).to_i)
2094
+ end
2095
+
2096
+ ###############################
2097
+ # All of the tagging code.
2098
+ attr_reader :tags
2099
+
2100
+ # Add a new tag.
2101
+ def tag(tag)
2102
+ tag = tag.intern if tag.is_a? String
2103
+ unless @tags.include? tag
2104
+ @tags << tag
2105
+ end
2106
+ end
2107
+
2108
+ # Define the initial list of tags.
2109
+ def tags=(list)
2110
+ list = [list] unless list.is_a? Array
2111
+
2112
+ @tags = list.collect do |t|
2113
+ case t
2114
+ when String: t.intern
2115
+ when Symbol: t
2116
+ else
2117
+ self.warning "Ignoring tag %s of type %s" % [tag.inspect, tag.class]
2118
+ end
2119
+ end
2120
+
2121
+ @tags << self.class.name unless @tags.include?(self.class.name)
2122
+ end
2123
+
2124
+ # Figure out of any of the specified tags apply to this object. This is an
2125
+ # OR operation.
2126
+ def tagged?(tags)
2127
+ tags = [tags] unless tags.is_a? Array
2128
+
2129
+ tags = tags.collect { |t| t.intern }
2130
+
2131
+ return tags.find { |tag| @tags.include? tag }
2132
+ end
37
2133
 
38
2134
  # Types (which map to resources in the languages) are entirely composed of
39
2135
  # attribute value pairs. Generally, Puppet calls any of these things an