puppet 0.18.4 → 0.22.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (673) hide show
  1. data/CHANGELOG +288 -0
  2. data/README +2 -2
  3. data/Rakefile +78 -5
  4. data/bin/puppet +28 -36
  5. data/bin/puppetca +81 -38
  6. data/bin/puppetd +65 -62
  7. data/bin/puppetdoc +409 -140
  8. data/bin/puppetmasterd +59 -47
  9. data/bin/puppetrun +38 -23
  10. data/conf/freebsd/puppetd +26 -0
  11. data/conf/freebsd/puppetmasterd +26 -0
  12. data/conf/gentoo/conf.d/puppet +5 -0
  13. data/conf/gentoo/conf.d/puppetmaster +12 -0
  14. data/conf/gentoo/init.d/puppet +38 -0
  15. data/conf/gentoo/init.d/puppetmaster +50 -0
  16. data/conf/gentoo/puppet/fileserver.conf +12 -0
  17. data/conf/gentoo/puppet/puppetca.conf +29 -0
  18. data/conf/gentoo/puppet/puppetd.conf +29 -0
  19. data/conf/gentoo/puppet/puppetmasterd.conf +29 -0
  20. data/conf/redhat/client.init +10 -5
  21. data/conf/redhat/client.sysconfig +1 -1
  22. data/conf/redhat/fileserver.conf +2 -2
  23. data/conf/redhat/logrotate +1 -1
  24. data/conf/redhat/no-lockdir.patch +13 -0
  25. data/conf/redhat/puppet.spec +65 -8
  26. data/conf/redhat/puppetd.conf +0 -4
  27. data/conf/redhat/server.init +3 -6
  28. data/conf/solaris/pkginfo +1 -1
  29. data/conf/solaris/smf/svc-puppetd +2 -2
  30. data/conf/suse/client.init +142 -0
  31. data/conf/suse/puppet.spec +221 -0
  32. data/conf/suse/server.init +162 -0
  33. data/examples/code/mac_automount.pp +16 -0
  34. data/examples/root/bin/sleeper +3 -5
  35. data/examples/root/etc/init.d/sleeper +8 -2
  36. data/examples/root/etc/puppet/fileserver.conf +12 -2
  37. data/examples/root/etc/puppet/namespaceauth.conf +20 -0
  38. data/examples/root/etc/puppet/puppetd.conf +4 -0
  39. data/examples/root/etc/puppet/puppetmasterd.conf +6 -9
  40. data/examples/root/etc/puppet/tagmail.conf +1 -0
  41. data/ext/emacs/puppet-mode.el +46 -1
  42. data/ext/logcheck/puppet +15 -0
  43. data/ext/module_puppet +15 -23
  44. data/ext/vim/puppet.vim +4 -2
  45. data/install.rb +2 -1
  46. data/lib/puppet.rb +76 -207
  47. data/lib/puppet/configuration.rb +331 -0
  48. data/lib/puppet/daemon.rb +63 -246
  49. data/lib/puppet/dsl.rb +371 -0
  50. data/lib/puppet/element.rb +8 -26
  51. data/lib/puppet/error.rb +54 -0
  52. data/lib/puppet/event.rb +8 -243
  53. data/lib/puppet/{base64.rb → external/base64.rb} +0 -0
  54. data/lib/puppet/external/event-loop.rb +1 -0
  55. data/lib/puppet/{event-loop → external/event-loop}/better-definers.rb +0 -0
  56. data/lib/puppet/{event-loop → external/event-loop}/event-loop.rb +2 -2
  57. data/lib/puppet/{event-loop → external/event-loop}/signal-system.rb +1 -1
  58. data/lib/puppet/external/gratr.rb +33 -0
  59. data/lib/puppet/external/gratr/adjacency_graph.rb +257 -0
  60. data/lib/puppet/external/gratr/base.rb +34 -0
  61. data/lib/puppet/external/gratr/biconnected.rb +116 -0
  62. data/lib/puppet/external/gratr/chinese_postman.rb +123 -0
  63. data/lib/puppet/external/gratr/common.rb +73 -0
  64. data/lib/puppet/external/gratr/comparability.rb +92 -0
  65. data/lib/puppet/external/gratr/digraph.rb +116 -0
  66. data/lib/puppet/external/gratr/digraph_distance.rb +185 -0
  67. data/lib/puppet/external/gratr/dot.rb +90 -0
  68. data/lib/puppet/external/gratr/edge.rb +145 -0
  69. data/lib/puppet/external/gratr/graph.rb +303 -0
  70. data/lib/puppet/external/gratr/graph_api.rb +83 -0
  71. data/lib/puppet/external/gratr/import.rb +44 -0
  72. data/lib/puppet/external/gratr/labels.rb +90 -0
  73. data/lib/puppet/external/gratr/maximum_flow.rb +64 -0
  74. data/lib/puppet/external/gratr/rdot.rb +327 -0
  75. data/lib/puppet/external/gratr/search.rb +409 -0
  76. data/lib/puppet/external/gratr/strong_components.rb +127 -0
  77. data/lib/puppet/external/gratr/undirected_graph.rb +153 -0
  78. data/lib/puppet/{lock.rb → external/lock.rb} +1 -1
  79. data/lib/puppet/feature/base.rb +20 -0
  80. data/lib/puppet/feature/rails.rb +52 -0
  81. data/lib/puppet/metatype/attributes.rb +719 -0
  82. data/lib/puppet/metatype/closure.rb +111 -0
  83. data/lib/puppet/metatype/container.rb +94 -0
  84. data/lib/puppet/metatype/evaluation.rb +118 -0
  85. data/lib/puppet/metatype/instances.rb +261 -0
  86. data/lib/puppet/metatype/manager.rb +169 -0
  87. data/lib/puppet/metatype/metaparams.rb +409 -0
  88. data/lib/puppet/metatype/providers.rb +260 -0
  89. data/lib/puppet/metatype/relationships.rb +116 -0
  90. data/lib/puppet/metatype/schedules.rb +39 -0
  91. data/lib/puppet/metatype/tags.rb +39 -0
  92. data/lib/puppet/modules.rb +113 -0
  93. data/lib/puppet/network/authconfig.rb +168 -0
  94. data/lib/puppet/network/authorization.rb +84 -0
  95. data/lib/puppet/network/authstore.rb +293 -0
  96. data/lib/puppet/network/client.rb +187 -0
  97. data/lib/puppet/network/client/ca.rb +56 -0
  98. data/lib/puppet/network/client/dipper.rb +81 -0
  99. data/lib/puppet/network/client/file.rb +7 -0
  100. data/lib/puppet/network/client/logger.rb +6 -0
  101. data/lib/puppet/network/client/master.rb +644 -0
  102. data/lib/puppet/{client → network/client}/proxy.rb +3 -3
  103. data/lib/puppet/{client/reporter.rb → network/client/report.rb} +4 -7
  104. data/lib/puppet/{client/pelement.rb → network/client/resource.rb} +6 -19
  105. data/lib/puppet/network/client/runner.rb +13 -0
  106. data/lib/puppet/network/client/status.rb +5 -0
  107. data/lib/puppet/network/client_request.rb +32 -0
  108. data/lib/puppet/network/handler.rb +33 -0
  109. data/lib/puppet/{server → network/handler}/ca.rb +5 -6
  110. data/lib/puppet/network/handler/filebucket.rb +180 -0
  111. data/lib/puppet/{server → network/handler}/fileserver.rb +277 -219
  112. data/lib/puppet/{server → network/handler}/logger.rb +3 -5
  113. data/lib/puppet/{server → network/handler}/master.rb +42 -8
  114. data/lib/puppet/network/handler/report.rb +158 -0
  115. data/lib/puppet/network/handler/resource.rb +190 -0
  116. data/lib/puppet/{server → network/handler}/runner.rb +17 -18
  117. data/lib/puppet/network/handler/status.rb +13 -0
  118. data/lib/puppet/network/rights.rb +74 -0
  119. data/lib/puppet/network/server.rb +5 -0
  120. data/lib/puppet/network/server/mongrel.rb +138 -0
  121. data/lib/puppet/network/server/webrick.rb +153 -0
  122. data/lib/puppet/network/xmlrpc/client.rb +129 -0
  123. data/lib/puppet/network/xmlrpc/processor.rb +91 -0
  124. data/lib/puppet/network/xmlrpc/server.rb +20 -0
  125. data/lib/puppet/network/xmlrpc/webrick_servlet.rb +121 -0
  126. data/lib/puppet/parameter.rb +390 -346
  127. data/lib/puppet/parser/ast.rb +116 -147
  128. data/lib/puppet/parser/ast/astarray.rb +17 -33
  129. data/lib/puppet/parser/ast/branch.rb +2 -0
  130. data/lib/puppet/parser/ast/caseopt.rb +7 -12
  131. data/lib/puppet/parser/ast/casestatement.rb +23 -32
  132. data/lib/puppet/parser/ast/collection.rb +19 -80
  133. data/lib/puppet/parser/ast/collexpr.rb +81 -0
  134. data/lib/puppet/parser/ast/component.rb +160 -89
  135. data/lib/puppet/parser/ast/else.rb +30 -0
  136. data/lib/puppet/parser/ast/function.rb +9 -2
  137. data/lib/puppet/parser/ast/hostclass.rb +47 -131
  138. data/lib/puppet/parser/ast/ifstatement.rb +43 -0
  139. data/lib/puppet/parser/ast/leaf.rb +10 -21
  140. data/lib/puppet/parser/ast/node.rb +32 -79
  141. data/lib/puppet/parser/ast/resourcedef.rb +222 -0
  142. data/lib/puppet/parser/ast/{typedefaults.rb → resourcedefaults.rb} +10 -16
  143. data/lib/puppet/parser/ast/resourceoverride.rb +62 -0
  144. data/lib/puppet/parser/ast/{objectparam.rb → resourceparam.rb} +12 -6
  145. data/lib/puppet/parser/ast/resourceref.rb +44 -0
  146. data/lib/puppet/parser/ast/selector.rb +16 -8
  147. data/lib/puppet/parser/ast/tag.rb +3 -1
  148. data/lib/puppet/parser/ast/vardef.rb +8 -12
  149. data/lib/puppet/parser/collector.rb +181 -0
  150. data/lib/puppet/parser/functions.rb +191 -36
  151. data/lib/puppet/parser/interpreter.rb +802 -380
  152. data/lib/puppet/parser/lexer.rb +86 -19
  153. data/lib/puppet/parser/parser.rb +1123 -960
  154. data/lib/puppet/parser/resource.rb +353 -0
  155. data/lib/puppet/parser/resource/param.rb +57 -0
  156. data/lib/puppet/parser/resource/reference.rb +71 -0
  157. data/lib/puppet/parser/scope.rb +573 -1000
  158. data/lib/puppet/parser/templatewrapper.rb +54 -0
  159. data/lib/puppet/pgraph.rb +208 -0
  160. data/lib/puppet/propertychange.rb +143 -0
  161. data/lib/puppet/provider.rb +302 -0
  162. data/lib/puppet/provider/cron/crontab.rb +187 -0
  163. data/lib/puppet/provider/group/groupadd.rb +29 -0
  164. data/lib/puppet/provider/group/netinfo.rb +12 -0
  165. data/lib/puppet/provider/group/pw.rb +31 -0
  166. data/lib/puppet/provider/host/netinfo.rb +18 -0
  167. data/lib/puppet/provider/host/parsed.rb +73 -0
  168. data/lib/puppet/provider/mount.rb +57 -0
  169. data/lib/puppet/provider/mount/netinfo.rb +38 -0
  170. data/lib/puppet/provider/mount/parsed.rb +37 -0
  171. data/lib/puppet/provider/nameservice.rb +344 -0
  172. data/lib/puppet/provider/nameservice/netinfo.rb +210 -0
  173. data/lib/puppet/provider/nameservice/objectadd.rb +45 -0
  174. data/lib/puppet/provider/nameservice/pw.rb +22 -0
  175. data/lib/puppet/provider/package/apple.rb +53 -0
  176. data/lib/puppet/provider/package/apt.rb +119 -0
  177. data/lib/puppet/provider/package/aptitude.rb +30 -0
  178. data/lib/puppet/provider/package/aptrpm.rb +79 -0
  179. data/lib/puppet/provider/package/blastwave.rb +114 -0
  180. data/lib/puppet/provider/package/darwinport.rb +88 -0
  181. data/lib/puppet/provider/package/dpkg.rb +109 -0
  182. data/lib/puppet/provider/package/freebsd.rb +43 -0
  183. data/lib/puppet/provider/package/gem.rb +104 -0
  184. data/lib/puppet/provider/package/openbsd.rb +93 -0
  185. data/lib/puppet/provider/package/pkgdmg.rb +119 -0
  186. data/lib/puppet/provider/package/portage.rb +112 -0
  187. data/lib/puppet/provider/package/ports.rb +94 -0
  188. data/lib/puppet/provider/package/rpm.rb +125 -0
  189. data/lib/puppet/provider/package/rug.rb +53 -0
  190. data/lib/puppet/provider/package/sun.rb +168 -0
  191. data/lib/puppet/provider/package/sunfreeware.rb +9 -0
  192. data/lib/puppet/provider/package/up2date.rb +45 -0
  193. data/lib/puppet/provider/package/yum.rb +54 -0
  194. data/lib/puppet/provider/parsedfile.rb +342 -0
  195. data/lib/puppet/provider/port/parsed.rb +174 -0
  196. data/lib/puppet/provider/service/base.rb +136 -0
  197. data/lib/puppet/provider/service/debian.rb +32 -0
  198. data/lib/puppet/provider/service/gentoo.rb +49 -0
  199. data/lib/puppet/{type → provider}/service/init.rb +42 -40
  200. data/lib/puppet/provider/service/redhat.rb +59 -0
  201. data/lib/puppet/{type → provider}/service/smf.rb +24 -13
  202. data/lib/puppet/provider/sshkey/parsed.rb +36 -0
  203. data/lib/puppet/provider/user/netinfo.rb +106 -0
  204. data/lib/puppet/provider/user/pw.rb +41 -0
  205. data/lib/puppet/provider/user/useradd.rb +67 -0
  206. data/lib/puppet/provider/zone/solaris.rb +208 -0
  207. data/lib/puppet/rails.rb +102 -66
  208. data/lib/puppet/rails/database/001_add_indexes.rb +38 -0
  209. data/lib/puppet/rails/database/schema.rb +89 -0
  210. data/lib/puppet/rails/external/tagging/acts_as_taggable.rb +62 -0
  211. data/lib/puppet/rails/external/tagging/init.rb +5 -0
  212. data/lib/puppet/rails/external/tagging/tag.rb +50 -0
  213. data/lib/puppet/rails/external/tagging/tagging.rb +12 -0
  214. data/lib/puppet/rails/fact_name.rb +7 -0
  215. data/lib/puppet/rails/fact_value.rb +5 -0
  216. data/lib/puppet/rails/host.rb +95 -46
  217. data/lib/puppet/rails/param_name.rb +28 -0
  218. data/lib/puppet/rails/param_value.rb +5 -0
  219. data/lib/puppet/rails/puppet_class.rb +9 -0
  220. data/lib/puppet/rails/resource.rb +95 -0
  221. data/lib/puppet/rails/source_file.rb +5 -0
  222. data/lib/puppet/relationship.rb +63 -0
  223. data/lib/puppet/reports/log.rb +14 -0
  224. data/lib/puppet/reports/rrdgraph.rb +114 -10
  225. data/lib/puppet/reports/store.rb +64 -0
  226. data/lib/puppet/reports/tagmail.rb +144 -71
  227. data/lib/puppet/sslcertificates.rb +38 -5
  228. data/lib/puppet/sslcertificates/ca.rb +142 -37
  229. data/lib/puppet/sslcertificates/certificate.rb +3 -3
  230. data/lib/puppet/sslcertificates/inventory.rb +53 -0
  231. data/lib/puppet/sslcertificates/support.rb +128 -0
  232. data/lib/puppet/transaction.rb +568 -189
  233. data/lib/puppet/transaction/report.rb +14 -3
  234. data/lib/puppet/transportable.rb +18 -10
  235. data/lib/puppet/type.rb +279 -2299
  236. data/lib/puppet/type/component.rb +63 -63
  237. data/lib/puppet/type/cron.rb +294 -710
  238. data/lib/puppet/type/exec.rb +185 -129
  239. data/lib/puppet/type/group.rb +38 -89
  240. data/lib/puppet/type/host.rb +110 -0
  241. data/lib/puppet/type/mount.rb +189 -0
  242. data/lib/puppet/type/notify.rb +47 -0
  243. data/lib/puppet/type/package.rb +129 -257
  244. data/lib/puppet/type/parsedtype.rb +172 -297
  245. data/lib/puppet/type/pfile.rb +540 -319
  246. data/lib/puppet/type/pfile/checksum.rb +103 -76
  247. data/lib/puppet/type/pfile/content.rb +16 -10
  248. data/lib/puppet/type/pfile/ensure.rb +52 -34
  249. data/lib/puppet/type/pfile/group.rb +25 -18
  250. data/lib/puppet/type/pfile/mode.rb +7 -4
  251. data/lib/puppet/type/pfile/{uid.rb → owner.rb} +21 -17
  252. data/lib/puppet/type/pfile/source.rb +119 -124
  253. data/lib/puppet/type/pfile/target.rb +29 -45
  254. data/lib/puppet/type/pfile/type.rb +2 -2
  255. data/lib/puppet/type/pfilebucket.rb +18 -14
  256. data/lib/puppet/type/port.rb +121 -0
  257. data/lib/puppet/type/property.rb +530 -0
  258. data/lib/puppet/type/resources.rb +150 -0
  259. data/lib/puppet/type/schedule.rb +38 -22
  260. data/lib/puppet/type/service.rb +70 -326
  261. data/lib/puppet/type/sshkey.rb +76 -0
  262. data/lib/puppet/type/tidy.rb +197 -97
  263. data/lib/puppet/type/user.rb +107 -183
  264. data/lib/puppet/type/yumrepo.rb +53 -34
  265. data/lib/puppet/type/zone.rb +55 -208
  266. data/lib/puppet/util.rb +239 -201
  267. data/lib/puppet/util/autoload.rb +107 -0
  268. data/lib/puppet/util/classgen.rb +208 -0
  269. data/lib/puppet/{config.rb → util/config.rb} +102 -54
  270. data/lib/puppet/util/docs.rb +104 -0
  271. data/lib/puppet/util/errors.rb +55 -0
  272. data/lib/puppet/util/execution.rb +22 -0
  273. data/lib/puppet/util/feature.rb +76 -0
  274. data/lib/puppet/util/fileparsing.rb +380 -0
  275. data/lib/puppet/util/filetype.rb +300 -0
  276. data/lib/puppet/util/graph.rb +39 -0
  277. data/lib/puppet/util/inifile.rb +209 -0
  278. data/lib/puppet/util/loadedfile.rb +71 -0
  279. data/lib/puppet/util/log.rb +549 -0
  280. data/lib/puppet/util/logging.rb +20 -0
  281. data/lib/puppet/util/metaid.rb +22 -0
  282. data/lib/puppet/util/methodhelper.rb +37 -0
  283. data/lib/puppet/util/metric.rb +160 -0
  284. data/lib/puppet/util/package.rb +31 -0
  285. data/lib/puppet/util/pidlock.rb +68 -0
  286. data/lib/puppet/util/plist.rb +24 -0
  287. data/lib/puppet/util/plist/generator.rb +226 -0
  288. data/lib/puppet/util/plist/parser.rb +227 -0
  289. data/lib/puppet/util/posix.rb +87 -0
  290. data/lib/puppet/util/provider_features.rb +170 -0
  291. data/lib/puppet/util/rails/collection_merger.rb +42 -0
  292. data/lib/puppet/util/storage.rb +103 -0
  293. data/lib/puppet/util/subclass_loader.rb +83 -0
  294. data/lib/puppet/util/suidmanager.rb +86 -0
  295. data/lib/puppet/util/variables.rb +39 -0
  296. data/lib/puppet/util/warnings.rb +15 -0
  297. data/test/Rakefile +97 -0
  298. data/test/certmgr/ca.rb +81 -0
  299. data/test/certmgr/certmgr.rb +77 -50
  300. data/test/certmgr/inventory.rb +79 -0
  301. data/test/certmgr/support.rb +81 -0
  302. data/test/executables/filebucket.rb +49 -0
  303. data/test/executables/puppetbin.rb +28 -12
  304. data/test/executables/puppetca.rb +75 -54
  305. data/test/executables/puppetd.rb +10 -13
  306. data/test/executables/puppetmasterd.rb +12 -17
  307. data/test/executables/puppetmodule.rb +18 -17
  308. data/test/language/ast.rb +242 -798
  309. data/test/language/ast/casestatement.rb +104 -0
  310. data/test/language/ast/component.rb +133 -0
  311. data/test/language/ast/hostclass.rb +162 -0
  312. data/test/language/ast/selector.rb +62 -0
  313. data/test/language/ast/variable.rb +31 -0
  314. data/test/language/collector.rb +369 -0
  315. data/test/language/functions.rb +305 -18
  316. data/test/language/interpreter.rb +894 -125
  317. data/test/language/lexer.rb +98 -12
  318. data/test/language/node.rb +37 -53
  319. data/test/language/parser.rb +455 -148
  320. data/test/language/resource.rb +535 -0
  321. data/test/language/scope.rb +451 -561
  322. data/test/language/snippets.rb +101 -111
  323. data/test/language/transportable.rb +6 -8
  324. data/test/lib/mocha.rb +19 -0
  325. data/test/lib/mocha/any_instance_method.rb +35 -0
  326. data/test/lib/mocha/auto_verify.rb +113 -0
  327. data/test/lib/mocha/central.rb +35 -0
  328. data/test/lib/mocha/class_method.rb +62 -0
  329. data/test/lib/mocha/expectation.rb +295 -0
  330. data/test/lib/mocha/expectation_error.rb +6 -0
  331. data/test/lib/mocha/infinite_range.rb +27 -0
  332. data/test/lib/mocha/inspect.rb +37 -0
  333. data/test/lib/mocha/instance_method.rb +8 -0
  334. data/test/lib/mocha/metaclass.rb +7 -0
  335. data/test/lib/mocha/mock.rb +20 -0
  336. data/test/lib/mocha/mock_methods.rb +122 -0
  337. data/test/lib/mocha/object.rb +100 -0
  338. data/test/lib/mocha/pretty_parameters.rb +28 -0
  339. data/test/lib/mocha/setup_and_teardown.rb +23 -0
  340. data/test/lib/mocha/standalone.rb +30 -0
  341. data/test/lib/mocha/test_case_adapter.rb +49 -0
  342. data/test/lib/mocha_standalone.rb +2 -0
  343. data/test/lib/puppettest.rb +294 -0
  344. data/test/lib/puppettest/certificates.rb +61 -0
  345. data/test/lib/puppettest/exetest.rb +123 -0
  346. data/test/lib/puppettest/fakes.rb +194 -0
  347. data/test/lib/puppettest/fileparsing.rb +33 -0
  348. data/test/lib/puppettest/filetesting.rb +231 -0
  349. data/test/lib/puppettest/graph.rb +41 -0
  350. data/test/lib/puppettest/parsertesting.rb +392 -0
  351. data/test/lib/puppettest/railstesting.rb +56 -0
  352. data/test/lib/puppettest/reporttesting.rb +19 -0
  353. data/test/lib/puppettest/resourcetesting.rb +73 -0
  354. data/test/lib/puppettest/servertest.rb +72 -0
  355. data/test/lib/puppettest/support.rb +8 -0
  356. data/test/lib/puppettest/support/assertions.rb +101 -0
  357. data/test/lib/puppettest/support/helpers.rb +23 -0
  358. data/test/lib/puppettest/support/resources.rb +37 -0
  359. data/test/lib/puppettest/support/utils.rb +160 -0
  360. data/test/lib/puppettest/testcase.rb +48 -0
  361. data/test/lib/rake/puppet_test_loader.rb +17 -0
  362. data/test/lib/rake/puppet_testtask.rb +17 -0
  363. data/test/lib/spec.rb +8 -0
  364. data/test/lib/spec/callback.rb +11 -0
  365. data/test/lib/spec/callback/callback_container.rb +60 -0
  366. data/test/lib/spec/callback/extensions/module.rb +24 -0
  367. data/test/lib/spec/callback/extensions/object.rb +37 -0
  368. data/test/lib/spec/deprecated.rb +3 -0
  369. data/test/lib/spec/expectations.rb +59 -0
  370. data/test/lib/spec/expectations/differs/default.rb +62 -0
  371. data/test/lib/spec/expectations/errors.rb +6 -0
  372. data/test/lib/spec/expectations/extensions.rb +3 -0
  373. data/test/lib/spec/expectations/extensions/object.rb +109 -0
  374. data/test/lib/spec/expectations/extensions/proc.rb +57 -0
  375. data/test/lib/spec/expectations/extensions/string_and_symbol.rb +17 -0
  376. data/test/lib/spec/expectations/handler.rb +47 -0
  377. data/test/lib/spec/expectations/should.rb +5 -0
  378. data/test/lib/spec/expectations/should/base.rb +64 -0
  379. data/test/lib/spec/expectations/should/change.rb +69 -0
  380. data/test/lib/spec/expectations/should/have.rb +128 -0
  381. data/test/lib/spec/expectations/should/not.rb +74 -0
  382. data/test/lib/spec/expectations/should/should.rb +81 -0
  383. data/test/lib/spec/expectations/sugar.rb +47 -0
  384. data/test/lib/spec/matchers.rb +160 -0
  385. data/test/lib/spec/matchers/be.rb +161 -0
  386. data/test/lib/spec/matchers/be_close.rb +37 -0
  387. data/test/lib/spec/matchers/change.rb +120 -0
  388. data/test/lib/spec/matchers/eql.rb +43 -0
  389. data/test/lib/spec/matchers/equal.rb +43 -0
  390. data/test/lib/spec/matchers/has.rb +44 -0
  391. data/test/lib/spec/matchers/have.rb +140 -0
  392. data/test/lib/spec/matchers/include.rb +50 -0
  393. data/test/lib/spec/matchers/match.rb +41 -0
  394. data/test/lib/spec/matchers/raise_error.rb +100 -0
  395. data/test/lib/spec/matchers/respond_to.rb +35 -0
  396. data/test/lib/spec/matchers/satisfy.rb +47 -0
  397. data/test/lib/spec/matchers/throw_symbol.rb +75 -0
  398. data/test/lib/spec/mocks.rb +232 -0
  399. data/test/lib/spec/mocks/argument_expectation.rb +132 -0
  400. data/test/lib/spec/mocks/error_generator.rb +85 -0
  401. data/test/lib/spec/mocks/errors.rb +10 -0
  402. data/test/lib/spec/mocks/extensions/object.rb +3 -0
  403. data/test/lib/spec/mocks/message_expectation.rb +231 -0
  404. data/test/lib/spec/mocks/methods.rb +40 -0
  405. data/test/lib/spec/mocks/mock.rb +26 -0
  406. data/test/lib/spec/mocks/mock_handler.rb +166 -0
  407. data/test/lib/spec/mocks/order_group.rb +29 -0
  408. data/test/lib/spec/rake/spectask.rb +173 -0
  409. data/test/lib/spec/rake/verify_rcov.rb +47 -0
  410. data/test/lib/spec/runner.rb +132 -0
  411. data/test/lib/spec/runner/backtrace_tweaker.rb +55 -0
  412. data/test/lib/spec/runner/command_line.rb +34 -0
  413. data/test/lib/spec/runner/context.rb +154 -0
  414. data/test/lib/spec/runner/context_eval.rb +142 -0
  415. data/test/lib/spec/runner/context_runner.rb +55 -0
  416. data/test/lib/spec/runner/drb_command_line.rb +21 -0
  417. data/test/lib/spec/runner/execution_context.rb +17 -0
  418. data/test/lib/spec/runner/extensions/kernel.rb +17 -0
  419. data/test/lib/spec/runner/extensions/object.rb +32 -0
  420. data/test/lib/spec/runner/formatter.rb +5 -0
  421. data/test/lib/spec/runner/formatter/base_text_formatter.rb +118 -0
  422. data/test/lib/spec/runner/formatter/html_formatter.rb +219 -0
  423. data/test/lib/spec/runner/formatter/progress_bar_formatter.rb +27 -0
  424. data/test/lib/spec/runner/formatter/rdoc_formatter.rb +22 -0
  425. data/test/lib/spec/runner/formatter/specdoc_formatter.rb +23 -0
  426. data/test/lib/spec/runner/heckle_runner.rb +71 -0
  427. data/test/lib/spec/runner/heckle_runner_win.rb +10 -0
  428. data/test/lib/spec/runner/option_parser.rb +224 -0
  429. data/test/lib/spec/runner/reporter.rb +105 -0
  430. data/test/lib/spec/runner/spec_matcher.rb +25 -0
  431. data/test/lib/spec/runner/spec_parser.rb +41 -0
  432. data/test/lib/spec/runner/spec_should_raise_handler.rb +74 -0
  433. data/test/lib/spec/runner/specification.rb +114 -0
  434. data/test/lib/spec/translator.rb +87 -0
  435. data/test/lib/spec/version.rb +30 -0
  436. data/test/lib/stubba.rb +2 -0
  437. data/test/network/authconfig.rb +72 -0
  438. data/test/network/authorization.rb +138 -0
  439. data/test/network/authstore.rb +450 -0
  440. data/test/network/client/ca.rb +38 -0
  441. data/test/{client → network/client}/client.rb +107 -24
  442. data/test/network/client/dipper.rb +35 -0
  443. data/test/network/client/master.rb +627 -0
  444. data/test/{client/pelement.rb → network/client/resource.rb} +13 -29
  445. data/test/network/client_request.rb +39 -0
  446. data/test/network/daemon.rb +71 -0
  447. data/test/{server → network/handler}/bucket.rb +103 -27
  448. data/test/{server → network/handler}/ca.rb +14 -19
  449. data/test/{server → network/handler}/fileserver.rb +443 -68
  450. data/test/network/handler/handler.rb +64 -0
  451. data/test/{server → network/handler}/logger.rb +26 -26
  452. data/test/network/handler/master.rb +352 -0
  453. data/test/network/handler/report.rb +185 -0
  454. data/test/{server/pelement.rb → network/handler/resource.rb} +25 -38
  455. data/test/{server → network/handler}/runner.rb +17 -16
  456. data/test/network/rights.rb +38 -0
  457. data/test/network/server/webrick.rb +140 -0
  458. data/test/network/xmlrpc/client.rb +68 -0
  459. data/test/network/xmlrpc/processor.rb +80 -0
  460. data/test/network/xmlrpc/server.rb +28 -0
  461. data/test/network/xmlrpc/webrick_servlet.rb +26 -0
  462. data/test/other/dsl.rb +218 -0
  463. data/test/other/events.rb +22 -15
  464. data/test/other/overrides.rb +9 -14
  465. data/test/other/pgraph.rb +289 -0
  466. data/test/other/propertychange.rb +142 -0
  467. data/test/other/provider.rb +162 -0
  468. data/test/other/puppet.rb +63 -10
  469. data/test/other/relationship.rb +74 -0
  470. data/test/other/relationships.rb +199 -123
  471. data/test/other/report.rb +152 -23
  472. data/test/other/transactions.rb +824 -78
  473. data/test/puppet/conffiles.rb +16 -11
  474. data/test/puppet/defaults.rb +7 -10
  475. data/test/puppet/{error.rb → errortest.rb} +5 -8
  476. data/test/puppet/modules.rb +58 -0
  477. data/test/puppet/tc_suidmanager.rb +107 -0
  478. data/test/rails/host.rb +177 -0
  479. data/test/rails/rails.rb +27 -0
  480. data/test/rails/railsparameter.rb +62 -0
  481. data/test/rails/railsresource.rb +100 -0
  482. data/test/ral/manager/attributes.rb +296 -0
  483. data/test/ral/manager/manager.rb +55 -0
  484. data/test/ral/manager/provider.rb +54 -0
  485. data/test/ral/manager/type.rb +837 -0
  486. data/test/ral/providers/cron/crontab.rb +346 -0
  487. data/test/ral/providers/group.rb +252 -0
  488. data/test/ral/providers/host/netinfo.rb +58 -0
  489. data/test/ral/providers/host/parsed.rb +226 -0
  490. data/test/ral/providers/mount/netinfo.rb +80 -0
  491. data/test/ral/providers/mount/parsed.rb +223 -0
  492. data/test/ral/providers/nameservice.rb +33 -0
  493. data/test/ral/providers/package.rb +253 -0
  494. data/test/ral/providers/package/apt.rb +89 -0
  495. data/test/ral/providers/package/aptitude.rb +69 -0
  496. data/test/ral/providers/package/aptrpm.rb +89 -0
  497. data/test/ral/providers/package/dpkg.rb +64 -0
  498. data/test/ral/providers/parsedfile.rb +668 -0
  499. data/test/ral/providers/parsedport.rb +233 -0
  500. data/test/ral/providers/provider.rb +423 -0
  501. data/test/{types → ral/providers}/service.rb +20 -121
  502. data/test/ral/providers/service/base.rb +75 -0
  503. data/test/ral/providers/sshkey/parsed.rb +111 -0
  504. data/test/ral/providers/user.rb +567 -0
  505. data/test/ral/providers/user/useradd.rb +250 -0
  506. data/test/ral/types/basic.rb +90 -0
  507. data/test/ral/types/component.rb +113 -0
  508. data/test/ral/types/cron.rb +480 -0
  509. data/test/{types → ral/types}/exec.rb +278 -82
  510. data/test/ral/types/file.rb +1799 -0
  511. data/test/ral/types/file/target.rb +363 -0
  512. data/test/{types → ral/types}/filebucket.rb +15 -17
  513. data/test/{types → ral/types}/fileignoresource.rb +9 -15
  514. data/test/ral/types/filesources.rb +1046 -0
  515. data/test/ral/types/group.rb +169 -0
  516. data/test/ral/types/host.rb +155 -0
  517. data/test/ral/types/mount.rb +312 -0
  518. data/test/ral/types/package.rb +85 -0
  519. data/test/ral/types/parameter.rb +172 -0
  520. data/test/ral/types/port.rb +148 -0
  521. data/test/ral/types/property.rb +343 -0
  522. data/test/ral/types/resources.rb +221 -0
  523. data/test/{types → ral/types}/schedule.rb +34 -12
  524. data/test/ral/types/service.rb +37 -0
  525. data/test/{types → ral/types}/sshkey.rb +75 -65
  526. data/test/ral/types/tidy.rb +240 -0
  527. data/test/ral/types/user.rb +493 -0
  528. data/test/{types → ral/types}/yumrepo.rb +7 -11
  529. data/test/{types → ral/types}/zone.rb +45 -45
  530. data/test/tagging/tagging.rb +17 -26
  531. data/test/util/autoload.rb +130 -0
  532. data/test/util/classgen.rb +227 -0
  533. data/test/{other → util}/config.rb +373 -113
  534. data/test/util/execution.rb +34 -0
  535. data/test/util/features.rb +94 -0
  536. data/test/util/fileparsing.rb +677 -0
  537. data/test/{other → util}/filetype.rb +9 -12
  538. data/test/util/graph.rb +108 -0
  539. data/test/{other → util}/inifile.rb +24 -11
  540. data/test/util/loadedfile.rb +106 -0
  541. data/test/{other → util}/log.rb +96 -50
  542. data/test/{other → util}/metrics.rb +7 -17
  543. data/test/util/package.rb +27 -0
  544. data/test/util/pidlock.rb +126 -0
  545. data/test/util/posixtest.rb +173 -0
  546. data/test/util/storage.rb +123 -0
  547. data/test/util/subclass_loader.rb +100 -0
  548. data/test/util/utiltest.rb +368 -0
  549. metadata +449 -169
  550. data/examples/code/classing +0 -35
  551. data/examples/code/failers/badclassnoparam +0 -10
  552. data/examples/code/failers/badclassparam +0 -10
  553. data/examples/code/failers/badcompnoparam +0 -9
  554. data/examples/code/failers/badcompparam +0 -9
  555. data/examples/code/failers/badtypeparam +0 -3
  556. data/examples/code/failers/noobjectrvalue +0 -1
  557. data/examples/code/snippets/aliastest.pp +0 -16
  558. data/examples/code/snippets/argumentdefaults +0 -14
  559. data/examples/code/snippets/casestatement.pp +0 -58
  560. data/examples/code/snippets/classheirarchy.pp +0 -15
  561. data/examples/code/snippets/classincludes.pp +0 -17
  562. data/examples/code/snippets/classpathtest +0 -11
  563. data/examples/code/snippets/componentmetaparams.pp +0 -11
  564. data/examples/code/snippets/deepclassheirarchy.pp +0 -23
  565. data/examples/code/snippets/defineoverrides.pp +0 -17
  566. data/examples/code/snippets/dirchmod +0 -19
  567. data/examples/code/snippets/emptyclass.pp +0 -9
  568. data/examples/code/snippets/emptyexec.pp +0 -3
  569. data/examples/code/snippets/failmissingexecpath.pp +0 -13
  570. data/examples/code/snippets/falsevalues.pp +0 -3
  571. data/examples/code/snippets/filecreate +0 -11
  572. data/examples/code/snippets/implicititeration +0 -15
  573. data/examples/code/snippets/multipleinstances +0 -7
  574. data/examples/code/snippets/namevartest +0 -9
  575. data/examples/code/snippets/scopetest +0 -13
  576. data/examples/code/snippets/selectorvalues.pp +0 -42
  577. data/examples/code/snippets/simpledefaults +0 -5
  578. data/examples/code/snippets/simpleselector +0 -38
  579. data/examples/code/snippets/singleary.pp +0 -19
  580. data/examples/code/snippets/singlequote.pp +0 -11
  581. data/examples/code/snippets/singleselector.pp +0 -22
  582. data/examples/code/snippets/tag.pp +0 -9
  583. data/examples/code/snippets/tagged.pp +0 -35
  584. data/lib/puppet/client.rb +0 -177
  585. data/lib/puppet/client/ca.rb +0 -21
  586. data/lib/puppet/client/dipper.rb +0 -76
  587. data/lib/puppet/client/file.rb +0 -20
  588. data/lib/puppet/client/log.rb +0 -17
  589. data/lib/puppet/client/master.rb +0 -531
  590. data/lib/puppet/client/runner.rb +0 -17
  591. data/lib/puppet/client/status.rb +0 -7
  592. data/lib/puppet/event-loop.rb +0 -1
  593. data/lib/puppet/filetype.rb +0 -308
  594. data/lib/puppet/inifile.rb +0 -201
  595. data/lib/puppet/log.rb +0 -524
  596. data/lib/puppet/metric.rb +0 -132
  597. data/lib/puppet/networkclient.rb +0 -175
  598. data/lib/puppet/parsedfile.rb +0 -58
  599. data/lib/puppet/parser/ast/classdef.rb +0 -79
  600. data/lib/puppet/parser/ast/compdef.rb +0 -75
  601. data/lib/puppet/parser/ast/nodedef.rb +0 -73
  602. data/lib/puppet/parser/ast/objectdef.rb +0 -284
  603. data/lib/puppet/parser/ast/objectref.rb +0 -77
  604. data/lib/puppet/rails/database.rb +0 -40
  605. data/lib/puppet/rails/rails_object.rb +0 -42
  606. data/lib/puppet/rails/rails_parameter.rb +0 -5
  607. data/lib/puppet/server.rb +0 -196
  608. data/lib/puppet/server/authconfig.rb +0 -177
  609. data/lib/puppet/server/authstore.rb +0 -226
  610. data/lib/puppet/server/filebucket.rb +0 -155
  611. data/lib/puppet/server/pelement.rb +0 -188
  612. data/lib/puppet/server/report.rb +0 -184
  613. data/lib/puppet/server/rights.rb +0 -78
  614. data/lib/puppet/server/servlet.rb +0 -274
  615. data/lib/puppet/statechange.rb +0 -129
  616. data/lib/puppet/storage.rb +0 -98
  617. data/lib/puppet/type/nameservice.rb +0 -264
  618. data/lib/puppet/type/nameservice/netinfo.rb +0 -232
  619. data/lib/puppet/type/nameservice/objectadd.rb +0 -146
  620. data/lib/puppet/type/nameservice/posix.rb +0 -12
  621. data/lib/puppet/type/nameservice/pw.rb +0 -107
  622. data/lib/puppet/type/package/apple.rb +0 -41
  623. data/lib/puppet/type/package/apt.rb +0 -107
  624. data/lib/puppet/type/package/blastwave.rb +0 -136
  625. data/lib/puppet/type/package/darwinport.rb +0 -97
  626. data/lib/puppet/type/package/dpkg.rb +0 -113
  627. data/lib/puppet/type/package/freebsd.rb +0 -19
  628. data/lib/puppet/type/package/gem.rb +0 -119
  629. data/lib/puppet/type/package/openbsd.rb +0 -112
  630. data/lib/puppet/type/package/ports.rb +0 -103
  631. data/lib/puppet/type/package/rpm.rb +0 -121
  632. data/lib/puppet/type/package/sun.rb +0 -174
  633. data/lib/puppet/type/package/sunfreeware.rb +0 -7
  634. data/lib/puppet/type/package/yum.rb +0 -52
  635. data/lib/puppet/type/parsedtype/host.rb +0 -144
  636. data/lib/puppet/type/parsedtype/mount.rb +0 -271
  637. data/lib/puppet/type/parsedtype/port.rb +0 -261
  638. data/lib/puppet/type/parsedtype/sshkey.rb +0 -123
  639. data/lib/puppet/type/service/base.rb +0 -12
  640. data/lib/puppet/type/service/debian.rb +0 -46
  641. data/lib/puppet/type/service/redhat.rb +0 -38
  642. data/lib/puppet/type/state.rb +0 -393
  643. data/lib/puppet/type/symlink.rb +0 -186
  644. data/test/client/master.rb +0 -207
  645. data/test/language/rails.rb +0 -105
  646. data/test/other/parsedfile.rb +0 -58
  647. data/test/other/storage.rb +0 -100
  648. data/test/puppet/utiltest.rb +0 -299
  649. data/test/puppettest.rb +0 -1170
  650. data/test/server/authconfig.rb +0 -56
  651. data/test/server/authstore.rb +0 -218
  652. data/test/server/master.rb +0 -201
  653. data/test/server/report.rb +0 -93
  654. data/test/server/rights.rb +0 -41
  655. data/test/server/server.rb +0 -152
  656. data/test/test +0 -61
  657. data/test/types/basic.rb +0 -117
  658. data/test/types/component.rb +0 -298
  659. data/test/types/cron.rb +0 -718
  660. data/test/types/file.rb +0 -1314
  661. data/test/types/filesources.rb +0 -590
  662. data/test/types/group.rb +0 -323
  663. data/test/types/host.rb +0 -186
  664. data/test/types/mount.rb +0 -294
  665. data/test/types/package.rb +0 -538
  666. data/test/types/parameter.rb +0 -107
  667. data/test/types/port.rb +0 -201
  668. data/test/types/query.rb +0 -101
  669. data/test/types/state.rb +0 -92
  670. data/test/types/symlink.rb +0 -120
  671. data/test/types/tidy.rb +0 -102
  672. data/test/types/type.rb +0 -469
  673. data/test/types/user.rb +0 -563
