puppet 3.5.1-x86-mingw32 → 3.6.0.rc1-x86-mingw32

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 (342) hide show
  1. data/CONTRIBUTING.md +5 -0
  2. data/Gemfile +17 -9
  3. data/README.md +1 -0
  4. data/conf/fileserver.conf +4 -3
  5. data/ext/README.environment +8 -0
  6. data/ext/build_defaults.yaml +1 -1
  7. data/ext/debian/control +2 -2
  8. data/ext/debian/puppet-common.dirs +4 -0
  9. data/ext/debian/rules +4 -0
  10. data/ext/emacs/puppet-mode-init.el +1 -1
  11. data/ext/emacs/puppet-mode.el +36 -17
  12. data/ext/redhat/client.init +3 -3
  13. data/ext/redhat/puppet.spec.erb +9 -0
  14. data/ext/systemd/puppet.service +3 -4
  15. data/ext/systemd/puppetmaster.service +1 -3
  16. data/install.rb +1 -1
  17. data/lib/puppet.rb +2 -1
  18. data/lib/puppet/agent.rb +1 -1
  19. data/lib/puppet/application.rb +17 -17
  20. data/lib/puppet/application/doc.rb +1 -1
  21. data/lib/puppet/configurer.rb +4 -1
  22. data/lib/puppet/configurer/downloader.rb +13 -12
  23. data/lib/puppet/configurer/plugin_handler.rb +3 -3
  24. data/lib/puppet/context.rb +6 -1
  25. data/lib/puppet/defaults.rb +82 -12
  26. data/lib/puppet/environments.rb +169 -13
  27. data/lib/puppet/external/nagios/grammar.ry +2 -0
  28. data/lib/puppet/external/nagios/parser.rb +28 -19
  29. data/lib/puppet/face/config.rb +19 -6
  30. data/lib/puppet/face/module/generate.rb +209 -7
  31. data/lib/puppet/face/module/install.rb +17 -16
  32. data/lib/puppet/face/module/list.rb +83 -82
  33. data/lib/puppet/face/module/search.rb +1 -1
  34. data/lib/puppet/face/module/upgrade.rb +10 -9
  35. data/lib/puppet/face/parser.rb +3 -2
  36. data/lib/puppet/face/plugin.rb +8 -4
  37. data/lib/puppet/file_bucket/dipper.rb +6 -3
  38. data/lib/puppet/file_bucket/file.rb +4 -2
  39. data/lib/puppet/file_serving/metadata.rb +1 -1
  40. data/lib/puppet/file_system/memory_file.rb +27 -1
  41. data/lib/puppet/file_system/memory_impl.rb +15 -1
  42. data/lib/puppet/forge.rb +148 -52
  43. data/lib/puppet/forge/cache.rb +5 -1
  44. data/lib/puppet/forge/errors.rb +10 -0
  45. data/lib/puppet/forge/repository.rb +61 -26
  46. data/lib/puppet/functions.rb +548 -0
  47. data/lib/puppet/functions/assert_type.rb +42 -0
  48. data/lib/puppet/functions/import.rb +7 -0
  49. data/lib/puppet/indirector/facts/facter.rb +1 -1
  50. data/lib/puppet/indirector/file_bucket_file/file.rb +3 -2
  51. data/lib/puppet/indirector/rest.rb +18 -0
  52. data/lib/puppet/loaders.rb +20 -0
  53. data/lib/puppet/module.rb +2 -2
  54. data/lib/puppet/module_tool.rb +40 -14
  55. data/lib/puppet/module_tool/applications.rb +0 -1
  56. data/lib/puppet/module_tool/applications/application.rb +35 -26
  57. data/lib/puppet/module_tool/applications/builder.rb +16 -6
  58. data/lib/puppet/module_tool/applications/checksummer.rb +25 -19
  59. data/lib/puppet/module_tool/applications/installer.rb +196 -35
  60. data/lib/puppet/module_tool/applications/searcher.rb +1 -0
  61. data/lib/puppet/module_tool/applications/uninstaller.rb +7 -1
  62. data/lib/puppet/module_tool/applications/unpacker.rb +57 -31
  63. data/lib/puppet/module_tool/applications/upgrader.rb +221 -65
  64. data/lib/puppet/module_tool/checksums.rb +5 -8
  65. data/lib/puppet/module_tool/errors/installer.rb +12 -44
  66. data/lib/puppet/module_tool/errors/shared.rb +84 -11
  67. data/lib/puppet/module_tool/errors/upgrader.rb +16 -45
  68. data/lib/puppet/module_tool/install_directory.rb +7 -6
  69. data/lib/puppet/module_tool/installed_modules.rb +92 -0
  70. data/lib/puppet/module_tool/local_tarball.rb +91 -0
  71. data/lib/puppet/module_tool/metadata.rb +119 -115
  72. data/lib/puppet/module_tool/modulefile.rb +9 -9
  73. data/lib/puppet/module_tool/shared_behaviors.rb +19 -7
  74. data/lib/puppet/module_tool/skeleton/templates/generator/README.md.erb +79 -0
  75. data/lib/puppet/module_tool/skeleton/templates/generator/Rakefile +18 -0
  76. data/lib/puppet/module_tool/skeleton/templates/generator/metadata.json.erb +1 -0
  77. data/lib/puppet/module_tool/skeleton/templates/generator/spec/classes/init_spec.rb.erb +7 -0
  78. data/lib/puppet/module_tool/tar.rb +3 -7
  79. data/lib/puppet/module_tool/tar/gnu.rb +21 -9
  80. data/lib/puppet/module_tool/tar/mini.rb +2 -8
  81. data/lib/puppet/network/http/api/v1.rb +1 -1
  82. data/lib/puppet/network/http/api/v2/authorization.rb +4 -2
  83. data/lib/puppet/network/http/issues.rb +1 -0
  84. data/lib/puppet/network/http_pool.rb +15 -6
  85. data/lib/puppet/node/environment.rb +91 -20
  86. data/lib/puppet/parser/ast/pops_bridge.rb +44 -3
  87. data/lib/puppet/parser/collector.rb +1 -1
  88. data/lib/puppet/parser/compiler.rb +50 -7
  89. data/lib/puppet/parser/functions.rb +6 -0
  90. data/lib/puppet/parser/functions/generate.rb +1 -1
  91. data/lib/puppet/parser/resource.rb +1 -1
  92. data/lib/puppet/pops.rb +22 -1
  93. data/lib/puppet/pops/adapters.rb +8 -1
  94. data/lib/puppet/pops/binder/bindings_composer.rb +1 -1
  95. data/lib/puppet/pops/binder/bindings_factory.rb +1 -1
  96. data/lib/puppet/pops/binder/config/binder_config_checker.rb +1 -1
  97. data/lib/puppet/pops/binder/producers.rb +2 -2
  98. data/lib/puppet/pops/evaluator/access_operator.rb +65 -25
  99. data/lib/puppet/pops/evaluator/callable_signature.rb +101 -0
  100. data/lib/puppet/pops/evaluator/closure.rb +57 -2
  101. data/lib/puppet/pops/evaluator/compare_operator.rb +1 -1
  102. data/lib/puppet/pops/evaluator/evaluator_impl.rb +9 -11
  103. data/lib/puppet/pops/evaluator/runtime3_support.rb +72 -21
  104. data/lib/puppet/pops/functions/dispatch.rb +71 -0
  105. data/lib/puppet/pops/functions/dispatcher.rb +237 -0
  106. data/lib/puppet/pops/functions/function.rb +77 -0
  107. data/lib/puppet/pops/issues.rb +12 -0
  108. data/lib/puppet/pops/loader/base_loader.rb +102 -0
  109. data/lib/puppet/pops/loader/dependency_loader.rb +60 -0
  110. data/lib/puppet/pops/loader/gem_support.rb +49 -0
  111. data/lib/puppet/pops/loader/loader.rb +180 -0
  112. data/lib/puppet/pops/loader/loader_paths.rb +137 -0
  113. data/lib/puppet/pops/loader/module_loaders.rb +242 -0
  114. data/lib/puppet/pops/loader/null_loader.rb +44 -0
  115. data/lib/puppet/pops/loader/ruby_function_instantiator.rb +34 -0
  116. data/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +109 -0
  117. data/lib/puppet/pops/loader/simple_environment_loader.rb +20 -0
  118. data/lib/puppet/pops/loader/static_loader.rb +69 -0
  119. data/lib/puppet/pops/loader/uri_helper.rb +22 -0
  120. data/lib/puppet/pops/loaders.rb +240 -0
  121. data/lib/puppet/pops/model/factory.rb +13 -5
  122. data/lib/puppet/pops/model/model_tree_dumper.rb +12 -4
  123. data/lib/puppet/pops/parser/egrammar.ra +31 -18
  124. data/lib/puppet/pops/parser/eparser.rb +1137 -1106
  125. data/lib/puppet/pops/parser/lexer2.rb +17 -16
  126. data/lib/puppet/pops/semantic_error.rb +17 -0
  127. data/lib/puppet/pops/types/type_calculator.rb +150 -15
  128. data/lib/puppet/pops/types/type_factory.rb +69 -0
  129. data/lib/puppet/pops/types/type_parser.rb +9 -0
  130. data/lib/puppet/pops/types/types.rb +65 -4
  131. data/lib/puppet/pops/validation/checker4_0.rb +1 -1
  132. data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -1
  133. data/lib/puppet/property/list.rb +1 -1
  134. data/lib/puppet/provider/augeas/augeas.rb +2 -2
  135. data/lib/puppet/provider/cron/crontab.rb +13 -2
  136. data/lib/puppet/provider/package.rb +24 -0
  137. data/lib/puppet/provider/package/apt.rb +6 -1
  138. data/lib/puppet/provider/package/gem.rb +8 -2
  139. data/lib/puppet/provider/package/msi.rb +0 -15
  140. data/lib/puppet/provider/package/openbsd.rb +0 -24
  141. data/lib/puppet/provider/package/rpm.rb +3 -29
  142. data/lib/puppet/provider/package/windows.rb +0 -15
  143. data/lib/puppet/provider/package/yum.rb +101 -24
  144. data/lib/puppet/provider/package/yumhelper.py +31 -1
  145. data/lib/puppet/provider/package/zypper.rb +10 -28
  146. data/lib/puppet/provider/service/debian.rb +1 -1
  147. data/lib/puppet/provider/service/init.rb +3 -0
  148. data/lib/puppet/provider/service/openbsd.rb +318 -0
  149. data/lib/puppet/provider/service/redhat.rb +6 -3
  150. data/lib/puppet/provider/service/systemd.rb +2 -2
  151. data/lib/puppet/provider/yumrepo/inifile.rb +115 -42
  152. data/lib/puppet/resource.rb +13 -9
  153. data/lib/puppet/resource/catalog.rb +12 -6
  154. data/lib/puppet/resource/type_collection.rb +3 -3
  155. data/lib/puppet/settings.rb +57 -36
  156. data/lib/puppet/settings/config_file.rb +5 -0
  157. data/lib/puppet/settings/environment_conf.rb +147 -0
  158. data/lib/puppet/settings/ttl_setting.rb +48 -0
  159. data/lib/puppet/ssl/certificate_authority.rb +2 -3
  160. data/lib/puppet/ssl/certificate_authority/autosign_command.rb +1 -1
  161. data/lib/puppet/ssl/certificate_request.rb +4 -4
  162. data/lib/puppet/ssl/validator/default_validator.rb +2 -2
  163. data/lib/puppet/status.rb +1 -1
  164. data/lib/puppet/test/test_helper.rb +1 -0
  165. data/lib/puppet/type/augeas.rb +13 -1
  166. data/lib/puppet/type/cron.rb +32 -18
  167. data/lib/puppet/type/file.rb +4 -2
  168. data/lib/puppet/type/file/checksum.rb +15 -5
  169. data/lib/puppet/type/file/content.rb +3 -1
  170. data/lib/puppet/type/file/source.rb +5 -5
  171. data/lib/puppet/type/package.rb +12 -17
  172. data/lib/puppet/type/resources.rb +3 -1
  173. data/lib/puppet/type/scheduled_task.rb +4 -5
  174. data/lib/puppet/type/service.rb +12 -2
  175. data/lib/puppet/type/user.rb +106 -0
  176. data/lib/puppet/type/yumrepo.rb +9 -1
  177. data/lib/puppet/util/checksums.rb +60 -1
  178. data/lib/puppet/util/diff.rb +3 -1
  179. data/lib/puppet/util/execution.rb +20 -16
  180. data/lib/puppet/util/feature.rb +3 -0
  181. data/lib/puppet/util/logging.rb +19 -12
  182. data/lib/puppet/util/rubygems.rb +10 -0
  183. data/lib/puppet/util/watched_file.rb +1 -1
  184. data/lib/puppet/util/windows/security.rb +5 -3
  185. data/lib/puppet/vendor/load_semantic.rb +1 -0
  186. data/lib/puppet/vendor/require_vendored.rb +2 -0
  187. data/lib/puppet/vendor/semantic/Gemfile +20 -0
  188. data/lib/puppet/vendor/semantic/Rakefile +69 -0
  189. data/lib/puppet/vendor/semantic/lib/semantic.rb +7 -0
  190. data/lib/puppet/vendor/semantic/lib/semantic/dependency.rb +181 -0
  191. data/lib/puppet/vendor/semantic/lib/semantic/dependency/graph.rb +60 -0
  192. data/lib/puppet/vendor/semantic/lib/semantic/dependency/graph_node.rb +117 -0
  193. data/lib/puppet/vendor/semantic/lib/semantic/dependency/module_release.rb +46 -0
  194. data/lib/puppet/vendor/semantic/lib/semantic/dependency/source.rb +25 -0
  195. data/lib/puppet/vendor/semantic/lib/semantic/dependency/unsatisfiable_graph.rb +31 -0
  196. data/lib/puppet/vendor/semantic/lib/semantic/version.rb +168 -0
  197. data/lib/puppet/vendor/semantic/lib/semantic/version_range.rb +424 -0
  198. data/lib/puppet/vendor/semantic/spec/spec_helper.rb +24 -0
  199. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/graph_node_spec.rb +141 -0
  200. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/graph_spec.rb +162 -0
  201. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/module_release_spec.rb +143 -0
  202. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/source_spec.rb +5 -0
  203. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/unsatisfiable_graph_spec.rb +44 -0
  204. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency_spec.rb +383 -0
  205. data/lib/puppet/vendor/semantic/spec/unit/semantic/version_range_spec.rb +307 -0
  206. data/lib/puppet/vendor/semantic/spec/unit/semantic/version_spec.rb +608 -0
  207. data/lib/puppet/version.rb +1 -1
  208. data/spec/fixtures/java.tgz +0 -0
  209. data/spec/fixtures/stdlib.tgz +0 -0
  210. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/usee/lib/puppet/functions/usee/callee.rb +5 -0
  211. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/user/lib/puppet/functions/user/caller.rb +5 -0
  212. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/user/metadata.json +9 -0
  213. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/lib/puppet/functions/modulea/rb_func_a.rb +5 -0
  214. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/lib/puppet/functions/rb_func_a.rb +5 -0
  215. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/manifests/init.pp +3 -0
  216. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/metadata.json +19 -0
  217. data/spec/fixtures/unit/pops/loaders/loaders/wo_metadata_module/modules/moduleb/lib/puppet/functions/moduleb/rb_func_b.rb +6 -0
  218. data/spec/fixtures/unit/pops/loaders/loaders/wo_metadata_module/modules/moduleb/manifests/init.pp +3 -0
  219. data/spec/fixtures/unit/provider/naginator/define_empty_param +6 -0
  220. data/spec/fixtures/unit/provider/service/systemd/list_unit_files_services +7 -0
  221. data/spec/fixtures/unit/type/user/authorized_keys +5 -0
  222. data/spec/integration/application/apply_spec.rb +1 -2
  223. data/spec/integration/configurer_spec.rb +2 -2
  224. data/spec/integration/faces/plugin_spec.rb +62 -0
  225. data/spec/integration/indirector/catalog/compiler_spec.rb +1 -1
  226. data/spec/integration/indirector/catalog/queue_spec.rb +1 -1
  227. data/spec/integration/node/environment_spec.rb +2 -2
  228. data/spec/integration/parser/future_compiler_spec.rb +96 -142
  229. data/spec/integration/parser/ruby_manifest_spec.rb +0 -5
  230. data/spec/integration/provider/cron/crontab_spec.rb +35 -0
  231. data/spec/integration/type/file_spec.rb +74 -72
  232. data/spec/integration/util/windows/security_spec.rb +17 -0
  233. data/spec/lib/matchers/resource.rb +45 -13
  234. data/spec/lib/puppet_spec/files.rb +18 -0
  235. data/spec/lib/puppet_spec/module_tool/shared_functions.rb +56 -0
  236. data/spec/lib/puppet_spec/module_tool/stub_source.rb +133 -0
  237. data/spec/shared_contexts/checksums.rb +55 -0
  238. data/spec/unit/application/apply_spec.rb +10 -7
  239. data/spec/unit/application/doc_spec.rb +17 -10
  240. data/spec/unit/application/indirection_base_spec.rb +18 -10
  241. data/spec/unit/application/inspect_spec.rb +22 -20
  242. data/spec/unit/configurer/downloader_spec.rb +7 -6
  243. data/spec/unit/configurer/plugin_handler_spec.rb +5 -8
  244. data/spec/unit/configurer_spec.rb +1 -1
  245. data/spec/unit/context_spec.rb +23 -0
  246. data/spec/unit/environments_spec.rb +274 -16
  247. data/spec/unit/face/config_spec.rb +111 -11
  248. data/spec/unit/face/module/install_spec.rb +14 -85
  249. data/spec/unit/face/module/list_spec.rb +108 -62
  250. data/spec/unit/face/module/search_spec.rb +1 -1
  251. data/spec/unit/face/module/uninstall_spec.rb +21 -42
  252. data/spec/unit/face/parser_spec.rb +5 -2
  253. data/spec/unit/file_bucket/dipper_spec.rb +92 -86
  254. data/spec/unit/file_bucket/file_spec.rb +23 -75
  255. data/spec/unit/file_serving/metadata_spec.rb +74 -74
  256. data/spec/unit/forge/module_release_spec.rb +131 -0
  257. data/spec/unit/forge/repository_spec.rb +21 -20
  258. data/spec/unit/forge_spec.rb +99 -23
  259. data/spec/unit/functions/assert_type_spec.rb +59 -0
  260. data/spec/unit/functions4_spec.rb +671 -0
  261. data/spec/unit/indirector/catalog/static_compiler_spec.rb +2 -2
  262. data/spec/unit/indirector/facts/facter_spec.rb +9 -3
  263. data/spec/unit/indirector/file_bucket_file/file_spec.rb +156 -155
  264. data/spec/unit/indirector/rest_spec.rb +8 -0
  265. data/spec/unit/interface/face_collection_spec.rb +35 -23
  266. data/spec/unit/module_spec.rb +20 -8
  267. data/spec/unit/module_tool/applications/builder_spec.rb +40 -12
  268. data/spec/unit/module_tool/applications/checksummer_spec.rb +86 -105
  269. data/spec/unit/module_tool/applications/installer_spec.rb +293 -261
  270. data/spec/unit/module_tool/applications/searcher_spec.rb +1 -1
  271. data/spec/unit/module_tool/applications/uninstaller_spec.rb +90 -154
  272. data/spec/unit/module_tool/applications/unpacker_spec.rb +12 -12
  273. data/spec/unit/module_tool/applications/upgrader_spec.rb +286 -18
  274. data/spec/unit/module_tool/metadata_spec.rb +223 -14
  275. data/spec/unit/module_tool/tar/gnu_spec.rb +12 -9
  276. data/spec/unit/module_tool/tar/mini_spec.rb +1 -1
  277. data/spec/unit/module_tool/tar_spec.rb +4 -18
  278. data/spec/unit/module_tool_spec.rb +123 -27
  279. data/spec/unit/network/formats_spec.rb +2 -2
  280. data/spec/unit/network/http_pool_spec.rb +21 -0
  281. data/spec/unit/network/rights_spec.rb +10 -8
  282. data/spec/unit/node/environment_spec.rb +27 -2
  283. data/spec/unit/parser/collector_spec.rb +1 -1
  284. data/spec/unit/parser/compiler_spec.rb +1 -1
  285. data/spec/unit/parser/functions/generate_spec.rb +4 -0
  286. data/spec/unit/pops/evaluator/access_ops_spec.rb +50 -11
  287. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +25 -0
  288. data/spec/unit/pops/loaders/dependency_loader_spec.rb +44 -0
  289. data/spec/unit/pops/loaders/loader_paths_spec.rb +66 -0
  290. data/spec/unit/pops/loaders/loaders_spec.rb +105 -0
  291. data/spec/unit/pops/loaders/module_loaders_spec.rb +119 -0
  292. data/spec/unit/pops/loaders/static_loader_spec.rb +46 -0
  293. data/spec/unit/pops/types/type_calculator_spec.rb +145 -10
  294. data/spec/unit/pops/types/type_factory_spec.rb +101 -0
  295. data/spec/unit/pops/types/type_parser_spec.rb +22 -0
  296. data/spec/unit/property/list_spec.rb +9 -1
  297. data/spec/unit/provider/augeas/augeas_spec.rb +58 -11
  298. data/spec/unit/provider/cron/crontab_spec.rb +1 -0
  299. data/spec/unit/provider/cron/parsed_spec.rb +15 -0
  300. data/spec/unit/provider/naginator_spec.rb +14 -0
  301. data/spec/unit/provider/package/apt_spec.rb +78 -64
  302. data/spec/unit/provider/package/gem_spec.rb +15 -0
  303. data/spec/unit/provider/package/rpm_spec.rb +6 -6
  304. data/spec/unit/provider/package/windows_spec.rb +1 -1
  305. data/spec/unit/provider/package/yum_spec.rb +199 -104
  306. data/spec/unit/provider/package/zypper_spec.rb +41 -15
  307. data/spec/unit/provider/service/openbsd_spec.rb +129 -22
  308. data/spec/unit/provider/service/redhat_spec.rb +18 -4
  309. data/spec/unit/provider/service/systemd_spec.rb +5 -9
  310. data/spec/unit/provider/service/upstart_spec.rb +1 -1
  311. data/spec/unit/provider/user/directoryservice_spec.rb +10 -0
  312. data/spec/unit/provider/yumrepo/inifile_spec.rb +171 -15
  313. data/spec/unit/resource/catalog_spec.rb +20 -104
  314. data/spec/unit/resource/type_collection_spec.rb +10 -9
  315. data/spec/unit/settings/config_file_spec.rb +29 -6
  316. data/spec/unit/settings/environment_conf_spec.rb +51 -0
  317. data/spec/unit/settings_spec.rb +97 -12
  318. data/spec/unit/ssl/certificate_authority_spec.rb +2 -0
  319. data/spec/unit/type/augeas_spec.rb +1 -1
  320. data/spec/unit/type/cron_spec.rb +6 -7
  321. data/spec/unit/type/file/checksum_spec.rb +6 -0
  322. data/spec/unit/type/file/content_spec.rb +277 -207
  323. data/spec/unit/type/file_spec.rb +9 -7
  324. data/spec/unit/type/user_spec.rb +106 -18
  325. data/spec/unit/type/yumrepo_spec.rb +8 -0
  326. data/spec/unit/util/checksums_spec.rb +12 -5
  327. data/spec/unit/util/diff_spec.rb +8 -0
  328. data/spec/unit/util/execution_spec.rb +4 -4
  329. data/spec/unit/util/feature_spec.rb +2 -0
  330. data/spec/unit/util/logging_spec.rb +14 -4
  331. data/spec/unit/util/rdoc/parser_spec.rb +5 -4
  332. data/spec/unit/util/rubygems_spec.rb +14 -0
  333. data/tasks/parallel.rake +2 -2
  334. metadata +154 -21
  335. checksums.yaml +0 -7
  336. data/lib/puppet/module_tool/applications/generator.rb +0 -142
  337. data/lib/puppet/module_tool/skeleton.rb +0 -37
  338. data/lib/puppet/module_tool/skeleton/templates/generator/Modulefile.erb +0 -11
  339. data/lib/puppet/module_tool/skeleton/templates/generator/README.erb +0 -16
  340. data/lib/puppet/module_tool/tar/solaris.rb +0 -5
  341. data/spec/fixtures/unit/provider/service/systemd/list_units_services +0 -17
  342. data/spec/unit/module_tool/tar/solaris_spec.rb +0 -22
