puppet 3.1.1 → 3.2.0.rc1

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 (477) hide show
  1. data/CONTRIBUTING.md +2 -2
  2. data/Gemfile +32 -19
  3. data/README_DEVELOPER.md +332 -14
  4. data/Rakefile +9 -5
  5. data/ext/build_defaults.yaml +2 -3
  6. data/ext/debian/changelog.erb +6 -0
  7. data/ext/debian/control +6 -6
  8. data/ext/envpuppet +4 -4
  9. data/ext/project_data.yaml +1 -0
  10. data/ext/puppet-nm-dispatcher +13 -0
  11. data/ext/redhat/puppet.spec.erb +17 -0
  12. data/ext/suse/client.init +1 -1
  13. data/ext/systemd/puppetagent.service +2 -2
  14. data/ext/systemd/puppetmaster.service +2 -2
  15. data/lib/hiera/scope.rb +29 -11
  16. data/lib/hiera_puppet.rb +1 -3
  17. data/lib/puppet/agent.rb +3 -3
  18. data/lib/puppet/application.rb +2 -2
  19. data/lib/puppet/application/agent.rb +27 -12
  20. data/lib/puppet/application/apply.rb +11 -1
  21. data/lib/puppet/application/describe.rb +1 -1
  22. data/lib/puppet/application/doc.rb +13 -9
  23. data/lib/puppet/application/filebucket.rb +0 -1
  24. data/lib/puppet/application/kick.rb +1 -0
  25. data/lib/puppet/application/master.rb +16 -8
  26. data/lib/puppet/daemon.rb +19 -64
  27. data/lib/puppet/defaults.rb +61 -5
  28. data/lib/puppet/error.rb +15 -4
  29. data/lib/puppet/external/nagios/grammar.ry +1 -1
  30. data/lib/puppet/external/nagios/makefile +1 -1
  31. data/lib/puppet/external/nagios/parser.rb +185 -618
  32. data/lib/puppet/external/pson/pure/parser.rb +47 -1
  33. data/lib/puppet/face/certificate.rb +3 -3
  34. data/lib/puppet/face/module.rb +1 -1
  35. data/lib/puppet/face/module/changes.rb +3 -1
  36. data/lib/puppet/face/module/uninstall.rb +1 -1
  37. data/lib/puppet/face/node/clean.rb +5 -5
  38. data/lib/puppet/feature/base.rb +3 -1
  39. data/lib/puppet/feature/libuser.rb +8 -0
  40. data/lib/puppet/file_serving/fileset.rb +9 -1
  41. data/lib/puppet/forge.rb +28 -5
  42. data/lib/puppet/forge/errors.rb +34 -0
  43. data/lib/puppet/forge/repository.rb +1 -1
  44. data/lib/puppet/indirector.rb +4 -1
  45. data/lib/puppet/indirector/catalog/compiler.rb +37 -30
  46. data/lib/puppet/indirector/facts/inventory_active_record.rb +1 -0
  47. data/lib/puppet/indirector/indirection.rb +28 -15
  48. data/lib/puppet/indirector/rest.rb +18 -10
  49. data/lib/puppet/interface.rb +11 -4
  50. data/lib/puppet/interface/action.rb +1 -3
  51. data/lib/puppet/interface/action_builder.rb +0 -3
  52. data/lib/puppet/interface/action_manager.rb +0 -3
  53. data/lib/puppet/interface/face_collection.rb +0 -2
  54. data/lib/puppet/interface/option.rb +0 -2
  55. data/lib/puppet/interface/option_builder.rb +0 -2
  56. data/lib/puppet/interface/option_manager.rb +0 -2
  57. data/lib/puppet/metatype/manager.rb +1 -1
  58. data/lib/puppet/module_tool.rb +1 -0
  59. data/lib/puppet/module_tool/applications/application.rb +0 -3
  60. data/lib/puppet/module_tool/applications/builder.rb +8 -20
  61. data/lib/puppet/module_tool/applications/checksummer.rb +1 -1
  62. data/lib/puppet/module_tool/applications/installer.rb +1 -0
  63. data/lib/puppet/module_tool/applications/unpacker.rb +3 -11
  64. data/lib/puppet/module_tool/checksums.rb +1 -1
  65. data/lib/puppet/module_tool/errors/installer.rb +18 -1
  66. data/lib/puppet/module_tool/modulefile.rb +2 -2
  67. data/lib/puppet/module_tool/skeleton/templates/generator/Modulefile.erb +1 -1
  68. data/lib/puppet/module_tool/tar.rb +17 -0
  69. data/lib/puppet/module_tool/tar/gnu.rb +9 -0
  70. data/lib/puppet/module_tool/tar/mini.rb +39 -0
  71. data/lib/puppet/module_tool/tar/solaris.rb +5 -0
  72. data/lib/puppet/network/http.rb +1 -0
  73. data/lib/puppet/network/http/connection.rb +9 -23
  74. data/lib/puppet/network/http/handler.rb +38 -7
  75. data/lib/puppet/network/http/rack/rest.rb +14 -3
  76. data/lib/puppet/network/http/webrick.rb +3 -1
  77. data/lib/puppet/network/http/webrick/rest.rb +11 -2
  78. data/lib/puppet/node/environment.rb +3 -1
  79. data/lib/puppet/parameter.rb +32 -29
  80. data/lib/puppet/parameter/package_options.rb +1 -1
  81. data/lib/puppet/parameter/path.rb +1 -1
  82. data/lib/puppet/parameter/value.rb +1 -1
  83. data/lib/puppet/parameter/value_collection.rb +7 -3
  84. data/lib/puppet/parser/ast.rb +3 -1
  85. data/lib/puppet/parser/ast/arithmetic_operator.rb +56 -12
  86. data/lib/puppet/parser/ast/astarray.rb +1 -1
  87. data/lib/puppet/parser/ast/block_expression.rb +41 -0
  88. data/lib/puppet/parser/ast/function.rb +13 -2
  89. data/lib/puppet/parser/ast/lambda.rb +107 -0
  90. data/lib/puppet/parser/ast/leaf.rb +1 -2
  91. data/lib/puppet/parser/ast/method_call.rb +77 -0
  92. data/lib/puppet/parser/ast/vardef.rb +7 -0
  93. data/lib/puppet/parser/compiler.rb +27 -16
  94. data/lib/puppet/parser/e_parser_adapter.rb +120 -0
  95. data/lib/puppet/parser/files.rb +7 -6
  96. data/lib/puppet/parser/functions.rb +10 -8
  97. data/lib/puppet/parser/functions/collect.rb +43 -0
  98. data/lib/puppet/parser/functions/each.rb +96 -0
  99. data/lib/puppet/parser/functions/foreach.rb +96 -0
  100. data/lib/puppet/parser/functions/fqdn_rand.rb +2 -2
  101. data/lib/puppet/parser/functions/hiera.rb +20 -2
  102. data/lib/puppet/parser/functions/hiera_array.rb +21 -2
  103. data/lib/puppet/parser/functions/hiera_hash.rb +23 -2
  104. data/lib/puppet/parser/functions/hiera_include.rb +33 -2
  105. data/lib/puppet/parser/functions/inline_template.rb +4 -4
  106. data/lib/puppet/parser/functions/reduce.rb +74 -0
  107. data/lib/puppet/parser/functions/reject.rb +46 -0
  108. data/lib/puppet/parser/functions/select.rb +46 -0
  109. data/lib/puppet/parser/functions/slice.rb +96 -0
  110. data/lib/puppet/parser/functions/template.rb +2 -2
  111. data/lib/puppet/parser/grammar.ra +7 -4
  112. data/lib/puppet/parser/lexer.rb +10 -0
  113. data/lib/puppet/parser/methods.rb +69 -0
  114. data/lib/puppet/parser/parser.rb +855 -808
  115. data/lib/puppet/parser/parser_factory.rb +62 -0
  116. data/lib/puppet/parser/parser_support.rb +8 -2
  117. data/lib/puppet/parser/scope.rb +153 -47
  118. data/lib/puppet/parser/templatewrapper.rb +28 -21
  119. data/lib/puppet/parser/type_loader.rb +3 -1
  120. data/lib/puppet/pops.rb +40 -0
  121. data/lib/puppet/pops/adaptable.rb +190 -0
  122. data/lib/puppet/pops/adapters.rb +65 -0
  123. data/lib/puppet/pops/containment.rb +37 -0
  124. data/lib/puppet/pops/issues.rb +258 -0
  125. data/lib/puppet/pops/label_provider.rb +71 -0
  126. data/lib/puppet/pops/model/ast_transformer.rb +636 -0
  127. data/lib/puppet/pops/model/ast_tree_dumper.rb +378 -0
  128. data/lib/puppet/pops/model/factory.rb +804 -0
  129. data/lib/puppet/pops/model/model.rb +567 -0
  130. data/lib/puppet/pops/model/model_label_provider.rb +75 -0
  131. data/lib/puppet/pops/model/model_tree_dumper.rb +352 -0
  132. data/lib/puppet/pops/model/tree_dumper.rb +59 -0
  133. data/lib/puppet/pops/parser/egrammar.ra +723 -0
  134. data/lib/puppet/pops/parser/eparser.rb +2300 -0
  135. data/lib/puppet/pops/parser/grammar.ra +746 -0
  136. data/lib/puppet/pops/parser/lexer.rb +842 -0
  137. data/lib/puppet/pops/parser/makefile +13 -0
  138. data/lib/puppet/pops/parser/parser_support.rb +203 -0
  139. data/lib/puppet/pops/patterns.rb +35 -0
  140. data/lib/puppet/pops/utils.rb +104 -0
  141. data/lib/puppet/pops/validation.rb +297 -0
  142. data/lib/puppet/pops/validation/checker3_1.rb +551 -0
  143. data/lib/puppet/pops/validation/validator_factory_3_1.rb +41 -0
  144. data/lib/puppet/pops/visitable.rb +6 -0
  145. data/lib/puppet/pops/visitor.rb +50 -0
  146. data/lib/puppet/property.rb +37 -28
  147. data/lib/puppet/property/ensure.rb +2 -2
  148. data/lib/puppet/property/ordered_list.rb +1 -1
  149. data/lib/puppet/provider.rb +26 -30
  150. data/lib/puppet/provider/aixobject.rb +45 -44
  151. data/lib/puppet/provider/augeas/augeas.rb +0 -1
  152. data/lib/puppet/provider/confiner.rb +1 -1
  153. data/lib/puppet/provider/cron/crontab.rb +107 -67
  154. data/lib/puppet/provider/group/groupadd.rb +59 -3
  155. data/lib/puppet/provider/interface/cisco.rb +4 -4
  156. data/lib/puppet/provider/mount/parsed.rb +1 -1
  157. data/lib/puppet/provider/nameservice.rb +22 -6
  158. data/lib/puppet/provider/nameservice/pw.rb +1 -1
  159. data/lib/puppet/provider/package/aix.rb +28 -4
  160. data/lib/puppet/provider/package/gem.rb +0 -2
  161. data/lib/puppet/provider/package/macports.rb +1 -1
  162. data/lib/puppet/provider/package/nim.rb +249 -4
  163. data/lib/puppet/provider/package/opkg.rb +77 -0
  164. data/lib/puppet/provider/package/pacman.rb +2 -2
  165. data/lib/puppet/provider/package/rpm.rb +30 -16
  166. data/lib/puppet/provider/package/yum.rb +3 -3
  167. data/lib/puppet/provider/parsedfile.rb +80 -3
  168. data/lib/puppet/provider/selmodule/semodule.rb +2 -2
  169. data/lib/puppet/provider/service/debian.rb +0 -4
  170. data/lib/puppet/provider/service/freebsd.rb +2 -2
  171. data/lib/puppet/provider/service/gentoo.rb +0 -9
  172. data/lib/puppet/provider/service/init.rb +27 -2
  173. data/lib/puppet/provider/service/launchd.rb +1 -1
  174. data/lib/puppet/provider/service/openwrt.rb +36 -0
  175. data/lib/puppet/provider/service/redhat.rb +0 -9
  176. data/lib/puppet/provider/service/src.rb +38 -4
  177. data/lib/puppet/provider/service/systemd.rb +2 -2
  178. data/lib/puppet/provider/service/upstart.rb +1 -8
  179. data/lib/puppet/provider/user/aix.rb +4 -10
  180. data/lib/puppet/provider/user/pw.rb +6 -10
  181. data/lib/puppet/provider/user/useradd.rb +129 -31
  182. data/lib/puppet/provider/vlan/cisco.rb +4 -4
  183. data/lib/puppet/reference/function.rb +2 -2
  184. data/lib/puppet/reference/indirection.rb +46 -5
  185. data/lib/puppet/reference/metaparameter.rb +2 -2
  186. data/lib/puppet/reports.rb +5 -5
  187. data/lib/puppet/reports/rrdgraph.rb +4 -4
  188. data/lib/puppet/reports/tagmail.rb +1 -1
  189. data/lib/puppet/resource.rb +1 -1
  190. data/lib/puppet/resource/type.rb +13 -11
  191. data/lib/puppet/scheduler.rb +16 -0
  192. data/lib/puppet/scheduler/job.rb +53 -0
  193. data/lib/puppet/scheduler/scheduler.rb +45 -0
  194. data/lib/puppet/scheduler/splay_job.rb +32 -0
  195. data/lib/puppet/scheduler/timer.rb +13 -0
  196. data/lib/puppet/settings/base_setting.rb +1 -1
  197. data/lib/puppet/simple_graph.rb +4 -4
  198. data/lib/puppet/ssl/base.rb +12 -2
  199. data/lib/puppet/ssl/certificate.rb +4 -1
  200. data/lib/puppet/ssl/certificate_request.rb +4 -1
  201. data/lib/puppet/ssl/certificate_revocation_list.rb +4 -1
  202. data/lib/puppet/ssl/configuration.rb +32 -0
  203. data/lib/puppet/ssl/host.rb +18 -21
  204. data/lib/puppet/ssl/key.rb +4 -1
  205. data/lib/puppet/ssl/validator.rb +116 -0
  206. data/lib/puppet/transaction.rb +1 -1
  207. data/lib/puppet/transaction/event.rb +3 -10
  208. data/lib/puppet/transaction/event_manager.rb +8 -1
  209. data/lib/puppet/transaction/report.rb +17 -16
  210. data/lib/puppet/type.rb +77 -69
  211. data/lib/puppet/type/cron.rb +20 -8
  212. data/lib/puppet/type/exec.rb +9 -3
  213. data/lib/puppet/type/file.rb +95 -21
  214. data/lib/puppet/type/file/content.rb +1 -1
  215. data/lib/puppet/type/file/mode.rb +7 -1
  216. data/lib/puppet/type/file/source.rb +2 -2
  217. data/lib/puppet/type/group.rb +11 -0
  218. data/lib/puppet/type/scheduled_task.rb +5 -1
  219. data/lib/puppet/type/service.rb +1 -1
  220. data/lib/puppet/type/ssh_authorized_key.rb +2 -2
  221. data/lib/puppet/type/user.rb +24 -6
  222. data/lib/puppet/util.rb +12 -2
  223. data/lib/puppet/util/classgen.rb +4 -4
  224. data/lib/puppet/util/colors.rb +55 -0
  225. data/lib/puppet/util/command_line/trollop.rb +4 -4
  226. data/lib/puppet/util/errors.rb +39 -3
  227. data/lib/puppet/util/fileparsing.rb +5 -0
  228. data/lib/puppet/util/filetype.rb +11 -9
  229. data/lib/puppet/util/instrumentation/instrumentable.rb +2 -2
  230. data/lib/puppet/util/libuser.conf +15 -0
  231. data/lib/puppet/util/libuser.rb +12 -0
  232. data/lib/puppet/util/monkey_patches.rb +48 -0
  233. data/lib/puppet/util/network_device.rb +1 -1
  234. data/lib/puppet/util/network_device/base.rb +2 -2
  235. data/lib/puppet/util/network_device/cisco/device.rb +29 -19
  236. data/lib/puppet/util/network_device/config.rb +5 -2
  237. data/lib/puppet/util/network_device/ipcalc.rb +1 -1
  238. data/lib/puppet/util/network_device/transport/ssh.rb +4 -3
  239. data/lib/puppet/util/network_device/transport/telnet.rb +4 -2
  240. data/lib/puppet/util/plugins.rb +4 -4
  241. data/lib/puppet/util/posix.rb +1 -1
  242. data/lib/puppet/util/profiler.rb +28 -0
  243. data/lib/puppet/util/profiler/logging.rb +47 -0
  244. data/lib/puppet/util/profiler/none.rb +8 -0
  245. data/lib/puppet/util/profiler/object_counts.rb +17 -0
  246. data/lib/puppet/util/profiler/wall_clock.rb +34 -0
  247. data/lib/puppet/util/provider_features.rb +1 -1
  248. data/lib/puppet/util/rdoc/parser.rb +5 -5
  249. data/lib/puppet/util/ssl.rb +38 -0
  250. data/lib/puppet/util/subclass_loader.rb +1 -5
  251. data/lib/puppet/util/windows.rb +1 -0
  252. data/lib/puppet/util/windows/process.rb +3 -0
  253. data/lib/puppet/util/windows/root_certs.rb +86 -0
  254. data/lib/puppet/util/windows/security.rb +1 -0
  255. data/lib/puppet/version.rb +1 -1
  256. data/spec/fixtures/integration/provider/cron/crontab/create_normal_entry +19 -0
  257. data/spec/fixtures/integration/provider/cron/crontab/create_special_entry +18 -0
  258. data/spec/fixtures/integration/provider/cron/crontab/crontab_user1 +15 -0
  259. data/spec/fixtures/integration/provider/cron/crontab/crontab_user2 +4 -0
  260. data/spec/fixtures/integration/provider/cron/crontab/modify_entry +13 -0
  261. data/spec/fixtures/integration/provider/cron/crontab/moved_cronjob_input1 +15 -0
  262. data/spec/fixtures/integration/provider/cron/crontab/moved_cronjob_input2 +6 -0
  263. data/spec/fixtures/integration/provider/cron/crontab/remove_named_resource +12 -0
  264. data/spec/fixtures/integration/provider/cron/crontab/remove_unnamed_resource +14 -0
  265. data/spec/fixtures/unit/pops/parser/lexer/aliastest.pp +16 -0
  266. data/spec/fixtures/unit/pops/parser/lexer/append.pp +11 -0
  267. data/spec/fixtures/unit/pops/parser/lexer/argumentdefaults.pp +14 -0
  268. data/spec/fixtures/unit/pops/parser/lexer/arithmetic_expression.pp +8 -0
  269. data/spec/fixtures/unit/pops/parser/lexer/arraytrailingcomma.pp +3 -0
  270. data/spec/fixtures/unit/pops/parser/lexer/casestatement.pp +65 -0
  271. data/spec/fixtures/unit/pops/parser/lexer/classheirarchy.pp +15 -0
  272. data/spec/fixtures/unit/pops/parser/lexer/classincludes.pp +17 -0
  273. data/spec/fixtures/unit/pops/parser/lexer/classpathtest.pp +11 -0
  274. data/spec/fixtures/unit/pops/parser/lexer/collection.pp +10 -0
  275. data/spec/fixtures/unit/pops/parser/lexer/collection_override.pp +8 -0
  276. data/spec/fixtures/unit/pops/parser/lexer/collection_within_virtual_definitions.pp +20 -0
  277. data/spec/fixtures/unit/pops/parser/lexer/componentmetaparams.pp +11 -0
  278. data/spec/fixtures/unit/pops/parser/lexer/componentrequire.pp +8 -0
  279. data/spec/fixtures/unit/pops/parser/lexer/deepclassheirarchy.pp +23 -0
  280. data/spec/fixtures/unit/pops/parser/lexer/defineoverrides.pp +17 -0
  281. data/spec/fixtures/unit/pops/parser/lexer/emptyclass.pp +9 -0
  282. data/spec/fixtures/unit/pops/parser/lexer/emptyexec.pp +3 -0
  283. data/spec/fixtures/unit/pops/parser/lexer/emptyifelse.pp +9 -0
  284. data/spec/fixtures/unit/pops/parser/lexer/falsevalues.pp +3 -0
  285. data/spec/fixtures/unit/pops/parser/lexer/filecreate.pp +11 -0
  286. data/spec/fixtures/unit/pops/parser/lexer/fqdefinition.pp +5 -0
  287. data/spec/fixtures/unit/pops/parser/lexer/fqparents.pp +11 -0
  288. data/spec/fixtures/unit/pops/parser/lexer/funccomma.pp +5 -0
  289. data/spec/fixtures/unit/pops/parser/lexer/hash.pp +33 -0
  290. data/spec/fixtures/unit/pops/parser/lexer/ifexpression.pp +12 -0
  291. data/spec/fixtures/unit/pops/parser/lexer/implicititeration.pp +15 -0
  292. data/spec/fixtures/unit/pops/parser/lexer/multilinecomments.pp +10 -0
  293. data/spec/fixtures/unit/pops/parser/lexer/multipleclass.pp +9 -0
  294. data/spec/fixtures/unit/pops/parser/lexer/multipleinstances.pp +7 -0
  295. data/spec/fixtures/unit/pops/parser/lexer/multisubs.pp +13 -0
  296. data/spec/fixtures/unit/pops/parser/lexer/namevartest.pp +9 -0
  297. data/spec/fixtures/unit/pops/parser/lexer/scopetest.pp +13 -0
  298. data/spec/fixtures/unit/pops/parser/lexer/selectorvalues.pp +49 -0
  299. data/spec/fixtures/unit/pops/parser/lexer/simpledefaults.pp +5 -0
  300. data/spec/fixtures/unit/pops/parser/lexer/simpleselector.pp +38 -0
  301. data/spec/fixtures/unit/pops/parser/lexer/singleary.pp +19 -0
  302. data/spec/fixtures/unit/pops/parser/lexer/singlequote.pp +11 -0
  303. data/spec/fixtures/unit/pops/parser/lexer/singleselector.pp +22 -0
  304. data/spec/fixtures/unit/pops/parser/lexer/subclass_name_duplication.pp +11 -0
  305. data/spec/fixtures/unit/pops/parser/lexer/tag.pp +9 -0
  306. data/spec/fixtures/unit/pops/parser/lexer/tagged.pp +35 -0
  307. data/spec/fixtures/unit/pops/parser/lexer/virtualresources.pp +14 -0
  308. data/spec/fixtures/unit/provider/cron/crontab/single_line.yaml +4 -4
  309. data/spec/fixtures/unit/provider/cron/crontab/vixie_header.txt +3 -0
  310. data/spec/fixtures/unit/provider/cron/parsed/managed +6 -0
  311. data/spec/fixtures/unit/provider/cron/parsed/simple +9 -0
  312. data/spec/fixtures/unit/provider/parsedfile/simple.txt +4 -0
  313. data/spec/fixtures/unit/provider/service/systemd/list_units +18 -0
  314. data/spec/integration/parser/collector_spec.rb +1 -1
  315. data/spec/integration/parser/compiler_spec.rb +252 -227
  316. data/spec/integration/parser/parser_spec.rb +171 -53
  317. data/spec/integration/parser/scope_spec.rb +1 -1
  318. data/spec/integration/provider/cron/crontab_spec.rb +187 -0
  319. data/spec/integration/provider/service/systemd_spec.rb +20 -0
  320. data/spec/integration/type/file_spec.rb +21 -21
  321. data/spec/integration/type/package_spec.rb +1 -1
  322. data/spec/lib/puppet_spec/database.rb +2 -5
  323. data/spec/spec_helper.rb +6 -1
  324. data/spec/unit/application/apply_spec.rb +16 -1
  325. data/spec/unit/application/describe_spec.rb +1 -1
  326. data/spec/unit/application/doc_spec.rb +55 -32
  327. data/spec/unit/application/kick_spec.rb +8 -6
  328. data/spec/unit/application/master_spec.rb +4 -4
  329. data/spec/unit/daemon_spec.rb +1 -1
  330. data/spec/unit/forge/errors_spec.rb +40 -0
  331. data/spec/unit/forge/repository_spec.rb +11 -1
  332. data/spec/unit/forge_spec.rb +13 -3
  333. data/spec/unit/hiera/backend/puppet_backend_spec.rb +1 -0
  334. data/spec/unit/hiera/scope_spec.rb +48 -25
  335. data/spec/unit/indirector/catalog/active_record_spec.rb +6 -3
  336. data/spec/unit/indirector/catalog/compiler_spec.rb +3 -28
  337. data/spec/unit/indirector/catalog/static_compiler_spec.rb +1 -1
  338. data/spec/unit/indirector/facts/inventory_active_record_spec.rb +154 -150
  339. data/spec/unit/indirector/indirection_spec.rb +5 -0
  340. data/spec/unit/indirector/resource/active_record_spec.rb +5 -22
  341. data/spec/unit/indirector_spec.rb +7 -1
  342. data/spec/unit/interface/action_builder_spec.rb +1 -1
  343. data/spec/unit/interface/action_manager_spec.rb +0 -2
  344. data/spec/unit/interface/action_spec.rb +1 -1
  345. data/spec/unit/interface/documentation_spec.rb +0 -2
  346. data/spec/unit/interface/face_collection_spec.rb +1 -1
  347. data/spec/unit/interface/option_builder_spec.rb +1 -1
  348. data/spec/unit/interface/option_spec.rb +0 -1
  349. data/spec/unit/module_spec.rb +17 -19
  350. data/spec/unit/module_tool/application_spec.rb +1 -3
  351. data/spec/unit/module_tool/applications/builder_spec.rb +38 -0
  352. data/spec/unit/module_tool/applications/checksummer_spec.rb +134 -0
  353. data/spec/unit/module_tool/applications/installer_spec.rb +71 -91
  354. data/spec/unit/module_tool/applications/searcher_spec.rb +1 -3
  355. data/spec/unit/module_tool/applications/uninstaller_spec.rb +18 -26
  356. data/spec/unit/module_tool/applications/unpacker_spec.rb +19 -52
  357. data/spec/unit/module_tool/tar/gnu_spec.rb +19 -0
  358. data/spec/unit/module_tool/tar/mini_spec.rb +59 -0
  359. data/spec/unit/module_tool/tar/solaris_spec.rb +19 -0
  360. data/spec/unit/network/http/connection_spec.rb +17 -2
  361. data/spec/unit/network/http/handler_spec.rb +195 -167
  362. data/spec/unit/network/http/rack/rest_spec.rb +26 -4
  363. data/spec/unit/network/http/webrick/rest_spec.rb +28 -1
  364. data/spec/unit/network/http/webrick_spec.rb +12 -3
  365. data/spec/unit/node/environment_spec.rb +421 -404
  366. data/spec/unit/parser/ast/arithmetic_operator_spec.rb +98 -2
  367. data/spec/unit/parser/collector_spec.rb +4 -4
  368. data/spec/unit/parser/compiler_spec.rb +13 -13
  369. data/spec/unit/parser/eparser_adapter_spec.rb +407 -0
  370. data/spec/unit/parser/functions/extlookup_spec.rb +20 -17
  371. data/spec/unit/parser/functions/fqdn_rand_spec.rb +5 -0
  372. data/spec/unit/parser/functions/hiera_include_spec.rb +0 -2
  373. data/spec/unit/parser/functions/hiera_spec.rb +0 -2
  374. data/spec/unit/parser/functions_spec.rb +27 -15
  375. data/spec/unit/parser/methods/collect_spec.rb +110 -0
  376. data/spec/unit/parser/methods/each_spec.rb +91 -0
  377. data/spec/unit/parser/methods/foreach_spec.rb +91 -0
  378. data/spec/unit/parser/methods/reduce_spec.rb +67 -0
  379. data/spec/unit/parser/methods/reject_spec.rb +73 -0
  380. data/spec/unit/parser/methods/select_spec.rb +79 -0
  381. data/spec/unit/parser/methods/shared.rb +61 -0
  382. data/spec/unit/parser/methods/slice_spec.rb +97 -0
  383. data/spec/unit/parser/parser_spec.rb +2 -2
  384. data/spec/unit/parser/scope_spec.rb +39 -16
  385. data/spec/unit/parser/templatewrapper_spec.rb +6 -5
  386. data/spec/unit/parser/type_loader_spec.rb +191 -165
  387. data/spec/unit/pops/adaptable_spec.rb +143 -0
  388. data/spec/unit/pops/containment_spec.rb +25 -0
  389. data/spec/unit/pops/factory_rspec_helper.rb +77 -0
  390. data/spec/unit/pops/factory_spec.rb +329 -0
  391. data/spec/unit/pops/issues_spec.rb +26 -0
  392. data/spec/unit/pops/label_provider_spec.rb +42 -0
  393. data/spec/unit/pops/model/ast_transformer_spec.rb +65 -0
  394. data/spec/unit/pops/model/model_spec.rb +37 -0
  395. data/spec/unit/pops/parser/lexer_spec.rb +884 -0
  396. data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +248 -0
  397. data/spec/unit/pops/parser/parse_calls_spec.rb +93 -0
  398. data/spec/unit/pops/parser/parse_conditionals_spec.rb +159 -0
  399. data/spec/unit/pops/parser/parse_containers_spec.rb +175 -0
  400. data/spec/unit/pops/parser/parse_resource_spec.rb +228 -0
  401. data/spec/unit/pops/parser/parser_rspec_helper.rb +11 -0
  402. data/spec/unit/pops/parser/parser_spec.rb +15 -0
  403. data/spec/unit/pops/parser/rgen_sanitycheck_spec.rb +16 -0
  404. data/spec/unit/pops/transformer/transform_basic_expressions_spec.rb +243 -0
  405. data/spec/unit/pops/transformer/transform_calls_spec.rb +80 -0
  406. data/spec/unit/pops/transformer/transform_conditionals_spec.rb +132 -0
  407. data/spec/unit/pops/transformer/transform_containers_spec.rb +182 -0
  408. data/spec/unit/pops/transformer/transform_resource_spec.rb +185 -0
  409. data/spec/unit/pops/transformer/transformer_rspec_helper.rb +27 -0
  410. data/spec/unit/pops/visitor_spec.rb +94 -0
  411. data/spec/unit/property_spec.rb +11 -0
  412. data/spec/unit/provider/augeas/augeas_spec.rb +3 -0
  413. data/spec/unit/provider/cron/crontab_spec.rb +97 -7
  414. data/spec/unit/provider/cron/parsed_spec.rb +325 -0
  415. data/spec/unit/provider/exec/posix_spec.rb +1 -1
  416. data/spec/unit/provider/group/groupadd_spec.rb +33 -3
  417. data/spec/unit/provider/group/pw_spec.rb +5 -5
  418. data/spec/unit/provider/nameservice_spec.rb +304 -0
  419. data/spec/unit/provider/package/aix_spec.rb +53 -11
  420. data/spec/unit/provider/package/aptrpm_spec.rb +6 -0
  421. data/spec/unit/provider/package/gem_spec.rb +6 -11
  422. data/spec/unit/provider/package/nim_spec.rb +216 -7
  423. data/spec/unit/provider/package/opkg_spec.rb +180 -0
  424. data/spec/unit/provider/package/rpm_spec.rb +149 -3
  425. data/spec/unit/provider/package/yum_spec.rb +6 -5
  426. data/spec/unit/provider/parsedfile_spec.rb +122 -28
  427. data/spec/unit/provider/service/freebsd_spec.rb +18 -0
  428. data/spec/unit/provider/service/init_spec.rb +108 -87
  429. data/spec/unit/provider/service/launchd_spec.rb +2 -2
  430. data/spec/unit/provider/service/openwrt_spec.rb +109 -0
  431. data/spec/unit/provider/service/src_spec.rb +117 -41
  432. data/spec/unit/provider/service/systemd_spec.rb +125 -17
  433. data/spec/unit/provider/service/upstart_spec.rb +1 -1
  434. data/spec/unit/provider/user/aix_spec.rb +42 -0
  435. data/spec/unit/provider/user/directoryservice_spec.rb +1 -0
  436. data/spec/unit/provider/user/pw_spec.rb +24 -12
  437. data/spec/unit/provider/user/user_role_add_spec.rb +1 -1
  438. data/spec/unit/provider/user/useradd_spec.rb +179 -15
  439. data/spec/unit/resource/type_spec.rb +3 -3
  440. data/spec/unit/scheduler/job_spec.rb +79 -0
  441. data/spec/unit/scheduler/scheduler_spec.rb +129 -0
  442. data/spec/unit/scheduler/splay_job_spec.rb +35 -0
  443. data/spec/unit/ssl/base_spec.rb +3 -9
  444. data/spec/unit/ssl/certificate_authority_spec.rb +1 -0
  445. data/spec/unit/ssl/certificate_request_spec.rb +3 -1
  446. data/spec/unit/ssl/certificate_spec.rb +3 -1
  447. data/spec/unit/ssl/configuration_spec.rb +74 -0
  448. data/spec/unit/ssl/host_spec.rb +28 -7
  449. data/spec/unit/ssl/validator_spec.rb +311 -0
  450. data/spec/unit/transaction/event_manager_spec.rb +49 -0
  451. data/spec/unit/transaction/event_spec.rb +20 -5
  452. data/spec/unit/transaction/report_spec.rb +8 -0
  453. data/spec/unit/type/cron_spec.rb +9 -0
  454. data/spec/unit/type/exec_spec.rb +11 -0
  455. data/spec/unit/type/file/content_spec.rb +20 -20
  456. data/spec/unit/type/file/mode_spec.rb +6 -0
  457. data/spec/unit/type/file/source_spec.rb +9 -7
  458. data/spec/unit/type/file_spec.rb +22 -3
  459. data/spec/unit/type/service_spec.rb +34 -21
  460. data/spec/unit/type_spec.rb +46 -1
  461. data/spec/unit/util/backups_spec.rb +2 -2
  462. data/spec/unit/util/execution_spec.rb +4 -1
  463. data/spec/unit/util/filetype_spec.rb +6 -0
  464. data/spec/unit/util/monkey_patches_spec.rb +18 -0
  465. data/spec/unit/util/network_device/cisco/device_spec.rb +37 -0
  466. data/spec/unit/util/network_device/config_spec.rb +14 -0
  467. data/spec/unit/util/network_device_spec.rb +3 -3
  468. data/spec/unit/util/profiler/logging_spec.rb +81 -0
  469. data/spec/unit/util/profiler/none_spec.rb +12 -0
  470. data/spec/unit/util/profiler/object_counts_spec.rb +14 -0
  471. data/spec/unit/util/profiler/wall_clock_spec.rb +13 -0
  472. data/spec/unit/util/pson_spec.rb +5 -0
  473. data/spec/unit/util/ssl_spec.rb +51 -0
  474. data/spec/unit/util/windows/root_certs_spec.rb +15 -0
  475. data/spec/unit/util_spec.rb +28 -0
  476. metadata +2593 -2307
  477. data/spec/unit/module_tool/applications/application_spec.rb +0 -19