@@ -2,1152 +2,725 @@
2
2
  # such.
3
3
 
4
4
  require 'puppet/parser/parser'
5
+ require 'puppet/parser/templatewrapper'
5
6
  require 'puppet/transportable'
7
+ require 'strscan'
6
8
 
7
- module Puppet::Parser
8
- class Scope
9
- class ScopeObj < Hash
10
- attr_accessor :file, :line, :type, :name
11
- end
12
-
13
- # A simple wrapper for templates, so they don't have full access to
14
- # the scope objects.
15
- class TemplateWrapper
16
- attr_accessor :scope, :file
17
- include Puppet::Util
18
- Puppet::Util.logmethods(self)
19
-
20
- def initialize(scope, file)
21
- @scope = scope
22
- if file =~ /^#{File::SEPARATOR}/
23
- @file = file
24
- else
25
- @file = File.join(Puppet[:templatedir], file)
26
- end
27
-
28
- unless FileTest.exists?(@file)
29
- raise Puppet::ParseError,
30
- "Could not find template %s" % file
31
- end
32
-
33
- # We'll only ever not have an interpreter in testing, but, eh.
34
- if @scope.interp
35
- @scope.interp.newfile(@file)
36
- end
37
- end
9
+ class Puppet::Parser::Scope
10
+ require 'puppet/parser/resource'
38
11
 