@@ -2,11 +2,13 @@ require 'open-uri'
2
2
  require 'pathname'
3
3
  require 'fileutils'
4
4
  require 'tmpdir'
5
- require 'semver'
5
+
6
6
  require 'puppet/forge'
7
7
  require 'puppet/module_tool'
8
8
  require 'puppet/module_tool/shared_behaviors'
9
9
  require 'puppet/module_tool/install_directory'
10
+ require 'puppet/module_tool/local_tarball'
11
+ require 'puppet/module_tool/installed_modules'
10
12
 
11
13
  module Puppet::ModuleTool
12
14
  module Applications
@@ -15,60 +17,166 @@ module Puppet::ModuleTool
15
17
  include Puppet::ModuleTool::Errors
16
18
  include Puppet::Forge::Errors
17
19
 
18
- def initialize(name, forge, install_dir, options = {})
20
+ def initialize(name, install_dir, options = {})
19
21
  super(options)
22
+
20
23
  @action = :install
21
24
  @environment = options[:environment_instance]
22
- @force = options[:force]
23
- @ignore_dependencies = options[:force] || options[:ignore_dependencies]
25
+ @ignore_dependencies = forced? || options[:ignore_dependencies]
24
26
  @name = name
25
- @forge = forge
26
27
  @install_dir = install_dir