@@ -1,4 +1,5 @@
1
1
  require 'puppet/provider/nameservice/objectadd'
2
+ require 'puppet/util/libuser'
2
3
 
3
4
  Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameService::ObjectAdd do
4
5
  desc "Group management via `groupadd` and its ilk. The default for most platforms.
@@ -13,17 +14,72 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
13
14
  value.is_a? Integer
14
15
  end
15
16
 
17
+ optional_commands :localadd => "lgroupadd"
18
+ has_feature :libuser if Puppet.features.libuser?
19
+
20
+ def exists?
21
+ return !!localgid if @resource.forcelocal?
22
+ super
23
+ end
24
+
25
+ def gid
26
+ return localgid if @resource.forcelocal?
27
+ get(:gid)
28
+ end
29
+
30
+ def findgroup(key, value)
31
+ group_file = "/etc/group"
32
+ group_keys = ['group_name', 'password', 'gid', 'user_list']
33
+ index = group_keys.index(key)
34
+ File.open(group_file) do |f|
35
+ f.each_line do |line|
36
+ group = line.split(":")
37
+ if group[index] == value
38
+ f.close
39
+ return group
40
+ end
41
+ end
42
+ end
43
+ false
44
+ end
45
+
46
+ def localgid
47
+ group = findgroup('group_name', resource[:name])
48
+ return group[2] if group
49
+ false
50
+ end
51
+
52
+ def check_allow_dup
53
+ # We have to manually check for duplicates when using libuser
54
+ # because by default duplicates are allowed. This check is
55
+ # to ensure consistent behaviour of the useradd provider when
56
+ # using both useradd and luseradd
57
+ if not @resource.allowdupe? and @resource.forcelocal?
58
+ if @resource.should(:gid) and findgroup('gid', @resource.should(:gid).to_s)
59
+ raise(Puppet::Error, "GID #{@resource.should(:gid).to_s} already exists, use allowdupe to force group creation")
60
+ end
61
+ elsif @resource.allowdupe? and not @resource.forcelocal?
62
+ return ["-o"]
63
+ end
64
+ []
65
+ end
66
+
16
67
  def addcmd