39
- def method_missing(name, *args)
40
- if value = @scope.lookupvar(name.to_s) and value != :undefined and value != ""
41
- return value
42
- else
43
- # Just throw an error immediately, instead of searching for
44
- # other missingmethod things or whatever.
45
- raise Puppet::ParseError,
46
- "Could not find value for '%s'" % name
47
- end
48
- end
12
+ AST = Puppet::Parser::AST
49
13
 
50
- def result
51
- result = nil
52
- benchmark(:info, "Interpolated template #{@file}") do
53
- template = ERB.new(File.read(@file))
54
- result = template.result(binding)
55
- end
14
+ # This doesn't actually work right now.
15
+ Puppet.config.setdefaults(:puppet,
16
+ :lexical => [false, "Whether to use lexical scoping (vs. dynamic)."],
17
+ :templatedir => ["$vardir/templates",
18
+ "Where Puppet looks for template files."
19
+ ]
20
+ )
56
21
 
57
- result
58
- end
22
+ Puppet::Util.logmethods(self)
59
23
 
60
- def to_s
61
- "template[%s]" % @file
62
- end
63
- end
24
+ include Enumerable
25
+ include Puppet::Util::Errors
26
+ attr_accessor :parent, :level, :interp, :source, :host
27
+ attr_accessor :name, :type, :topscope, :base, :keyword
28
+ attr_accessor :top, :translated, :exported
64
29
 