28
+
29
+ Puppet::Forge::Cache.clean
30
+
31
+ @local_tarball = Puppet::FileSystem.exist?(name)
32
+
33
+ if @local_tarball
34
+ release = local_tarball_source.release
35
+ @name = release.name
36
+ options[:version] = release.version.to_s
37
+ Semantic::Dependency.add_source(local_tarball_source)
38
+
39
+ # If we're operating on a local tarball and ignoring dependencies, we
40
+ # don't need to search any additional sources. This will cut down on
41
+ # unnecessary network traffic.
42
+ unless @ignore_dependencies
43
+ Semantic::Dependency.add_source(installed_modules_source)
44
+ Semantic::Dependency.add_source(module_repository)
45
+ end
46
+
47
+ else
48
+ Semantic::Dependency.add_source(installed_modules_source) unless forced?
49
+ Semantic::Dependency.add_source(module_repository)
50
+ end
27
51
  end
28
52
 
29
53
  def run
30
- results = {}
54
+ name = @name.tr('/', '-')
55
+ version = options[:version] || '>= 0.0.0'
56
+
57
+ results = { :action => :install, :module_name => name, :module_version => version }
58
+
31
59
  begin
32
- if is_module_package?(@name)
33
- @source = :filesystem
34
- @filename = File.expand_path(@name)
35
- raise MissingPackageError, :requested_package => @filename unless Puppet::FileSystem.exist?(@filename)
36
-
37
- parsed = parse_filename(@filename)
38
- @module_name = parsed[:module_name]
39
- @version = parsed[:version]
60
+ if mod = installed_modules[name]
61
+ unless forced?
62
+ if Semantic::VersionRange.parse(version).include? mod.version
63
+ results[:result] = :noop
64
+ results[:version] = mod.version
65
+ return results
66
+ else
67
+ changes = Checksummer.run(installed_modules[name].mod.path) rescue []
68
+ raise AlreadyInstalledError,
69
+ :module_name => name,
70
+ :installed_version => installed_modules[name].version,
71
+ :requested_version => options[:version] || :latest,
72
+ :local_changes => changes
73
+ end
74
+ end
75
+ end
76
+
77
+ @install_dir.prepare(name, options[:version] || 'latest')
78
+ results[:install_dir] = @install_dir.target
79
+
80
+ unless @local_tarball && @ignore_dependencies
81
+ Puppet.notice "Downloading from #{module_repository.host} ..."
82
+ end
83
+
84
+ if @ignore_dependencies
85
+ graph = build_single_module_graph(name, version)
40
86
  else