17
- cmd = [command(:add)]
68
+ if @resource.forcelocal?
69
+ cmd = [command(:localadd)]
70
+ @custom_environment = Puppet::Util::Libuser.getenv
71
+ else
72
+ cmd = [command(:add)]
73
+ end
74
+
18
75
  if gid = @resource.should(:gid)
19
76
  unless gid == :absent
20
77
  cmd << flag(:gid) << gid
21
78
  end
22
79
  end
23
- cmd << "-o" if @resource.allowdupe?
80
+ cmd += check_allow_dup
24
81
  cmd << "-r" if @resource.system? and self.class.system_groups?
25
82
  cmd << @resource[:name]
26
-
27
83
  cmd
28
84
  end
29
85
  end
@@ -8,8 +8,8 @@ Puppet::Type.type(:interface).provide :cisco, :parent => Puppet::Provider::Cisco
8
8
 
9
9
  def self.lookup(device, name)
10
10
  interface = nil
11
- device.command do |ng|
12
- interface = device.interface(name)
11
+ device.command do |dev|
12
+ interface = dev.interface(name)
13
13
  end
14
14
  interface
15
15
  end
@@ -19,8 +19,8 @@ Puppet::Type.type(:interface).provide :cisco, :parent => Puppet::Provider::Cisco
19
19
  end