65
- # This doesn't actually work right now.
66
- Puppet.config.setdefaults(:puppet,
67
- :lexical => [false, "Whether to use lexical scoping (vs. dynamic)."],
68
- :templatedir => ["$vardir/templates",
69
- "Where Puppet looks for template files."
70
- ]
71
- )
30
+ # Whether we behave declaratively. Note that it's a class variable,
31
+ # so all scopes behave the same.
32
+ @@declarative = true
72
33
 
73
- Puppet::Util.logmethods(self)
74
-
75
- include Enumerable
76
- attr_accessor :parent, :level, :interp
77
- attr_accessor :name, :type, :topscope, :base, :keyword
34
+ # Retrieve and set the declarative setting.
35
+ def self.declarative
36
+ return @@declarative
37
+ end
78
38
 
79
- attr_accessor :top, :context, :translated, :collectable
39
+ def self.declarative=(val)
40
+ @@declarative = val
41
+ end
80
42
 
81
- # This is probably not all that good of an idea, but...
82
- # This way a parent can share its tables with all of its children.
83
- attr_writer :nodetable, :classtable, :definedtable, :exportable
43
+ # This handles the shared tables that all scopes have. They're effectively
44
+ # global tables, except that they're only global for a single scope tree,
45
+ # which is why I can't use class variables for them.
46
+ def self.sharedtable(*names)
47
+ attr_accessor(*names)
48
+ @@sharedtables ||= []
49
+ @@sharedtables += names
50
+ end
84
51
 
85
- # Whether we behave declaratively. Note that it's a class variable,
86
- # so all scopes behave the same.
87
- @@declarative = true
52
+ # This is probably not all that good of an idea, but...
53
+ # This way a parent can share its tables with all of its children.
54
+ sharedtable :classtable, :definedtable, :exportable, :overridetable, :collecttable
88
55
 
89
- # Retrieve and set the declarative setting.
90
- def self.declarative
91
- return @@declarative
56
+ # Is the value true? This allows us to control the definition of truth
57
+ # in one place.
58
+ def self.true?(value)
59
+ if value == false or value == ""
60
+ return false
61
+ else
62
+ return true
92
63
  end
64
+ end
93
65
 
94
- def self.declarative=(val)
95
- @@declarative = val
66
+ # Add to our list of namespaces.
67
+ def add_namespace(ns)
68
+ return false if @namespaces.include?(ns)
69
+ if @namespaces == [""]
70
+ @namespaces = [ns]
71
+ else
72
+ @namespaces << ns
96
73
  end
74
+ end
97
75
 
98
- # Add all of the defaults for a given object to that object.
99
- def adddefaults(obj)
100
- defaults = lookupdefaults(obj.type)
101
-
102
- defaults.each do |var, value|
103
- unless obj[var]
104
- self.debug "Adding default %s for %s" %
105
- [var, obj.type]
106
-
107
- obj[var] = value
108
- end
109
- end
76
+ # Is the type a builtin type?
77
+ def builtintype?(type)
78
+ if typeklass = Puppet::Type.type(type)
79
+ return typeklass
80
+ else
81
+ return false
110
82
  end
83
+ end
111
84
 
112
- # Add a single object's tags to the global list of tags for
113
- # that object.
114
- def addtags(obj)
115
- unless defined? @tagtable
116
- raise Puppet::DevError, "Told to add tags, but no tag table"
117
- end
118
- list = @tagtable[obj.type][obj.name]
119
-
120
- obj.tags.each { |tag|
121
- unless list.include?(tag)
122
- if tag.nil? or tag == ""
123
- Puppet.debug "Got tag %s from %s(%s)" %
124
- [tag.inspect, obj.type, obj.name]
125
- else
126
- list << tag
127
- end
128
- end
129
- }
130
- end
85
+ # Create a new child scope.
86
+ def child=(scope)
87
+ @children.push(scope)
131
88
 