41
- @source = :repository
42
- @module_name = @name.gsub('/', '-')
43
- @version = options[:version]
87
+ graph = build_dependency_graph(name, version)
44
88
  end
45
89
 
46
- results = {
47
- :module_name => @module_name,
48
- :module_version => @version,
49
- :install_dir => options[:target_dir],
50
- }
90
+ unless forced?
91
+ add_module_name_constraints_to_graph(graph)
92
+ end
93
+
94
+ installed_modules.each do |mod, release|
95
+ mod = mod.tr('/', '-')
96
+ next if mod == name
97
+
98
+ version = release.version
99
+
100
+ unless forced?
101
+ # Since upgrading already installed modules can be troublesome,
102
+ # we'll place constraints on the graph for each installed module,
103
+ # locking it to upgrades within the same major version.
104
+ ">=#{version} #{version.major}.x".tap do |range|
105
+ graph.add_constraint('installed', mod, range) do |node|
106
+ Semantic::VersionRange.parse(range).include? node.version
107
+ end
108
+ end
109
+
110
+ release.mod.dependencies.each do |dep|
111
+ dep_name = dep['name'].tr('/', '-')
112
+
113
+ dep['version_requirement'].tap do |range|
114
+ graph.add_constraint("#{mod} constraint", dep_name, range) do |node|
115
+ Semantic::VersionRange.parse(range).include? node.version
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ # Ensure that there is at least one candidate release available
123
+ # for the target package.
124
+ if graph.dependencies[name].empty?
125
+ raise NoCandidateReleasesError, results.merge(:module_name => name, :source => module_repository.host, :requested_version => options[:version] || :latest)
126
+ end
127
+
128
+ begin
129
+ Puppet.info "Resolving dependencies ..."
130
+ releases = Semantic::Dependency.resolve(graph)
131
+ rescue Semantic::Dependency::UnsatisfiableGraph
132
+ raise NoVersionsSatisfyError, results.merge(:requested_name => name)
133
+ end
51
134
 