20
20
 
21
21
  def flush
22
- device.command do |device|
23
- device.new_interface(name).update(former_properties, properties)
22
+ device.command do |dev|
23
+ dev.new_interface(name).update(former_properties, properties)
24
24
  end
25
25
  super
26
26
  end
@@ -88,7 +88,7 @@ Puppet::Type.type(:mount).provide(
88
88
 
89
89
  def self.mountinstances
90
90
  # XXX: Will not work for mount points that have spaces in path (does fstab support this anyways?)
91
- regex = case Facter.value(:osfamily)
91
+ regex = case Facter.value(:osfamily)
92
92
  when "Darwin"
93
93
  / on (?:\/private\/var\/automount)?(\S*)/
94
94
  when "Solaris", "HP-UX"
@@ -18,6 +18,7 @@ class Puppet::Provider::NameService < Puppet::Provider
18
18
 
19
19
  def initvars
20
20
  @checks = {}
21
+ @options = {}
21
22
  super
22
23
  end
23
24
 
@@ -76,10 +77,9 @@ class Puppet::Provider::NameService < Puppet::Provider
76
77
  # This is annoying, but there really aren't that many options,
77
78
  # and this *is* built into Ruby.
78
79
  def section
79
- unless defined?(@resource_type)
80
+ unless resource_type
80
81
  raise Puppet::DevError,
81
82
  "Cannot determine Etc section without a resource type"
82
-
83
83
  end
84
84
 
85
85
  if @resource_type.name == :group
@@ -164,7 +164,7 @@ class Puppet::Provider::NameService < Puppet::Provider
164
164
  end
165
165
 
166
166
  begin
167
- execute(self.addcmd)
167
+ execute(self.addcmd, {:failonfail => true, :combine => true, :custom_environment => @custom_environment})
168
168
  if feature?(:manages_password_age) && (cmd = passcmd)
169
169
  execute(cmd)
170
170
  end
@@ -202,7 +202,23 @@ class Puppet::Provider::NameService < Puppet::Provider
202
202
 
203
203
  # Retrieve a specific value by name.
204
204
  def get(param)
205
- (hash = getinfo(false)) ? hash[param] : nil
205
+ (hash = getinfo(false)) ? unmunge(param, hash[param]) : nil
206
+ end
207
+
208
+ def munge(name, value)
209
+ if block = self.class.option(name, :munge) and block.is_a? Proc
210
+ block.call(value)
211
+ else
212
+ value
213
+ end
214
+ end
215
+
216
+ def unmunge(name, value)
217
+ if block = self.class.option(name, :unmunge) and block.is_a? Proc
218
+ block.call(value)
219
+ else
220
+ value
221
+ end
206
222
  end
207
223
 
208
224
  # Retrieve what we can about our object
@@ -258,13 +274,13 @@ class Puppet::Provider::NameService < Puppet::Provider
258
274
 
259
275
  def initialize(resource)
260
276
  super
261
-
277
+ @custom_environment = {}
262
278
  @objectinfo = nil
263
279
  end
264
280
 
265
281
  def set(param, value)
266
282
  self.class.validate(param, value)
267
- cmd = modifycmd(param, value)
283
+ cmd = modifycmd(param, munge(param, value))
268
284
  raise Puppet::DevError, "Nameservice command must be an array" unless cmd.is_a?(Array)
269
285
  begin
270
286
  execute(cmd)
@@ -12,7 +12,7 @@ class PW < ObjectAdd
12
12
  "#{@resource.class.name.to_s}mod",
13
13
  @resource[:name],
14
14
  flag(param),
15
- value
15
+ munge(param, value)
16
16
  ]