132
- # Is the type a builtin type?
133
- def builtintype?(type)
134
- if typeklass = Puppet::Type.type(type)
135
- return typeklass
136
- else
137
- return false
138
- end
89
+ # Copy all of the shared tables over to the child.
90
+ @@sharedtables.each do |name|
91
+ scope.send(name.to_s + "=", self.send(name))
139
92
  end
93
+ end
140
94
 
141
- # Verify that the given object isn't defined elsewhere.
142
- def chkobjectclosure(hash)
143
- type = hash[:type]
144
- name = hash[:name]
145
- unless name
146
- return true
147
- end
148
- if @definedtable[type].include?(name)
149
- typeklass = Puppet::Type.type(type)
150
- if typeklass and ! typeklass.isomorphic?
151
- Puppet.info "Allowing duplicate %s" % type
152
- else
153
- exobj = @definedtable[type][name]
154
-
155
- # Either it's a defined type, which are never
156
- # isomorphic, or it's a non-isomorphic type.
157
- msg = "Duplicate definition: %s[%s] is already defined" %
158
- [type, name]
159
-
160
- if exobj.file and exobj.line
161
- msg << " in file %s at line %s" %
162
- [exobj.file, exobj.line]
163
- end
164
-
165
- if hash[:line] or hash[:file]
166
- msg << "; cannot redefine"
167
- end
95
+ # Verify that the given object isn't defined elsewhere.
96
+ def chkobjectclosure(obj)
97
+ if exobj = @definedtable[obj.ref]
98
+ typeklass = Puppet::Type.type(obj.type)
99
+ if typeklass and ! typeklass.isomorphic?
100
+ Puppet.info "Allowing duplicate %s" % type
101
+ else
102
+ # Either it's a defined type, which are never
103
+ # isomorphic, or it's a non-isomorphic type.
104
+ msg = "Duplicate definition: %s is already defined" % obj.ref
168
105
 
169
- error = Puppet::ParseError.new(msg)
170
- raise error
106
+ if exobj.file and exobj.line
107
+ msg << " in file %s at line %s" %
108
+ [exobj.file, exobj.line]
171
109
  end
172
- end
173
110
 
174
- return true
175
- end
111
+ if obj.line or obj.file
112
+ msg << "; cannot redefine"
113
+ end
176
114
 
177
- def declarative=(val)
178
- self.class.declarative = val
115
+ raise Puppet::ParseError.new(msg)
116
+ end
179
117
  end
180
118
 
181
- def declarative
182
- self.class.declarative
183
- end
119
+ return true
120
+ end
184
121
 
185
- # Log the existing tags. At some point this should be in a better
186
- # place, but eh.
187
- def logtags
188
- @tagtable.sort { |a, b|
189
- a[0] <=> b[0]
190
- }.each { |type, names|
191
- names.sort { |a, b|
192
- a[0] <=> b[0]
193
- }.each { |name, tags|
194
- Puppet.info "%s(%s): '%s'" % [type, name, tags.join("' '")]
195
- }
196
- }
122
+ # Return the scope associated with a class. This is just here so
123
+ # that subclasses can set their parent scopes to be the scope of
124
+ # their parent class.
125
+ def class_scope(klass)
126
+ if klass.respond_to?(:fqname)
127
+ @classtable[klass.fqname]
128
+ else
129
+ @classtable[klass]
197
130
  end
131
+ end
198
132
 
199
- # Create a new child scope.
200
- def child=(scope)
201
- @children.push(scope)
133
+ # Return the list of collections.
134
+ def collections
135
+ @collecttable
136
+ end
202
137
 
203
- if defined? @nodetable
204
- scope.nodetable = @nodetable
205
- else
206
- raise Puppet::DevError, "No nodetable has been defined"
207
- end
138
+ def declarative=(val)
139
+ self.class.declarative = val
140
+ end
208
141
 
209
- if defined? @classtable
210
- scope.classtable = @classtable
211
- else
212
- raise Puppet::DevError, "No classtable has been defined"
213
- end
142
+ def declarative
143
+ self.class.declarative
144
+ end
214
145
 
215
- if defined? @exportable
216
- scope.exportable = @exportable
217
- else
218
- raise Puppet::DevError, "No exportable has been defined"
219
- end
146
+ # Test whether a given scope is declarative. Even though it's
147
+ # a global value, the calling objects don't need to know that.
148
+ def declarative?
149
+ @@declarative
150
+ end
220
151
 
221
- if defined? @definedtable
222
- scope.definedtable = @definedtable
223
- else
224
- raise Puppet::DevError, "No definedtable has been defined"
225
- end
226
- end
152
+ # Remove a specific child.
153
+ def delete(child)
154
+ @children.delete(child)
155
+ end
227
156
 
228
- # Test whether a given scope is declarative. Even though it's
229
- # a global value, the calling objects don't need to know that.
230
- def declarative?
231
- @@declarative
157
+ # Remove a resource from the various tables. This is only used when
158
+ # a resource maps to a definition and gets evaluated.
159
+ def deleteresource(resource)
160
+ if @definedtable[resource.ref]
161
+ @definedtable.delete(resource.ref)
232
162
  end
233
163
 
234
- # Remove a specific child.
235
- def delete(child)
236
- @children.delete(child)
164
+ if @children.include?(resource)
165
+ @children.delete(resource)
237
166
  end
167
+ end
238
168
 
239
- # Are we the top scope?
240
- def topscope?
241
- @level == 1
242
- end
169
+ # Are we the top scope?
170
+ def topscope?
171
+ @level == 1
172
+ end
243
173
 
244
- # Return a list of all of the defined classes.
245
- def classlist
246
- unless defined? @classtable
247
- raise Puppet::DevError, "Scope did not receive class table"
248
- end
249
- return @classtable.collect { |id, klass|
250
- # The class table can contain scopes or strings as its values
251
- # so support them accordingly.
252
- if klass.is_a? Scope
253
- klass.type
254
- else
255
- klass
256
- end
257
- }
174
+ # Return a list of all of the defined classes.
175
+ def classlist
176
+ unless defined? @classtable
177
+ raise Puppet::DevError, "Scope did not receive class table"
258
178
  end
179
+ return @classtable.keys.reject { |k| k == "" }
180
+ end
259
181
 
260
- # Yield each child scope in turn
261
- def each
262
- @children.each { |child|
263
- yield child
264
- }
265
- end
182
+ # Yield each child scope in turn
183
+ def each
184
+ @children.each { |child|
185
+ yield child
186
+ }
187
+ end
266
188
 
267
- # Evaluate a list of classes.
268
- def evalclasses(classes)
269
- return unless classes
270
- classes.each do |klass|
271
- if code = lookuptype(klass)
272
- # Just reuse the 'include' function, since that's the equivalent
273
- # of what we're doing here.
274
- function_include(klass)
275
- end
189
+ # Evaluate a list of classes.
190
+ def evalclasses(*classes)
191
+ retval = []
192
+ classes.each do |klass|
193
+ if obj = findclass(klass)
194
+ obj.safeevaluate :scope => self
195
+ retval << klass
276
196
  end
277
197
  end
198
+ retval
199
+ end
278
200
 
279
- # Evaluate a specific node's code. This method will normally be called
280
- # on the top-level scope, but it actually evaluates the node at the
281
- # appropriate scope.
282
- def evalnode(hash)
283
- objects = hash[:ast]
284
- names = hash[:names] or
285
- raise Puppet::DevError, "Node names must be provided to evalnode"
286
- facts = hash[:facts]
287
- classes = hash[:classes]
288
- parent = hash[:parent]
289
-
290
- # Always add "default" to our name list, so we're always searching
291
- # for a default node.
292
- names << "default"
293
-
294
- scope = code = nil
295
- # Find a node that matches one of our names
296
- names.each { |node|
297
- if nodehash = @nodetable[node]
298
- code = nodehash[:node]
299
- scope = nodehash[:scope]
300
-
301
- if node == "default"
302
- Puppet.info "Using default node"
303
- end
304
- break
305
- end
306
- }
201
+ def exported?
202
+ self.exported
203
+ end
307
204
 
308
- # And fail if we don't find one.
309
- unless scope and code
310
- raise Puppet::Error, "Could not find configuration for %s" %
311
- names.join(" or ")
205
+ def findclass(name)
206
+ @namespaces.each do |namespace|
207
+ if r = interp.findclass(namespace, name)
208
+ return r
312
209
  end
313
-
314
- # We need to do a little skullduggery here. We want a
315
- # temporary scope, because we don't want this scope to
316
- # show up permanently in the scope tree -- otherwise we could
317
- # not evaluate the node multiple times. We could conceivably
318
- # cache the results, but it's not worth it at this stage.
319
-
320
- # Note that we evaluate the node code with its containing
321
- # scope, not with the top scope. We also retrieve the created
322
- # scope so that we can get any classes set within it
323
- nodescope = code.safeevaluate(:scope => scope, :facts => facts)
324
-
325
- scope.evalclasses(classes)
326
210
  end
211
+ return nil
212
+ end
327
213
 
328
- # The top-level evaluate, used to evaluate a whole AST tree. This is
329
- # a strange method, in that it turns around and calls evaluate() on its
330
- # :ast argument.
331
- def evaluate(hash)
332
- objects = hash[:ast]
333
- facts = hash[:facts] || {}
334
-
335
- @@done = []
336
-
337
- unless objects
338
- raise Puppet::DevError, "Evaluation requires an AST tree"
339
- end
340
-
341
- # Set all of our facts in the top-level scope.
342
- facts.each { |var, value|
343
- self.setvar(var, value)
344
- }
345
-
346
- # Evaluate all of our configuration. This does not evaluate any
347
- # node definitions.
348
- result = objects.safeevaluate(:scope => self)
349
-
350
- # If they've provided a name or a parent, we assume they're looking
351
- # for nodes.
352
- if hash[:searched]
353
- # Specifying a parent node takes precedence, because it is assumed
354
- # that this node was found in a remote repository like ldap.
355
- gennode(hash)
356
- elsif hash.include? :names # else, look for it in the config
357
- evalnode(hash)
358
- else
359
- # Else we're not using nodes at all, so just evaluate any passed-in
360
- # classes.
361
- classes = hash[:classes] || []
362
- evalclasses(classes)
363
-
364
- # These classes would be passed in manually, via something like
365
- # a cfengine module
214
+ def finddefine(name)
215
+ @namespaces.each do |namespace|
216
+ if r = interp.finddefine(namespace, name)
217
+ return r
366
218
  end
219
+ end
220
+ return nil
221
+ end
367
222
 
368
- bucket = self.to_trans
369
-
370
- # Add our class list
371
- unless self.classlist.empty?
372
- bucket.classes = self.classlist
373
- end
223
+ def findresource(string, name = nil)
224
+ if name
225
+ string = "%s[%s]" % [string.capitalize, name]
226
+ end
374
227
 
375
- # Now clean up after ourselves
376
- [@@done].each do |table|
377
- table.clear
378
- end
228
+ @definedtable[string]
229
+ end
379
230
 
380
- return bucket
231
+ # Recursively complete the whole tree, in preparation for
232
+ # translation or storage.
233
+ def finish
234
+ self.each do |obj|
235
+ obj.finish
381
236
  end
237
+ end
382
238
 
383
- # Return the hash of objects that we specifically exported. We return
384
- # a hash to make it easy for the caller to deduplicate based on name.
385
- def exported(type)
386
- if @exportable.include?(type)
387
- return @exportable[type].dup
239
+ # Initialize our new scope. Defaults to having no parent and to
240
+ # being declarative.
241
+ def initialize(hash = {})
242
+ @parent = nil
243
+ @type = nil
244
+ @name = nil
245
+ @finished = false
246
+ if hash.include?(:namespace)
247
+ if n = hash[:namespace]
248
+ @namespaces = [n]
249
+ end
250
+ hash.delete(:namespace)
251
+ else
252
+ @namespaces = [""]
253
+ end
254
+ hash.each { |name, val|
255
+ method = name.to_s + "="
256
+ if self.respond_to? method
257
+ self.send(method, val)
388
258
  else
389
- return {}
390
- end
391
- end
392
-
393
- # Store our object in the central export table.
394
- def exportobject(obj)
395
- if @exportable.include?(obj.type) and
396
- @exportable[obj.type].include?(obj.name)
397
- raise Puppet::ParseError, "Object %s[%s] is already exported" %
398
- [obj.type, obj.name]
259
+ raise Puppet::DevError, "Invalid scope argument %s" % name
399
260
  end
261
+ }
400
262
 
401
- debug "Exporting %s[%s]" % [obj.type, obj.name]
263
+ @tags = []
402
264
 