52
- @install_dir.prepare(@module_name, @version || 'latest')
135
+ unless forced?
136
+ # Check for module name conflicts.
137
+ releases.each do |rel|
138
+ if mod = installed_modules_source.by_name[rel.name.split('-').last]
139
+ next if mod.has_metadata? && mod.forge_name.tr('/', '-') == rel.name
53
140
 
54
- cached_paths = get_release_packages
141
+ if rel.name != name
142
+ dependency = {
143
+ :name => rel.name,
144
+ :version => rel.version
145
+ }
146
+ end
55
147
 
56
- unless @graph.empty?
57
- Puppet.notice 'Installing -- do not interrupt ...'
58
- cached_paths.each do |hash|
59
- hash.each do |dir, path|
60
- Unpacker.new(path, @options.merge(:target_dir => dir)).run
148
+ raise InstallConflictError,
149
+ :requested_module => name,
150
+ :requested_version => options[:version] || 'latest',
151
+ :dependency => dependency,
152
+ :directory => mod.path,
153
+ :metadata => mod.metadata
61
154
  end
62
155
  end
63
156
  end
157
+
158
+ Puppet.info "Preparing to install ..."
159
+ releases.each { |release| release.prepare }
160
+
161
+ Puppet.notice 'Installing -- do not interrupt ...'
162
+ releases.each do |release|
163
+ installed = installed_modules[release.name]
164
+ if forced? || installed.nil?
165
+ release.install(Pathname.new(results[:install_dir]))
166
+ else
167
+ release.install(Pathname.new(installed.mod.modulepath))
168
+ end
169
+ end
170
+
171
+ results[:result] = :success
172
+ results[:installed_modules] = releases
173
+ results[:graph] = [ build_install_graph(releases.first, releases) ]
174
+
64
175
  rescue ModuleToolError, ForgeError => err
65
176
  results[:error] = {
66
177
  :oneline => err.message,
67
178
  :multiline => err.multiline,
68
179
  }
69
- else
70
- results[:result] = :success
71
- results[:installed_modules] = @graph
72
180
  ensure
73
181
  results[:result] ||= :failure
74
182
  end
@@ -78,6 +186,60 @@ module Puppet::ModuleTool
78
186
 
79
187
  private
80
188
 
189
+ def module_repository
190
+ @repo ||= Puppet::Forge.new
191
+ end
192
+
193
+ def local_tarball_source
194
+ @tarball_source ||= begin
195
+ Puppet::ModuleTool::LocalTarball.new(@name)
196
+ rescue Puppet::Module::Error => e
197
+ raise InvalidModuleError.new(@name, :action => @action, :error => e)
198
+ end
199
+ end
200
+
201
+ def installed_modules_source
202
+ @installed ||= Puppet::ModuleTool::InstalledModules.new(@environment)
203
+ end
204
+
205
+ def installed_modules
206
+ installed_modules_source.modules
207
+ end
208
+
209
+ def build_single_module_graph(name, version)
210
+ range = Semantic::VersionRange.parse(version)
211
+ graph = Semantic::Dependency::Graph.new(name => range)
212
+ releases = Semantic::Dependency.fetch_releases(name)
213
+ releases.each { |release| release.dependencies.clear }
214
+ graph << releases
215
+ end
216
+
217
+ def build_dependency_graph(name, version)
218
+ Semantic::Dependency.query(name => version)
219
+ end
220
+
221
+ def build_install_graph(release, installed, graphed = [])
222
+ graphed << release
223
+ dependencies = release.dependencies.values.map do |deps|
224
+ dep = (deps & installed).first
225
+ unless dep.nil? || graphed.include?(dep)
226
+ build_install_graph(dep, installed, graphed)
227
+ end
228
+ end
229
+
230
+ previous = installed_modules[release.name]
231
+ previous = previous.version if previous
232
+ return {
233
+ :release => release,
234
+ :name => release.name,
235
+ :path => release.install_dir.to_s,
236
+ :dependencies => dependencies.compact,
237
+ :version => release.version,
238
+ :previous_version => previous,
239
+ :action => (previous.nil? || previous == release.version || forced? ? :install : :upgrade),
240
+ }
241
+ end
242
+
81
243
  include Puppet::ModuleTool::Shared