17
17
  cmd
18
18
  end
@@ -2,12 +2,24 @@ require 'puppet/provider/package'
2
2
  require 'puppet/util/package'
3
3
 
4
4
  Puppet::Type.type(:package).provide :aix, :parent => Puppet::Provider::Package do
5
- desc "Installation from the AIX software directory."
5
+ desc "Installation from an AIX software directory, using the AIX `installp`
6
+ command. The `source` parameter is required for this provider, and should
7
+ be set to the absolute path (on the puppet agent machine) of a directory
8
+ containing one or more BFF package files.
9
+
10
+ The `installp` command will generate a table of contents file (named `.toc`)
11
+ in this directory, and the `name` parameter (or resource title) that you
12
+ specify for your `package` resource must match a package name that exists
13
+ in the `.toc` file.
14
+
15
+ Note that package downgrades are *not* supported; if your resource specifies
16
+ a specific version number and there is already a newer version of the package
17
+ installed on the machine, the resource will fail with an error message."
6
18
 
7
19
  # The commands we are using on an AIX box are installed standard
8
20
  # (except nimclient) nimclient needs the bos.sysmgt.nim.client fileset.
9
21
  commands :lslpp => "/usr/bin/lslpp",
10
- :installp => "/usr/sbin/installp"
22
+ :installp => "/usr/sbin/installp"
11
23
 