403
- @exportable[obj.type][obj.name] = obj
265
+ if @parent.nil?
266
+ unless hash.include?(:declarative)
267
+ hash[:declarative] = true
268
+ end
269
+ self.istop(hash[:declarative])
270
+ @inside = nil
271
+ else
272
+ # This is here, rather than in newchild(), so that all
273
+ # of the later variable initialization works.
274
+ @parent.child = self
404
275
 
405
- return obj
276
+ @level = @parent.level + 1
277
+ @interp = @parent.interp
278
+ @source = hash[:source] || @parent.source
279
+ @topscope = @parent.topscope
280
+ #@inside = @parent.inside # Used for definition inheritance
281
+ @host = @parent.host
282
+ @type ||= @parent.type
406
283
  end
407
284
 
408
- # Pull in all of the appropriate classes and evaluate them. It'd
409
- # be nice if this didn't know quite so much about how AST::Node
410
- # operated internally. This is used when a list of classes is passed in,
411
- # instead of a node definition, such as from the cfengine module.
412
- def gennode(hash)
413
- names = hash[:names] or
414
- raise Puppet::DevError, "Node names must be provided to gennode"
415
- facts = hash[:facts]
416
- classes = hash[:classes]
417
- parent = hash[:parentnode]
418
- name = names.shift
419
- arghash = {
420
- :type => name,
421
- :code => AST::ASTArray.new(:pin => "[]")
422
- }
423
-
424
- #Puppet.notice "hash is %s" %
425
- # hash.inspect
426
- #Puppet.notice "Classes are %s, parent is %s" %
427
- # [classes.inspect, parent.inspect]
285
+ # Our child scopes and objects
286
+ @children = []
428
287
 
429
- if parent
430
- arghash[:parentclass] = parent
431
- end
288
+ # The symbol table for this scope. This is where we store variables.
289
+ @symtable = {}
432
290
 
433
- # Create the node
434
- node = AST::Node.new(arghash)
435
- node.keyword = "node"
291
+ # All of the defaults set for types. It's a hash of hashes,
292
+ # with the first key being the type, then the second key being
293
+ # the parameter.
294
+ @defaultstable = Hash.new { |dhash,type|
295
+ dhash[type] = {}
296
+ }
436
297
 
437
- # Now evaluate it, which evaluates the parent and nothing else
438
- # but does return the nodescope.
439
- scope = node.safeevaluate(:scope => self)
440
-
441
- # Finally evaluate our list of classes in this new scope.
442
- scope.evalclasses(classes)
298
+ unless @interp
299
+ raise Puppet::DevError, "Scopes require an interpreter"
443
300
  end
301
+ end
444
302
 
445
- # Initialize our new scope. Defaults to having no parent and to
446
- # being declarative.
447
- def initialize(hash = {})
448
- @parent = nil
449
- @type = nil
450
- @name = nil
451
- @finished = false
452
- hash.each { |name, val|
453
- method = name.to_s + "="
454
- if self.respond_to? method
455
- self.send(method, val)
456
- else
457
- raise Puppet::DevError, "Invalid scope argument %s" % name
458
- end
459
- }
460
-
461
- @tags = []
462
-
463
- if @parent.nil?
464
- unless hash.include?(:declarative)
465
- hash[:declarative] = true
466
- end
467
- self.istop(hash[:declarative])
468
- else
469
- # This is here, rather than in newchild(), so that all
470
- # of the later variable initialization works.
471
- @parent.child = self
472
-
473
- @level = @parent.level + 1
474
- @interp = @parent.interp
475
- @topscope = @parent.topscope
476
- @context = @parent.context
477
- end
478
-
479
- # Our child scopes and objects
480
- @children = []
303
+ # Associate the object directly with the scope, so that contained objects
304
+ # can look up what container they're running within.
305
+ def inside(arg = nil)
306
+ return @inside unless arg
307
+
308
+ old = @inside
309
+ @inside = arg
310
+ yield
311
+ ensure
312
+ #Puppet.warning "exiting %s" % @inside.name
313
+ @inside = old
314
+ end
481
315
 
482
- # The symbol table for this scope
483
- @symtable = Hash.new(nil)
316
+ # Mark that we're the top scope, and set some hard-coded info.
317
+ def istop(declarative = true)
318
+ # the level is mostly used for debugging
319
+ @level = 1
484
320
 
485
- # The type table for this scope
486
- @typetable = Hash.new(nil)
321
+ # The table for storing class singletons. This will only actually
322
+ # be used by top scopes and node scopes.
323
+ @classtable = {}
487
324
 
488
- # All of the defaults set for types. It's a hash of hashes,
489
- # with the first key being the type, then the second key being
490
- # the parameter.
491
- @defaultstable = Hash.new { |dhash,type|
492
- dhash[type] = Hash.new(nil)
493
- }
325
+ self.class.declarative = declarative
494
326
 
495
- # The object table is similar, but it is actually a hash of hashes
496
- # where the innermost objects are TransObject instances.
497
- @objectable = Hash.new { |typehash,typekey|
498
- # See #newobject for how to create the actual objects
499
- typehash[typekey] = Hash.new(nil)
500
- }
327
+ # The table for all defined objects.
328
+ @definedtable = {}
501
329
 
502
- # This is just for collecting statements locally, so we can
503
- # verify that there is no overlap within this specific scope
504
- @localobjectable = Hash.new { |typehash,typekey|
505
- typehash[typekey] = Hash.new(nil)
506
- }
330
+ # The list of objects that will available for export.
331
+ @exportable = {}
507
332
 
508
- # Map the names to the tables.
509
- @map = {
510
- "variable" => @symtable,
511
- "type" => @typetable,
512
- "node" => @nodetable,
513
- "object" => @objectable,
514
- "defaults" => @defaultstable
515
- }
333
+ # The list of overrides. This is used to cache overrides on objects
334
+ # that don't exist yet. We store an array of each override.
335
+ @overridetable = Hash.new do |overs, ref|
336
+ overs[ref] = []
516
337
  end
517
338
 
518
- # Mark that we're the top scope, and set some hard-coded info.
519
- def istop(declarative = true)
520
- # the level is mostly used for debugging
521
- @level = 1
339
+ # Eventually, if we support sites, this will allow definitions
340
+ # of nodes with the same name in different sites. For now
341
+ # the top-level scope is always the only site scope.
342
+ @sitescope = true
522
343
 
523
- # The table for storing class singletons. This will only actually
524
- # be used by top scopes and node scopes.
525
- @classtable = Hash.new(nil)
344
+ @namespaces = [""]
526
345
 
527
- self.class.declarative = declarative
346
+ # The list of collections that have been created. This is a global list,
347
+ # but they each refer back to the scope that created them.
348
+ @collecttable = []
528
349
 
529
- # The table for all defined objects.
530
- @definedtable = Hash.new { |types, type|
531
- types[type] = {}
532
- }
533
-
534
- # A table for storing nodes.
535
- @nodetable = Hash.new(nil)
536
-
537
- # The list of objects that will available for export.
538
- @exportable = Hash.new { |types, type|
539
- types[type] = {}
540
- }
350
+ @topscope = self
351
+ @type = "puppet"
352
+ @name = "top"
353
+ end
541
354
 