82
244
 
83
245
  # Return a Pathname object representing the path to the module
@@ -85,8 +247,7 @@ module Puppet::ModuleTool
85
247
  def get_release_packages
86
248
  get_local_constraints
87
249
 
88
- if !@force && @installed.include?(@module_name)
89
-
250
+ if !forced? && @installed.include?(@module_name)
90
251
  raise AlreadyInstalledError,
91
252
  :module_name => @module_name,
92
253
  :installed_version => @installed[@module_name].first.version,
@@ -108,7 +269,7 @@ module Puppet::ModuleTool
108
269
 
109
270
  @graph = resolve_constraints({ @module_name => @version })
110
271
  @graph.first[:tarball] = @filename if @source == :filesystem
111
- resolve_install_conflicts(@graph) unless @force
272
+ resolve_install_conflicts(@graph) unless forced?
112
273
 
113
274
  # This clean call means we never "cache" the module we're installing, but this
114
275
  # is desired since module authors can easily rerelease modules different content but the same
@@ -12,6 +12,7 @@ module Puppet::ModuleTool
12
12
  def run
13
13
  results = {}
14
14
  begin
15
+ Puppet.notice "Searching #{@forge.host} ..."
15
16
  results[:answers] = @forge.search(@term)
16
17
  results[:result] = :success
17
18
  rescue ForgeError => e
@@ -22,6 +22,7 @@ module Puppet::ModuleTool
22
22
  begin
23
23
  find_installed_module
24
24
  validate_module
25
+
25
26
  FileUtils.rm_rf(@installed.first.path, :secure => true)
26
27
 
27
28
  results[:affected_modules] = @installed
@@ -87,7 +88,12 @@ module Puppet::ModuleTool
87
88
  mod = @installed.first
88
89
 
89
90
  if !@options[:force] && mod.has_metadata?
90
- changes = Puppet::ModuleTool::Applications::Checksummer.run(mod.path)
91
+ changes = begin
92
+ Puppet::ModuleTool::Applications::Checksummer.run(mod.path)
93
+ rescue ArgumentError
94
+ []
95
+ end
96
+
91
97
  if !changes.empty?
92
98
  raise LocalChangesError,
93
99
  :action => :uninstall,
@@ -1,59 +1,85 @@
1
1
  require 'pathname'
2
2
  require 'tmpdir'
3
+ require 'json'
3
4
 
4
5
  module Puppet::ModuleTool
5
6
  module Applications
6
7
  class Unpacker < Application
8
+ def self.unpack(filename, target)
9
+ app = self.new(filename, :target_dir => target)
10
+ app.unpack
11
+ app.move_into(target)
12
+ end
13
+
14
+ def self.harmonize_ownership(source, target)
15
+ unless Puppet.features.microsoft_windows?
16
+ source = Pathname.new(source) unless source.respond_to?(:stat)
17
+ target = Pathname.new(target) unless target.respond_to?(:stat)
18
+
19
+ FileUtils.chown_R(source.stat.uid, source.stat.gid, target)
20
+ end
21
+ end
7
22
 
8
23
  def initialize(filename, options = {})
9
24
  @filename = Pathname.new(filename)
10
- parsed = parse_filename(filename)
11
- @module_name = parsed[:module_name]
12
25
  super(options)
13
26
  @module_path = Pathname(options[:target_dir])
14
- @module_dir = @module_path + parsed[:dir_name]
15
27
  end
16
28
 
17
29
  def run
18
- extract_module_to_install_dir
30
+ unpack
31
+ module_dir = @module_path + module_name
32
+ move_into(module_dir)
19
33
 
20
34
  # Return the Pathname object representing the directory where the
21
- # module release archive was unpacked the to, and the module release
22
- # name.
23
- @module_dir
35
+ # module release archive was unpacked the to.
36
+ return module_dir
24
37
  end
25
38
 
26
- # Obtain a suitable temporary path for building and unpacking tarballs
27
- #
28
- # @return [Pathname] path to temporary build location
29
- def build_dir
30
- Puppet::Forge::Cache.base_path + "tmp-unpacker-#{Digest::SHA1.hexdigest(@filename.basename.to_s)}"
39
+ # @api private
40
+ def unpack
41
+ begin
42
+ Puppet::ModuleTool::Tar.instance.unpack(@filename.to_s, tmpdir, [@module_path.stat.uid, @module_path.stat.gid].join(':'))
43
+ rescue Puppet::ExecutionFailure => e
44
+ raise RuntimeError, "Could not extract contents of module archive: #{e.message}"
45
+ end
31
46
  end
32
47
 
33
- private
48
+ # @api private
49
+ def root_dir
50
+ return @root_dir if @root_dir
34
51
 
35
- def extract_module_to_install_dir
36
- delete_existing_installation_or_abort!
52
+ # Grab the first directory containing a metadata.json file
53
+ metadata_file = Dir["#{tmpdir}/**/metadata.json"].sort_by(&:length)[0]
37
54
 
38
- build_dir.mkpath
39
- begin
40
- begin
41
- Puppet::ModuleTool::Tar.instance(@module_name).unpack(@filename.to_s, build_dir.to_s, [@module_path.stat.uid, @module_path.stat.gid].join(':'))
42
- rescue Puppet::ExecutionFailure => e
43
- raise RuntimeError, "Could not extract contents of module archive: #{e.message}", e.backtrace
44
- end
45
-
46
- # grab the first directory
47
- extracted = build_dir.children.detect { |c| c.directory? }
48
- FileUtils.mv extracted, @module_dir
49
- ensure
50
- build_dir.rmtree
55
+ if metadata_file
56
+ @root_dir = Pathname.new(metadata_file).dirname
57
+ else
58
+ raise "No valid metadata.json found!"
51
59
  end
52
60
  end
53
61
 
54
- def delete_existing_installation_or_abort!
55
- return unless @module_dir.exist?
56
- FileUtils.rm_rf(@module_dir, :secure => true)
62
+ # @api private
63
+ def module_name
64
+ metadata = JSON.parse((root_dir + 'metadata.json').read)
65
+ name = metadata['name'][/-(.*)/, 1]
66
+ end
67
+
68
+ # @api private
69
+ def move_into(dir)
70
+ dir = Pathname.new(dir)
71
+ dir.rmtree if dir.exist?
72
+ FileUtils.mv(root_dir, dir)
73
+ ensure
74
+ FileUtils.rmtree(tmpdir)
75
+ end
76
+
77
+ # Obtain a suitable temporary path for unpacking tarballs
78
+ #
79
+ # @api private
80
+ # @return [String] path to temporary unpacking location
81
+ def tmpdir
82
+ @dir ||= Dir.mktmpdir('tmp-unpacker', Puppet::Forge::Cache.base_path)
57
83
  end