12
24
  # AIX supports versionable packages with and without a NIM server
13
25
  has_feature :versionable
@@ -60,6 +72,12 @@ Puppet::Type.type(:package).provide :aix, :parent => Puppet::Provider::Package d
60
72
  # Automatically process dependencies when installing/uninstalling
61
73
  # with the -g option to installp.
62
74
  installp "-gu", @resource[:name]
75
+
76
+ # installp will return an exit code of zero even if it didn't uninstall
77
+ # anything... so let's make sure it worked.
78
+ unless query().nil?
79
+ self.fail "Failed to uninstall package '#{@resource[:name]}'"
80
+ end
63
81
  end
64
82
 
65
83
  def install(useversion = true)
@@ -69,9 +87,15 @@ Puppet::Type.type(:package).provide :aix, :parent => Puppet::Provider::Package d
69
87
 
70
88
  pkg = @resource[:name]
71
89
 
72
- pkg << " #{@resource.should(:ensure)}" if (! @resource.should(:ensure).is_a? Symbol) and useversion
90
+ pkg += " #{@resource.should(:ensure)}" if (! @resource.should(:ensure).is_a? Symbol) and useversion
91
+
92
+ output = installp "-acgwXY", "-d", source, pkg
73
93
 
74
- installp "-acgwXY", "-d", source, pkg
94
+ # If the package is superseded, it means we're trying to downgrade and we
95
+ # can't do that.
96
+ if output =~ /^#{Regexp.escape(@resource[:name])}\s+.*\s+Already superseded by.*$/
97
+ self.fail "aix package provider is unable to downgrade packages"
98
+ end
75
99
  end