542
- # Eventually, if we support sites, this will allow definitions
543
- # of nodes with the same name in different sites. For now
544
- # the top-level scope is always the only site scope.
545
- @sitescope = true
546
-
547
- # And create a tag table, so we can collect all of the tags
548
- # associated with any objects created in this scope tree
549
- @tagtable = Hash.new { |types, type|
550
- types[type] = Hash.new { |names, name|
551
- names[name] = []
552
- }
355
+ # Collect all of the defaults set at any higher scopes.
356
+ # This is a different type of lookup because it's additive --
357
+ # it collects all of the defaults, with defaults in closer scopes
358
+ # overriding those in later scopes.
359
+ def lookupdefaults(type)
360
+ values = {}
361
+
362
+ # first collect the values from the parents
363
+ unless @parent.nil?
364
+ @parent.lookupdefaults(type).each { |var,value|
365
+ values[var] = value
553
366
  }
554
-
555
- @context = nil
556
- @topscope = self
557
- @type = "puppet"
558
- @name = "top"
559
- end
560
-
561
- # Look up a given class. This enables us to make sure classes are
562
- # singletons
563
- def lookupclass(klassid)
564
- unless defined? @classtable
565
- raise Puppet::DevError, "Scope did not receive class table"
566
- end
567
- return @classtable[klassid]
568
367
  end
569
368
 
570
- # Collect all of the defaults set at any higher scopes.
571
- # This is a different type of lookup because it's additive --
572
- # it collects all of the defaults, with defaults in closer scopes
573
- # overriding those in later scopes.
574
- def lookupdefaults(type)
575
- values = {}
576
-
577
- # first collect the values from the parents
578
- unless @parent.nil?
579
- @parent.lookupdefaults(type).each { |var,value|
580
- values[var] = value
581
- }
582
- end
583
-
584
- # then override them with any current values
585
- # this should probably be done differently
586
- if @defaultstable.include?(type)
587
- @defaultstable[type].each { |var,value|
588
- values[var] = value
589
- }
590
- end
591
- #Puppet.debug "Got defaults for %s: %s" %
592
- # [type,values.inspect]
593
- return values
594
- end
595
-
596
- # Look up all of the exported objects of a given type. Just like
597
- # lookupobject, this only searches up through parent classes, not
598
- # the whole scope tree.
599
- def lookupexported(type)
600
- found = []
601
- sub = proc { |table|
602
- # We always return nil so that it will search all the way
603
- # up the scope tree.
604
- if table.has_key?(type)
605
- table[type].each do |name, obj|
606
- found << obj
607
- end
608
- nil
609
- else
610
- info table.keys.inspect
611
- nil
612
- end
369
+ # then override them with any current values
370
+ # this should probably be done differently
371
+ if @defaultstable.include?(type)
372
+ @defaultstable[type].each { |var,value|
373
+ values[var] = value
613
374
  }
375
+ end
614
376
 
615
- value = lookup("object",sub, false)
377
+ #Puppet.debug "Got defaults for %s: %s" %
378
+ # [type,values.inspect]
379
+ return values
380
+ end
616
381
 
617
- return found
382
+ # Look up all of the exported objects of a given type. Just like
383
+ # lookupobject, this only searches up through parent classes, not
384
+ # the whole scope tree.
385
+ def lookupexported(type)
386
+ @definedtable.find_all do |name, r|
387
+ r.type == type and r.exported?
618
388
  end
389
+ end
619
390
 
620
- # Look up a node by name
621
- def lookupnode(name)
622
- #Puppet.debug "Looking up type %s" % name
623
- value = lookup("type",name)
624
- if value == :undefined
625
- return nil
626
- else
627
- #Puppet.debug "Found node %s" % name
628
- return value
629
- end
630
- end
391
+ def lookupoverrides(obj)
392
+ @overridetable[obj.ref]
393
+ end
631
394
 
632
- # Look up a defined type.
633
- def lookuptype(name)
634
- #Puppet.debug "Looking up type %s" % name
635
- value = lookup("type",name)
636
- if value == :undefined
637
- return nil
638
- else
639
- #Puppet.debug "Found type %s" % name
640
- return value
641
- end
642
- end
395
+ # Look up a defined type.
396
+ def lookuptype(name)
397
+ finddefine(name) || findclass(name)
398
+ end
643
399
 
644
- # Look up an object by name and type. This should only look up objects
645
- # within a class structure, not within the entire scope structure.
646
- def lookupobject(hash)
647
- type = hash[:type]
648
- name = hash[:name]
649
- #Puppet.debug "Looking up object %s of type %s in level %s" %
650
- # [name, type, @level]
651
- sub = proc { |table|
652
- if table.include?(type)
653
- if table[type].include?(name)
654
- table[type][name]
655
- end
656
- else
657
- nil
658
- end
659
- }
660
- value = lookup("object",sub, true)
661
- if value == :undefined
662
- return nil
663
- else
664
- return value
665
- end
400
+ def lookup_qualified_var(name, usestring)
401
+ parts = name.split(/::/)
402
+ shortname = parts.pop
403
+ klassname = parts.join("::")
404
+ klass = findclass(klassname)
405
+ unless klass
406
+ raise Puppet::ParseError, "Could not find class %s" % klassname
666
407
  end
667
-
668
- # Look up a variable. The simplest value search we do.
669
- def lookupvar(name)
670
- value = lookup("variable", name)
671
- if value == :undefined
672
- return ""
673
- else
674
- return value
675
- end
408
+ unless kscope = class_scope(klass)
409
+ raise Puppet::ParseError, "Class %s has not been evaluated so its variables cannot be referenced" % klass.fqname
676
410
  end
411
+ return kscope.lookupvar(shortname, usestring)
412
+ end
677
413
 
678
- def newcollection(coll)
679
- @children << coll
414
+ private :lookup_qualified_var
415
+
416
+ # Look up a variable. The simplest value search we do. Default to returning
417
+ # an empty string for missing values, but support returning a constant.
418
+ def lookupvar(name, usestring = true)
419
+ # If the variable is qualified, then find the specified scope and look the variable up there instead.
420
+ if name =~ /::/
421
+ return lookup_qualified_var(name, usestring)
422
+ end
423
+ # We can't use "if @symtable[name]" here because the value might be false
424
+ if @symtable.include?(name)
425
+ return @symtable[name]
426
+ elsif self.parent
427
+ return @parent.lookupvar(name, usestring)
428
+ elsif usestring
429
+ return ""
430
+ else
431
+ return :undefined
680
432
  end
433
+ end
681
434
 
682
- # Add a new object to our object table.
683
- def newobject(hash)
684
- if @objectable[hash[:type]].include?(hash[:name])
685
- raise Puppet::DevError, "Object %s[%s] is already defined" %
686
- [hash[:type], hash[:name]]
687
- end
688
-
689
- self.chkobjectclosure(hash)
690
-
691
- obj = nil
692
-
693
- obj = Puppet::TransObject.new(hash[:name], hash[:type])
435
+ def namespaces
436
+ @namespaces.dup
437
+ end
694
438
 
695
- @children << obj
439
+ # Add a collection to the global list.
440
+ def newcollection(coll)
441
+ @collecttable << coll
442
+ end
696
443
 
697
- @objectable[hash[:type]][hash[:name]] = obj
444
+ # Create a new scope.
445
+ def newscope(hash = {})
446
+ hash[:parent] = self
447
+ #debug "Creating new scope, level %s" % [self.level + 1]
448
+ return Puppet::Parser::Scope.new(hash)
449
+ end
698
450
 
699
- @definedtable[hash[:type]][hash[:name]] = obj
451
+ # Return the list of remaining overrides.
452
+ def overrides
453
+ #@overridetable.collect { |name, overs| overs }.flatten
454
+ @overridetable.values.flatten
455
+ end
700
456
 
701
- return obj
702
- end
457
+ def resources
458
+ @definedtable.values
459
+ end
703
460
 
704
- # Create a new scope.
705
- def newscope(hash = {})
706
- hash[:parent] = self
707
- #debug "Creating new scope, level %s" % [self.level + 1]
708
- return Puppet::Parser::Scope.new(hash)
461
+ def setclass?(obj)
462
+ if obj.respond_to?(:fqname)
463
+ @classtable.has_key?(obj.fqname)
464
+ else
465
+ @classtable[obj]
709
466
  end
467
+ end
710
468
 
711
- # Retrieve a specific node. This is used in ast.rb to find a
712
- # parent node and in findnode to retrieve and evaluate a node.
713
- def node(name)
714
- @nodetable[name]
469
+ # Store the fact that we've evaluated a given class. We use a hash
470
+ # that gets inherited from the top scope down, rather than a global
471
+ # hash. We store the object ID, not class name, so that we
472
+ # can support multiple unrelated classes with the same name.
473
+ def setclass(obj)
474
+ if obj.is_a?(AST::HostClass)
475
+ unless obj.fqname
476
+ raise Puppet::DevError, "Got a %s with no fully qualified name" %
477
+ obj.class
478
+ end
479
+ @classtable[obj.fqname] = self
480
+ else
481
+ raise Puppet::DevError, "Invalid class %s" % obj.inspect
715
482
  end
483
+ end
716
484
 
717
- # Store the fact that we've evaluated a given class. We use a hash
718
- # that gets inherited from the top scope down, rather than a global
719
- # hash. We store the object ID, not class name, so that we
720
- # can support multiple unrelated classes with the same name.
721
- def setclass(id, name)
722
- unless name =~ /^[a-z][\w-]*$/
723
- raise Puppet::ParseError, "Invalid class name '%s'" % name
724
- end
485
+ # Set all of our facts in the top-level scope.
486
+ def setfacts(facts)
487
+ facts.each { |var, value|
488
+ self.setvar(var, value)
489
+ }
490
+ end
725
491
 
726
- @classtable[id] = name
727
- end
492
+ # Add a new object to our object table and the global list, and do any necessary
493
+ # checks.
494
+ def setresource(obj)
495
+ self.chkobjectclosure(obj)
728
496
 
729
- # Store the scope for each class, so that other subclasses can look
730
- # them up.
731
- def setscope(id, scope)
732
- @classtable[id] = scope
733
- end
497
+ @children << obj
734
498
 
735
- # Set defaults for a type. The typename should already be downcased,
736
- # so that the syntax is isolated.
737
- def setdefaults(type,params)
738
- table = @defaultstable[type]
499
+ # The global table
500
+ @definedtable[obj.ref] = obj
739
501
 
740
- # if we got a single param, it'll be in its own array
741
- unless params[0].is_a?(Array)
742
- params = [params]
743
- end
502
+ return obj
503
+ end
744
504
 
745
- params.each { |ary|
746
- #Puppet.debug "Default for %s is %s => %s" %
747
- # [type,ary[0].inspect,ary[1].inspect]
748
- if @@declarative
749
- if table.include?(ary[0])
750
- error = Puppet::ParseError.new(
751
- "Default already defined for %s { %s }" %
752
- [type,ary[0]]
753
- )
754
- raise error
755
- end
756
- else
757
- if table.include?(ary[0])
758
- # we should maybe allow this warning to be turned off...
759
- Puppet.warning "Replacing default for %s { %s }" %
760
- [type,ary[0]]
761
- end
762
- end
763
- table[ary[0]] = ary[1]
764
- }
505
+ # Override a parameter in an existing object. If the object does not yet
506
+ # exist, then cache the override in a global table, so it can be flushed
507
+ # at the end.
508
+ def setoverride(resource)
509
+ resource.override = true
510
+ if obj = @definedtable[resource.ref]
511
+ obj.merge(resource)
512
+ else
513
+ @overridetable[resource.ref] << resource
765
514
  end
515
+ end
766
516
 
767
- # Store a host in the site node table.
768
- def setnode(name,code)
769
- unless defined? @nodetable
770
- raise Puppet::DevError, "No node table defined"
771
- end
772
- if @nodetable.include?(name)
773
- raise Puppet::ParseError, "Host %s is already defined" % name
517
+ # Set defaults for a type. The typename should already be downcased,
518
+ # so that the syntax is isolated. We don't do any kind of type-checking
519
+ # here; instead we let the resource do it when the defaults are used.
520
+ def setdefaults(type, params)
521
+ table = @defaultstable[type]
522
+
523
+ # if we got a single param, it'll be in its own array
524
+ params = [params] unless params.is_a?(Array)
525
+
526
+ params.each { |param|
527
+ #Puppet.debug "Default for %s is %s => %s" %
528
+ # [type,ary[0].inspect,ary[1].inspect]
529
+ if @@declarative
530
+ if table.include?(param.name)
531
+ self.fail "Default already defined for %s { %s }" %
532
+ [type,param.name]
533
+ end
774
534
  else
775
- #Puppet.warning "Setting node %s at level %s" % [name, @level]
776
-
777
- # We have to store both the scope that's setting the node and
778
- # the node itself, so that the node gets evaluated in the correct
779
- # scope.
780
- code.scope = self
781
- @nodetable[name] = {
782
- :scope => self,
783
- :node => code
784
- }
535
+ if table.include?(param.name)
536
+ # we should maybe allow this warning to be turned off...
537
+ Puppet.warning "Replacing default for %s { %s }" %
538
+ [type,param.name]
539
+ end
785
540
  end
786
- end
541
+ table[param.name] = param
542
+ }
543
+ end
787
544
 
788
- # Define our type.
789
- def settype(name,ltype)
790
- # Don't let them redefine the class in this scope.
791
- if @typetable.include?(name)
792
- raise Puppet::ParseError,
793
- "%s is already defined" % name
545
+ # Set a variable in the current scope. This will override settings
546
+ # in scopes above, but will not allow variables in the current scope
547
+ # to be reassigned if we're declarative (which is the default).
548
+ def setvar(name,value, file = nil, line = nil)
549
+ #Puppet.debug "Setting %s to '%s' at level %s" %
550
+ # [name.inspect,value,self.level]
551
+ if @symtable.include?(name)
552
+ if @@declarative
553
+ error = Puppet::ParseError.new("Cannot reassign variable %s" % name)
554
+ if file
555
+ error.file = file
556
+ end
557
+ if line
558
+ error.line = line
559
+ end
560
+ raise error
794
561
  else
795
- ltype.scope = self
796
- @typetable[name] = ltype
562
+ Puppet.warning "Reassigning %s to %s" % [name,value]
797
563
  end
798
564
  end
565
+ @symtable[name] = value
566
+ end
799
567
 
800
- # This method will fail if the named object is already defined anywhere
801
- # in the scope tree, which is what provides some minimal closure-like
802
- # behaviour.
803
- def setobject(hash)
804
- # FIXME This objectlookup stuff should be looking up using both
805
- # the name and the namevar.
806
-
807
- # First see if we can look the object up using normal scope
808
- # rules, i.e., one of our parent classes has defined the
809
- # object or something
810
-
811
- name = hash[:name]
812
- type = hash[:type]
813
- params = hash[:arguments]
814
- file = hash[:file]
815
- line = hash[:line]
816
-
817
- collectable = hash[:collectable] || self.collectable
818
-
819
- # Verify that we're not overriding any already-set parameters.
820
- if localobj = @localobjectable[type][name]
821
- params.each { |var, value|
822
- if localobj.include?(var)
823
- msg = "Cannot reassign attribute %s on %s[%s]" %
824
- [var, type, name]
825
-
826
- error = Puppet::ParseError.new(msg)
827
- error.line = line
828
- error.file = file
829
- raise error
568
+ # Return an interpolated string.
569
+ def strinterp(string, file = nil, line = nil)
570
+ # Most strings won't have variables in them.
571
+ ss = StringScanner.new(string)
572
+ out = ""
573
+ while not ss.eos?
574
+ if ss.scan(/^\$\{((\w*::)*\w+)\}|^\$((\w*::)*\w+)/)
575
+ # If it matches the backslash, then just retun the dollar sign.
576
+ if ss.matched == '\\$'
577
+ out << '$'
578
+ else # look the variable up
579
+ out << lookupvar(ss[1] || ss[3]).to_s || ""
580
+ end
581
+ elsif ss.scan(/^\\(.)/)
582
+ # Puppet.debug("Got escape: pos:%d; m:%s" % [ss.pos, ss.matched])
583
+ case ss[1]
584
+ when 'n'
585
+ out << "\n"
586
+ when 't'
587
+ out << "\t"
588
+ when 's'
589
+ out << " "
590
+ when '\\'
591
+ out << '\\'
592
+ when '$'
593
+ out << '$'
594
+ else
595
+ str = "Unrecognised escape sequence '#{ss.matched}'"
596
+ if file
597
+ str += " in file %s" % file
830
598
  end
831
- }
832
- end
833
-
834
- # First look for it in a parent scope
835
- obj = lookupobject(:name => name, :type => type)
836
-
837
- if obj
838
- unless collectable == obj.collectable
839
- msg = nil
840
- if collectable
841
- msg = "Exported %s[%s] cannot override local objects"
842
- [type, name]
843
- else
844
- msg = "Local %s[%s] cannot override exported objects"
845
- [type, name]
599
+ if line
600
+ str += " at line %s" % line
846
601
  end
847
-
848
- error = Puppet::ParseError.new(msg)
849
- error.line = line
850
- error.file = file
851
- raise error
602
+ Puppet.warning str
603
+ out << ss.matched
852
604
  end
853
- end
854
-
855
- unless obj and obj != :undefined
856
- unless obj = @objectable[type][name]
857
- obj = self.newobject(
858
- :type => type,
859
- :name => name,
860
- :line => line,
861
- :file => file
862
- )
863
-
864
- obj.collectable = collectable
865
-
866
- # only set these if we've created the object,
867
- # which is the most common case
868
- # FIXME we eventually need to store the file
869
- # and line with each param, not the object
870
- # itself.
871
- obj.file = file
872
- obj.line = line
605
+ elsif ss.scan(/^\$/)
606
+ out << '$'
607
+ elsif ss.scan(/^\\\n/) # an escaped carriage return
608
+ next
609
+ else
610
+ tmp = ss.scan(/[^\\$]+/)
611
+ # Puppet.debug("Got other: pos:%d; m:%s" % [ss.pos, tmp])
612
+ unless tmp
613
+ error = Puppet::ParseError.new("Could not parse string %s" %
614
+ string.inspect)
615
+ {:file= => file, :line= => line}.each do |m,v|
616
+ error.send(m, v) if v
617
+ end
618
+ raise error
873
619
  end
620
+ out << tmp
874
621
  end
875
-
876
- # Now add our parameters. This has the function of overriding
877
- # existing values, which might have been defined in a higher
878
- # scope.
879
- params.each { |var,value|
880
- # Add it to our found object
881
- obj[var] = value
882
- }
883
-
884
- # This is only used for override verification -- the local object
885
- # table does not have transobjects or whatever in it, it just has
886
- # simple hashes. This is necessary because setobject can modify
887
- # our object table or a parent class's object table, and we
888
- # still need to make sure param settings cannot be duplicated
889
- # within our scope.
890
- @localobjectable[type][name] ||= {}
891
- params.each { |var,value|
892
- # And add it to the local table; mmm, hack
893
- @localobjectable[type][name][var] = value
894
- }
895
-
896
- return obj
897
622
  end
898
623
 
899
- # Set a variable in the current scope. This will override settings
900
- # in scopes above, but will not allow variables in the current scope
901
- # to be reassigned if we're declarative (which is the default).
902
- def setvar(name,value)
903
- #Puppet.debug "Setting %s to '%s' at level %s" %
904
- # [name.inspect,value,self.level]
905
- if @@declarative and @symtable.include?(name)
906
- raise Puppet::ParseError, "Cannot reassign variable %s" % name
907
- else
908
- if @symtable.include?(name)
909
- Puppet.warning "Reassigning %s to %s" % [name,value]
910
- end
911
- @symtable[name] = value
912
- end
913
- end
624
+ return out
625
+ end
914
626
 
915
- # Return an interpolated string.
916
- def strinterp(string)
917
- newstring = string.gsub(/\\\$|\$\{(\w+)\}|\$(\w+)/) do |value|
918
- # If it matches the backslash, then just retun the dollar sign.
919
- if value == '\\$'
920
- '$'
921
- else # look the variable up
922
- var = $1 || $2
923
- lookupvar($1 || $2)
924
- end
627
+ # Add a tag to our current list. These tags will be added to all
628
+ # of the objects contained in this scope.
629
+ def tag(*ary)
630
+ ary.each { |tag|
631
+ if tag.nil? or tag == ""
632
+ puts caller
633
+ Puppet.debug "got told to tag with %s" % tag.inspect
634
+ next
925
635
  end
636
+ unless tag =~ /^\w[-\w]+$/
637
+ fail Puppet::ParseError, "Invalid tag %s" % tag.inspect
638
+ end
639
+ tag = tag.to_s
640
+ unless @tags.include?(tag)
641
+ #Puppet.info "Tagging scope %s with %s" % [self.object_id, tag]
642
+ @tags << tag
643
+ end
644
+ }
645
+ end
926
646
 
927
- return newstring.gsub(/\\t/, "\t").gsub(/\\n/, "\n").gsub(/\\s/, "\s")
928
- end
929
-
930
- # Add a tag to our current list. These tags will be added to all
931
- # of the objects contained in this scope.
932
- def tag(*ary)
933
- ary.each { |tag|
647
+ # Return the tags associated with this scope. It's basically
648
+ # just our parents' tags, plus our type. We don't cache this value
649
+ # because our parent tags might change between calls.
650
+ def tags
651
+ tmp = [] + @tags
652
+ unless ! defined? @type or @type.nil? or @type == ""
653
+ tmp << @type.to_s
654
+ end
655
+ if @parent
656
+ #info "Looking for tags in %s" % @parent.type
657
+ @parent.tags.each { |tag|
934
658
  if tag.nil? or tag == ""
935
- Puppet.debug "got told to tag with %s" % tag.inspect
659
+ Puppet.debug "parent returned tag %s" % tag.inspect
936
660
  next
937
661
  end
938
- unless @tags.include?(tag)
939
- #Puppet.info "Tagging scope %s with %s" % [self.object_id, tag]
940
- @tags << tag.to_s
662
+ unless tmp.include?(tag)
663
+ tmp << tag
941
664
  end
942
665
  }
943
666
  end
667
+ return tmp.sort.uniq
668
+ end
944
669
 
945
- # Return the tags associated with this scope. It's basically
946
- # just our parents' tags, plus our type.
947
- def tags
948
- tmp = [] + @tags
949
- unless ! defined? @type or @type.nil? or @type == ""
950
- tmp << @type.to_s
951
- end
952
- if @parent
953
- #info "Looking for tags in %s" % @parent.type
954
- @parent.tags.each { |tag|
955
- if tag.nil? or tag == ""
956
- Puppet.debug "parent returned tag %s" % tag.inspect
957
- next
958
- end
959
- unless tmp.include?(tag)
960
- tmp << tag
961
- end
962
- }
963
- end
964
- return tmp
670
+ # Used mainly for logging
671
+ def to_s
672
+ if self.name
673
+ return "%s[%s]" % [@type, @name]
674
+ else
675
+ return self.type.to_s
965
676
  end
677
+ end
966
678
 
967
- # Used mainly for logging
968
- def to_s
969
- if @name
970
- return "%s[%s]" % [@type, @name]
679
+ # Convert all of our objects as necessary.
680
+ def translate
681
+ ret = @children.collect do |child|
682
+ case child
683
+ when Puppet::Parser::Resource
684
+ child.to_trans
685
+ when self.class
686
+ child.translate
971
687
  else
972
- return @type.to_s
688
+ devfail "Got %s for translation" % child.class
973
689
  end
974
- end
975
-
976
- # Convert our scope to a TransBucket. Everything in our @localobjecttable
977
- # gets converted to either an evaluated definition, or a TransObject
978
- def to_trans
979
- results = []
980
-
981
- # Set this on entry, just in case someone tries to get all weird
982
- @translated = true
983
-
984
- @children.dup.each do |child|
985
- if @@done.include?(child)
986
- raise Puppet::DevError, "Already translated %s" %
987
- child.object_id
988
- else
989
- @@done << child
990
- end
991
- #warning "Working on %s of type %s with id %s" %
992
- # [child.type, child.class, child.object_id]
993
-
994
- # If it's a scope, then it can only be a subclass's scope, so
995
- # convert it to a transbucket and store it in our results list
996
- result = nil
997
- case child
998
- when Scope
999
- result = child.to_trans
1000
- when Puppet::TransObject
1001
- # These objects can map to defined types or builtin types.
1002
- # Builtin types should be passed out as they are, but defined
1003
- # types need to be evaluated. We have to wait until this
1004
- # point so that subclass overrides can happen.
1005
-
1006
- # Wait until the last minute to set tags, although this
1007
- # probably should not matter
1008
- child.tags = self.tags
1009
-
1010
- # Add any defaults.
1011
- self.adddefaults(child)
1012
-
1013
- # Then make sure this child's tags are stored in the
1014
- # central table. This should maybe be in the evaluate
1015
- # methods, but, eh.
1016
- @topscope.addtags(child)
1017
-
1018
- # Now that all that is done, check to see what kind of object
1019
- # it is.
1020
- if objecttype = lookuptype(child.type)
1021
- # It's a defined type, so evaluate it. Retain whether
1022
- # the object is collectable. If the object is collectable,
1023
- # then it will store all of its contents into the
1024
- # @exportable table, rather than returning them.
1025
- result = objecttype.safeevaluate(
1026
- :name => child.name,
1027
- :type => child.type,
1028
- :arguments => child.to_hash,
1029
- :scope => self,
1030
- :collectable => child.collectable
1031
- )
1032
- else
1033
- # If it's collectable, then store it. It will be
1034
- # stripped out in the interpreter using the collectstrip
1035
- # method. If we don't do this, then these objects
1036
- # don't get stored in the DB.
1037
- if child.collectable
1038
- exportobject(child)
1039
- end
1040
- result = child
1041
- end
1042
- # This is pretty hackish, but the collection has to actually
1043
- # be performed after all of the classes and definitions are
1044
- # evaluated, otherwise we won't catch objects that are exported
1045
- # in them. I think this will still be pretty limited in some
1046
- # cases, especially those where you are both exporting and
1047
- # collecting, but it's the best I can do for now.
1048
- when Puppet::Parser::AST::Collection
1049
- child.perform(self).each do |obj|
1050
- results << obj
1051
- end
1052
- else
1053
- raise Puppet::DevError,
1054
- "Puppet::Parse::Scope cannot handle objects of type %s" %
1055
- child.class
1056
- end
1057
-
1058
- # Skip nil objects or empty transbuckets
1059
- if result
1060
- unless result.is_a? Puppet::TransBucket and result.empty?
1061
- results << result
1062
- end
1063
- end
1064
- end
1065
-
1066
- # Get rid of any nil objects.
1067
- results.reject! { |child|
1068
- child.nil?
1069
- }
1070
-
1071
- # If we have a name and type, then make a TransBucket, which
1072
- # becomes a component.
1073
- # Else, just stack all of the objects into the current bucket.
1074
- if @type
1075
- bucket = Puppet::TransBucket.new
690
+ end.reject { |o| o.nil? }
691
+ bucket = Puppet::TransBucket.new ret
1076
692
 
1077
- if defined? @name and @name
1078
- bucket.name = @name
1079
- end
1080
- # it'd be nice not to have to do this...
1081
- results.each { |result|
1082
- #Puppet.warning "Result type is %s" % result.class
1083
- bucket.push(result)
1084
- }
1085
- bucket.type = @type
1086
-
1087
- if defined? @keyword
1088
- bucket.keyword = @keyword
1089
- end
1090
- #Puppet.debug(
1091
- # "TransBucket with name %s and type %s in scope %s" %
1092
- # [@name,@type,self.object_id]
1093
- #)
1094
-
1095
- # now find metaparams
1096
- @symtable.each { |var,value|
1097
- if Puppet::Type.metaparam?(var.intern)
1098
- #Puppet.debug("Adding metaparam %s" % var)
1099
- bucket.param(var,value)
1100
- else
1101
- #Puppet.debug("%s is not a metaparam" % var)
1102
- end
1103
- }
1104
- #Puppet.debug "Returning bucket %s from scope %s" %
1105
- # [bucket.name,self.object_id]
1106
- return bucket
1107
- else
1108
- Puppet.debug "typeless scope; just returning a list"
1109
- return results
1110
- end
693
+ case self.type
694
+ when "": bucket.type = "main"
695
+ when nil: devfail "A Scope with no type"
696
+ else
697
+ bucket.type = @type
1111
698
  end
699
+ if self.name
700
+ bucket.name = self.name
701
+ end
702
+ return bucket
703
+ end
1112
704
 
1113
- # Undefine a variable; only used for testing.
1114
- def unsetvar(var)
1115
- if @symtable.include?(var)
1116
- @symtable.delete(var)
1117
- end
705
+ # Undefine a variable; only used for testing.
706
+ def unsetvar(var)
707
+ if @symtable.include?(var)
708
+ @symtable.delete(var)
1118
709
  end
710
+ end
1119
711
 
1120
- protected
1121
-
1122
- # This method abstracts recursive searching. It accepts the type
1123
- # of search being done and then either a literal key to search for or
1124
- # a Proc instance to do the searching.
1125
- def lookup(type,sub, usecontext = false)
1126
- table = @map[type]
1127
- if table.nil?
1128
- error = Puppet::ParseError.new(
1129
- "Could not retrieve %s table at level %s" %
1130
- [type,self.level]
1131
- )
1132
- raise error
1133
- end
712
+ # Return an array of all of the unevaluated objects
713
+ def unevaluated
714
+ ary = @definedtable.find_all do |name, object|
715
+ ! object.builtin? and ! object.evaluated?
716
+ end.collect { |name, object| object }
1134
717
 
1135
- if sub.is_a?(Proc) and obj = sub.call(table)
1136
- return obj
1137
- elsif table.include?(sub)
1138
- return table[sub]
1139
- elsif ! @parent.nil?
1140
- # Context is used for retricting overrides.
1141
- if usecontext and self.context != @parent.context
1142
- return :undefined
1143
- else
1144
- return @parent.lookup(type,sub, usecontext)
1145
- end
1146
- else
1147
- return :undefined
1148
- end
718
+ if ary.empty?
719
+ return nil
720
+ else
721
+ return ary
1149
722
  end
1150
723
  end
1151
724
  end
1152
725
 
1153
- # $Id: scope.rb 1401 2006-07-18 14:00:33Z luke $
726
+ # $Id: scope.rb 2418 2007-04-26 19:09:24Z luke $