58
84
  end
59
85
  end
@@ -1,112 +1,268 @@
1
+ require 'pathname'
2
+
3
+ require 'puppet/forge'
4
+ require 'puppet/module_tool'
5
+ require 'puppet/module_tool/shared_behaviors'
6
+ require 'puppet/module_tool/install_directory'
7
+ require 'puppet/module_tool/installed_modules'
8
+
1
9
  module Puppet::ModuleTool
2
10
  module Applications
3
11
  class Upgrader < Application
4
12
 
5
13
  include Puppet::ModuleTool::Errors
6
14
 
7
- def initialize(name, forge, options)
15
+ def initialize(name, options)
16
+ super(options)
17
+
8
18
  @action = :upgrade
9
19
  @environment = options[:environment_instance]
10
- @module_name = name
11
- @options = options
12
- @force = options[:force]
13
- @ignore_dependencies = options[:force] || options[:ignore_dependencies]
14
- @version = options[:version]
15
- @forge = forge
20
+ @name = name
21
+ @ignore_dependencies = forced? || options[:ignore_dependencies]
22
+
23
+ Semantic::Dependency.add_source(installed_modules_source)
24
+ Semantic::Dependency.add_source(module_repository)
16
25
  end
17
26
 
18
27
  def run
28
+ name = @name.tr('/', '-')
29
+ version = options[:version] || '>= 0.0.0'
30
+
31
+ results = {
32
+ :action => :upgrade,
33
+ :requested_version => options[:version] || :latest,
34
+ }
35
+
19
36
  begin
20
- results = { :module_name => @module_name }
21
-
22
- get_local_constraints
23
-
24
- if @installed[@module_name].length > 1
25
- raise MultipleInstalledError,
26
- :action => :upgrade,
27
- :module_name => @module_name,
28
- :installed_modules => @installed[@module_name].sort_by { |mod| @environment.modulepath.index(mod.modulepath) }
29
- elsif @installed[@module_name].empty?
30
- raise NotInstalledError,
31
- :action => :upgrade,
32
- :module_name => @module_name
37
+ all_modules = @environment.modules_by_path.values.flatten
38
+ matching_modules = all_modules.select do |x|
39
+ x.forge_name && x.forge_name.tr('/', '-') == name
40
+ end
41
+
42
+ if matching_modules.empty?
43
+ raise NotInstalledError, results.merge(:module_name => name)
44
+ elsif matching_modules.length > 1
45
+ raise MultipleInstalledError, results.merge(:module_name => name, :installed_modules => matching_modules)
33
46
  end
34
47
 
35
- @module = @installed[@module_name].last
36
- results[:installed_version] = @module.version ? @module.version.sub(/^(?=\d)/, 'v') : nil
37
- results[:requested_version] = @version || (@conditions[@module_name].empty? ? :latest : :best)
38
- dir = @module.modulepath
48
+ mod = installed_modules[name]
39
49
 
40
- Puppet.notice "Found '#{@module_name}' (#{colorize(:cyan, results[:installed_version] || '???')}) in #{dir} ..."
41
- if !@options[:force] && @module.has_metadata?
42
- changes = Puppet::ModuleTool::Applications::Checksummer.run(@module.path)
43
- if !changes.empty?
50
+ # `priority` is an attribute of a `Semantic::Dependency::Source`,
51
+ # which is delegated through `ModuleRelease` instances for the sake of
52
+ # comparison (sorting). By default, the `InstalledModules` source has
53
+ # a priority of 10 (making it the most preferable source, so that
54
+ # already installed versions of modules are selected in preference to
55
+ # modules from e.g. the Forge). Since we are specifically looking to
56
+ # upgrade this module, we don't want the installed version of this
57
+ # module to be chosen in preference to those with higher versions.
58
+ #
59
+ # This implementation is suboptimal, and since we can expect this sort
60
+ # of behavior to be reasonably common in Semantic, we should probably
61
+ # see about implementing a `ModuleRelease#override_priority` method
62
+ # (or something similar).
63
+ def mod.priority
64
+ 0
65
+ end
66
+
67
+ mod = mod.mod
68
+ results[:installed_version] = Semantic::Version.parse(mod.version)
69
+ dir = Pathname.new(mod.modulepath)
70
+
71
+ vstring = mod.version ? "v#{mod.version}" : '???'
72
+ Puppet.notice "Found '#{name}' (#{colorize(:cyan, vstring)}) in #{dir} ..."
73
+ unless forced?
74
+ changes = Checksummer.run(mod.path) rescue []
75
+ if mod.has_metadata? && !changes.empty?
44
76
  raise LocalChangesError,
45
77
  :action => :upgrade,
46
- :module_name => @module_name,
47
- :requested_version => @version || (@conditions[@module_name].empty? ? :latest : :best),
48
- :installed_version => @module.version
78
+ :module_name => name,
79
+ :requested_version => results[:requested_version],
80
+ :installed_version => mod.version
49
81
  end
50
82
  end
51
83
 
52
- begin
53
- get_remote_constraints(@forge)
54
- rescue => e
55
- raise UnknownModuleError, results.merge(:repository => @forge.uri), e.backtrace
84
+ Puppet::Forge::Cache.clean
85
+
86
+ Puppet.notice "Downloading from #{module_repository.host} ..."
87
+ if @ignore_dependencies
88
+ graph = build_single_module_graph(name, version)
56
89
  else
57
- raise UnknownVersionError, results.merge(:repository => @forge.uri) if @remote.empty?
90
+ graph = build_dependency_graph(name, version)
58
91
  end
59
92
 