76
100
 
77
101
  def self.pkglist(hash = {})
@@ -72,8 +72,6 @@ Puppet::Type.type(:package).provide :gem, :parent => Puppet::Provider::Package d
72
72
  def install(useversion = true)
73
73
  command = [command(:gemcmd), "install"]
74
74
  command << "-v" << resource[:ensure] if (! resource[:ensure].is_a? Symbol) and useversion
75
- # Always include dependencies
76
- command << "--include-dependencies"
77
75
 
78
76
  if source = resource[:source]
79
77
  begin
@@ -14,7 +14,7 @@ Puppet::Type.type(:package).provide :macports, :parent => Puppet::Provider::Pack
14
14
 
15
15
  confine :operatingsystem => :darwin
16
16
 
17
- has_command(:port, "/opt/local/bin/port") do
17
+ has_command(:port, "/opt/local/bin/port") do
18
18
  environment :HOME => "/opt/local"
19
19
  end
20
20
 
@@ -2,11 +2,20 @@ require 'puppet/provider/package'
2
2
  require 'puppet/util/package'
3
3
 
4
4
  Puppet::Type.type(:package).provide :nim, :parent => :aix, :source => :aix do
5
- desc "Installation from NIM LPP source."
5
+ desc "Installation from an AIX NIM LPP source. The `source` parameter is required
6
+ for this provider, and should specify the name of a NIM `lpp_source` resource
7
+ that is visible to the puppet agent machine. This provider supports the
8
+ management of both BFF/installp and RPM packages.
9
+
10
+ Note that package downgrades are *not* supported; if your resource specifies
11
+ a specific version number and there is already a newer version of the package
12
+ installed on the machine, the resource will fail with an error message."
6
13
 
7
14
  # The commands we are using on an AIX box are installed standard
8
15
  # (except nimclient) nimclient needs the bos.sysmgt.nim.client fileset.
9
- commands :nimclient => "/usr/sbin/nimclient"
16
+ commands :nimclient => "/usr/sbin/nimclient",
17
+ :lslpp => "/usr/bin/lslpp",
18
+ :rpm => "rpm"
10
19
 
11
20
  # If NIM has not been configured, /etc/niminfo will not be present.
12
21
  # However, we have no way of knowing if the NIM server is not configured
@@ -17,10 +26,34 @@ Puppet::Type.type(:package).provide :nim, :parent => :aix, :source => :aix do
17
26
 
18
27
  attr_accessor :latest_info
19
28
 
29
+
30
+
20
31
  def self.srclistcmd(source)
21
32
  [ command(:nimclient), "-o", "showres", "-a", "installp_flags=L", "-a", "resource=#{source}" ]
22
33
  end
23
34
 
35
+ def uninstall
36
+ output = lslpp("-qLc", @resource[:name]).split(':')
37
+ # the 6th index in the colon-delimited output contains a " " for installp/BFF
38
+ # packages, and an "R" for RPMS. (duh.)
39
+ pkg_type = output[6]
40
+
41
+ case pkg_type
42
+ when " "
43
+ installp "-gu", @resource[:name]
44
+ when "R"
45
+ rpm "-e", @resource[:name]
46
+ else
47
+ self.fail("Unrecognized AIX package type identifier: '#{pkg_type}'")
48
+ end
49
+
50
+ # installp will return an exit code of zero even if it didn't uninstall
51
+ # anything... so let's make sure it worked.
52
+ unless query().nil?
53
+ self.fail "Failed to uninstall package '#{@resource[:name]}'"
54
+ end
55
+ end
56
+
24
57
  def install(useversion = true)
25
58
  unless source = @resource[:source]
26
59
  self.fail "An LPP source location is required in 'source'"
@@ -28,8 +61,220 @@ Puppet::Type.type(:package).provide :nim, :parent => :aix, :source => :aix do
28
61
 
29
62
  pkg = @resource[:name]
30
63
 
31
- pkg << " " << @resource.should(:ensure) if (! @resource.should(:ensure).is_a? Symbol) and useversion
64
+ version_specified = (useversion and (! @resource.should(:ensure).is_a? Symbol))
65
+
66
+ # This is unfortunate for a couple of reasons. First, because of a subtle
67
+ # difference in the command-line syntax for installing an RPM vs an
68
+ # installp/BFF package, we need to know ahead of time which type of
69
+ # package we're trying to install. This means we have to execute an
70
+ # extra command.
71
+ #
72
+ # Second, the command is easiest to deal with and runs fastest if we
73
+ # pipe it through grep on the shell. Unfortunately, the way that
74
+ # the provider `make_command_methods` metaprogramming works, we can't
75
+ # use that code path to execute the command (because it treats the arguments
76
+ # as an array of args that all apply to `nimclient`, which fails when you
77
+ # hit the `|grep`.) So here we just call straight through to P::U.execute
78
+ # with a single string argument for the full command, rather than going
79
+ # through the metaprogrammed layer. We could get rid of the grep and
80
+ # switch back to the metaprogrammed stuff, and just parse all of the output
81
+ # in Ruby... but we'd be doing an awful lot of unnecessary work.
82
+ showres_command = "/usr/sbin/nimclient -o showres -a resource=#{source} |/usr/bin/grep -p -E "
83
+ if (version_specified)
84
+ version = @resource.should(:ensure)
85
+ showres_command << "'#{Regexp.escape(pkg)}( |-)#{Regexp.escape(version)}'"
86
+ else
87
+ version = nil
88
+ showres_command << "'#{Regexp.escape(pkg)}'"
89
+ end
90
+ output = Puppet::Util.execute(showres_command)
91
+
92
+
93
+ if (version_specified)
94
+ package_type = determine_package_type(output, pkg, version)
95
+ else
96
+ package_type, version = determine_latest_version(output, pkg)
97
+ end
98
+
99
+ if (package_type == nil)
100
+ errmsg = "Unable to find package '#{pkg}' "
101
+ if (version_specified)
102
+ errmsg << "with version '#{version}' "
103
+ end
104
+ errmsg << "on lpp_source '#{source}'"
105
+ self.fail errmsg
106
+ end
107
+
108
+ # This part is a bit tricky. If there are multiple versions of the
109
+ # package available, then `version` will be set to a value, and we'll need
110
+ # to add that value to our installation command. However, if there is only
111
+ # one version of the package available, `version` will be set to `nil`, and
112
+ # we don't need to add the version string to the command.
113
+ if (version)
114
+ # Now we know if the package type is RPM or not, and we can adjust our
115
+ # `pkg` string for passing to the install command accordingly.
116
+ if (package_type == :rpm)
117
+ # RPM's expect a hyphen between the package name and the version number
118
+ version_separator = "-"
119
+ else
120
+ # installp/BFF packages expect a space between the package name and the
121
+ # version number.
122
+ version_separator = " "
123
+ end
124
+
125
+ pkg += version_separator + version
126
+ end
127
+
128
+ # NOTE: the installp flags here are ignored (but harmless) for RPMs
129
+ output = nimclient "-o", "cust", "-a", "installp_flags=acgwXY", "-a", "lpp_source=#{source}", "-a", "filesets=#{pkg}"
130
+
131
+ # If the package is superseded, it means we're trying to downgrade and we
132
+ # can't do that.
133
+ case package_type
134
+ when :installp
135
+ if output =~ /^#{Regexp.escape(@resource[:name])}\s+.*\s+Already superseded by.*$/
136
+ self.fail "NIM package provider is unable to downgrade packages"
137
+ end
138
+ when :rpm
139
+ if output =~ /^#{Regexp.escape(@resource[:name])}.* is superseded by.*$/
140
+ self.fail "NIM package provider is unable to downgrade packages"
141
+ end
142
+ end
143
+ end
144
+
145
+
146
+ private
147
+
148
+ ## UTILITY METHODS FOR PARSING `nimclient -o showres` output
149
+
150
+ # This makes me very sad. These regexes seem pretty fragile, but
151
+ # I spent a lot of time trying to figure out a solution that didn't
152
+ # require parsing the `nimclient -o showres` output and was unable to
153
+ # do so.
154
+ HEADER_LINE_REGEX = /^([^\s]+)\s+[^@]+@@(I|R):(\1)\s+[^\s]+$/
155
+ PACKAGE_LINE_REGEX = /^.*@@(I|R):(.*)$/
156
+ RPM_PACKAGE_REGEX = /^(.*)-(.*-\d+) \2$/
157
+ INSTALLP_PACKAGE_REGEX = /^(.*) (.*)$/
32
158
 
33
- nimclient "-o", "cust", "-a", "installp_flags=acgwXY", "-a", "lpp_source=#{source}", "-a", "filesets='#{pkg}'"
159
+ # Here is some sample output that shows what the above regexes will be up
160
+ # against:
161
+ # FOR AN INSTALLP PACKAGE:
162
+ #
163
+ # mypackage.foo ALL @@I:mypackage.foo _all_filesets
164
+ # @ 1.2.3.1 MyPackage Runtime Environment @@I:mypackage.foo 1.2.3.1
165
+ # + 1.2.3.4 MyPackage Runtime Environment @@I:mypackage.foo 1.2.3.4
166
+ # + 1.2.3.8 MyPackage Runtime Environment @@I:mypackage.foo 1.2.3.8
167
+ #
168
+ # FOR AN RPM PACKAGE:
169
+ #
170
+ # mypackage.foo ALL @@R:mypackage.foo _all_filesets
171
+ # @@R:mypackage.foo-1.2.3-1 1.2.3-1
172
+ # @@R:mypackage.foo-1.2.3-4 1.2.3-4
173
+ # @@R:mypackage.foo-1.2.3-8 1.2.3-8
174
+
175
+
176
+ # Parse the output of a `nimclient -o showres` command. Returns a two-dimensional
177
+ # hash, where the first-level keys are package names, the second-level keys are
178
+ # version number strings for all of the available version numbers for a package,
179
+ # and the values indicate the package type (:rpm / :installp)
180
+ def parse_showres_output(showres_output)
181
+ paragraphs = split_into_paragraphs(showres_output)
182
+ packages = {}
183
+ paragraphs.each do |para|
184
+ lines = para.split(/$/)
185
+ parse_showres_header_line(lines.shift)
186
+ lines.each do |l|
187
+ package, version, type = parse_showres_package_line(l)
188
+ packages[package] ||= {}
189
+ packages[package][version] = type
190
+ end
191
+ end
192
+ packages
193
+ end
194
+
195
+ # This method basically just splits the multi-line input string into chunks
196
+ # based on lines that contain nothing but whitespace. It also strips any
197
+ # leading or trailing whitespace (including newlines) from the resulting
198
+ # strings and then returns them as an array.
199
+ def split_into_paragraphs(showres_output)
200
+ showres_output.split(/^\s*$/).map { |p| p.strip! }
201
+ end
202
+
203
+ def parse_showres_header_line(line)
204
+ # This method doesn't produce any meaningful output; it's basically just
205
+ # meant to validate that the header line for the package listing output
206
+ # looks sane, so we know we're dealing with the kind of output that we
207
+ # are capable of handling.
208
+ unless line.match(HEADER_LINE_REGEX)
209
+ self.fail "Unable to parse output from nimclient showres: line does not match expected package header format:\n'#{line}'"
210
+ end
211
+ end
212
+
213
+ def parse_installp_package_string(package_string)
214
+ unless match = package_string.match(INSTALLP_PACKAGE_REGEX)
215
+ self.fail "Unable to parse output from nimclient showres: package string does not match expected installp package string format:\n'#{package_string}'"
216
+ end
217
+ package_name = match.captures[0]
218
+ version = match.captures[1]
219
+ [package_name, version, :installp]
220
+ end
221
+
222
+ def parse_rpm_package_string(package_string)
223
+ unless match = package_string.match(RPM_PACKAGE_REGEX)
224
+ self.fail "Unable to parse output from nimclient showres: package string does not match expected rpm package string format:\n'#{package_string}'"
225
+ end
226
+ package_name = match.captures[0]
227
+ version = match.captures[1]
228
+ [package_name, version, :rpm]
229
+ end
230
+
231
+ def parse_showres_package_line(line)
232
+ unless match = line.match(PACKAGE_LINE_REGEX)
233
+ self.fail "Unable to parse output from nimclient showres: line does not match expected package line format:\n'#{line}'"
234
+ end
235
+
236
+ package_type_flag = match.captures[0]
237
+ package_string = match.captures[1]
238
+
239
+ case package_type_flag
240
+ when "I"
241
+ parse_installp_package_string(package_string)
242
+ when "R"
243
+ parse_rpm_package_string(package_string)
244
+ else
245
+ self.fail "Unrecognized package type specifier: '#{package_type_flag}' in package line:\n'#{line}'"
246
+ end
247
+ end
248
+
249
+ # Given a blob of output from `nimclient -o showres` and a package name,
250
+ # this method checks to see if there are multiple versions of the package
251
+ # available on the lpp_source. If there are, the method returns
252
+ # [package_type, latest_version] (where package_type is one of :installp or :rpm).
253
+ # If there is only one version of the package available, it returns
254
+ # [package_type, nil], because the caller doesn't need to pass the version
255
+ # string to the command-line command if there is only one version available.
256
+ # If the package is not available at all, the method simply returns nil (instead
257
+ # of a tuple).
258
+ def determine_latest_version(showres_output, package_name)
259
+ packages = parse_showres_output(showres_output)
260
+ unless packages.has_key?(package_name)
261
+ return nil
262
+ end
263
+ if (packages[package_name].count == 1)
264
+ version = packages[package_name].keys[0]
265
+ return packages[package_name][version], nil
266
+ else
267
+ versions = packages[package_name].keys
268
+ latest_version = (versions.sort { |a, b| Puppet::Util::Package.versioncmp(b, a) })[0]
269
+ return packages[package_name][latest_version], latest_version
270
+ end
271
+ end
272
+
273
+ def determine_package_type(showres_output, package_name, version)
274
+ packages = parse_showres_output(showres_output)
275
+ unless (packages.has_key?(package_name) and packages[package_name].has_key?(version))
276
+ return nil
277
+ end
278
+ packages[package_name][version]
34
279
  end
35
280
  end