60
- if !@options[:force] && @versions["#{@module_name}"].last[:vstring].sub(/^(?=\d)/, 'v') == (@module.version || '0.0.0').sub(/^(?=\d)/, 'v')
61
- raise VersionAlreadyInstalledError,
62
- :module_name => @module_name,
63
- :requested_version => @version || ((@conditions[@module_name].empty? ? 'latest' : 'best') + ": #{@versions["#{@module_name}"].last[:vstring].sub(/^(?=\d)/, 'v')}"),
64
- :installed_version => @installed[@module_name].last.version,
65
- :conditions => @conditions[@module_name] + [{ :module => :you, :version => @version }]
93
+ unless forced?
94
+ add_module_name_constraints_to_graph(graph)
66
95
  end
67
96
 
68
- @graph = resolve_constraints({ @module_name => @version })
97
+ installed_modules.each do |mod, release|
98
+ mod = mod.tr('/', '-')
99
+ next if mod == name
69
100
 
70
- # This clean call means we never "cache" the module we're installing, but this
71
- # is desired since module authors can easily rerelease modules different content but the same
72
- # version number, meaning someone with the old content cached will be very confused as to why
73
- # they can't get new content.
74
- # Long term we should just get rid of this caching behavior and cleanup downloaded modules after they install
75
- # but for now this is a quick fix to disable caching
76
- Puppet::Forge::Cache.clean
77
- tarballs = download_tarballs(@graph, @graph.last[:path], @forge)
101
+ version = release.version
102
+
103
+ unless forced?
104
+ # Since upgrading already installed modules can be troublesome,
105
+ # we'll place constraints on the graph for each installed
106
+ # module, locking it to upgrades within the same major version.
107
+ ">=#{version} #{version.major}.x".tap do |range|
108
+ graph.add_constraint('installed', mod, range) do |node|
109
+ Semantic::VersionRange.parse(range).include? node.version
110
+ end
111
+ end
112
+
113
+ release.mod.dependencies.each do |dep|
114
+ dep_name = dep['name'].tr('/', '-')
115
+
116
+ dep['version_requirement'].tap do |range|
117
+ graph.add_constraint("#{mod} constraint", dep_name, range) do |node|
118
+ Semantic::VersionRange.parse(range).include? node.version
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ # Ensure that there is at least one candidate release available
126
+ # for the target package.
127
+ if graph.dependencies[name].empty? || graph.dependencies[name] == SortedSet.new([ installed_modules[name] ])
128
+ if results[:requested_version] == :latest || !Semantic::VersionRange.parse(results[:requested_version]).include?(results[:installed_version])
129
+ raise NoCandidateReleasesError, results.merge(:module_name => name, :source => module_repository.host)
130
+ end
131
+ end
132
+
133
+ begin
134
+ Puppet.info "Resolving dependencies ..."
135
+ releases = Semantic::Dependency.resolve(graph)
136
+ rescue Semantic::Dependency::UnsatisfiableGraph
137
+ raise NoVersionsSatisfyError, results.merge(:requested_name => name)
138
+ end
78
139
 
79
- unless @graph.empty?
80
- Puppet.notice 'Upgrading -- do not interrupt ...'
81
- tarballs.each do |hash|
82
- hash.each do |dir, path|
83
- Unpacker.new(path, @options.merge(:target_dir => dir)).run
140
+ releases.each do |rel|
141
+ if mod = installed_modules_source.by_name[rel.name.split('-').last]
142
+ next if mod.has_metadata? && mod.forge_name.tr('/', '-') == rel.name
143
+
144
+ if rel.name != name
145
+ dependency = {
146
+ :name => rel.name,
147
+ :version => rel.version
148
+ }
84
149
  end
150
+
151
+ raise InstallConflictError,
152
+ :requested_module => name,
153
+ :requested_version => options[:version] || 'latest',
154
+ :dependency => dependency,
155
+ :directory => mod.path,
156
+ :metadata => mod.metadata
157
+ end
158
+ end
159
+
160
+ child = releases.find { |x| x.name == name }
161
+
162
+ unless forced?
163
+ if child.version <= results[:installed_version]
164
+ versions = graph.dependencies[name].map { |r| r.version }
165
+ newer_versions = versions.select { |v| v > results[:installed_version] }
166
+
167
+ raise VersionAlreadyInstalledError,
168
+ :module_name => name,
169
+ :requested_version => results[:requested_version],
170
+ :installed_version => results[:installed_version],
171
+ :newer_versions => newer_versions,
172
+ :possible_culprits => installed_modules_source.fetched.reject { |x| x == name }
173
+ end
174
+ end
175
+
176
+ Puppet.info "Preparing to upgrade ..."
177
+ releases.each { |release| release.prepare }
178
+
179
+ Puppet.notice 'Upgrading -- do not interrupt ...'
180
+ releases.each do |release|
181
+ if installed = installed_modules[release.name]
182
+ release.install(Pathname.new(installed.mod.modulepath))
183
+ else
184
+ release.install(dir)
85
185
  end
86
186
  end
87
187
 
88
188
  results[:result] = :success
89
- results[:base_dir] = @graph.first[:path]
90
- results[:affected_modules] = @graph
189
+ results[:base_dir] = releases.first.install_dir
190
+ results[:affected_modules] = releases
191
+ results[:graph] = [ build_install_graph(releases.first, releases) ]
192
+
91
193
  rescue VersionAlreadyInstalledError => e
92
- results[:result] = :noop
93
- results[:error] = {
94
- :oneline => e.message,
95
- :multiline => e.multiline
96
- }
194
+ results[:result] = (e.newer_versions.empty? ? :noop : :failure)
195
+ results[:error] = { :oneline => e.message, :multiline => e.multiline }
97
196
  rescue => e
98
197
  results[:error] = {
99
- :oneline => e.message,
198
+ :oneline => e.message,
100
199
  :multiline => e.respond_to?(:multiline) ? e.multiline : [e.to_s, e.backtrace].join("\n")
101
200
  }
102
201
  ensure
103
202
  results[:result] ||= :failure
104
203
  end
105
204
 
106
- return results
205
+ results
107
206
  end
108
207
 
109
208
  private
209
+ def module_repository
210
+ @repo ||= Puppet::Forge.new
211
+ end
212
+
213
+ def installed_modules_source
214
+ @installed ||= Puppet::ModuleTool::InstalledModules.new(@environment)
215
+ end
216
+
217
+ def installed_modules
218
+ installed_modules_source.modules
219
+ end
220
+
221
+ def build_single_module_graph(name, version)
222
+ range = Semantic::VersionRange.parse(version)
223
+ graph = Semantic::Dependency::Graph.new(name => range)
224
+ releases = Semantic::Dependency.fetch_releases(name)
225
+ releases.each { |release| release.dependencies.clear }
226
+ graph << releases
227
+ end
228
+
229
+ def build_dependency_graph(name, version)
230
+ Semantic::Dependency.query(name => version)
231
+ end
232
+
233
+ def build_install_graph(release, installed, graphed = [])
234
+ previous = installed_modules[release.name]
235
+ previous = previous.version if previous
236
+
237
+ action = :upgrade
238
+ unless previous && previous != release.version
239
+ action = :install
240
+ end
241
+
242
+ graphed << release
243
+
244
+ dependencies = release.dependencies.values.map do |deps|
245
+ dep = (deps & installed).first
246
+ if dep == installed_modules[dep.name]
247
+ next
248
+ end
249
+
250
+ if dep && !graphed.include?(dep)
251
+ build_install_graph(dep, installed, graphed)
252
+ end
253
+ end.compact
254
+
255
+ return {
256
+ :release => release,
257
+ :name => release.name,
258
+ :path => release.install_dir,
259
+ :dependencies => dependencies.compact,
260
+ :version => release.version,
261
+ :previous_version => previous,
262
+ :action => action,
263
+ }
264
+ end
265
+
110
266
  include Puppet::ModuleTool::Shared
111
267
  end
112
268
  end