puppet 2.7.11 → 2.7.12

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 (220) hide show
  1. data/CHANGELOG +188 -0
  2. data/conf/osx/createpackage.sh +1 -0
  3. data/conf/redhat/puppet.spec +12 -9
  4. data/conf/suse/puppet.spec +4 -1
  5. data/install.rb +9 -22
  6. data/lib/puppet.rb +1 -31
  7. data/lib/puppet/agent.rb +3 -5
  8. data/lib/puppet/agent/locker.rb +15 -1
  9. data/lib/puppet/application.rb +7 -4
  10. data/lib/puppet/application/agent.rb +4 -25
  11. data/lib/puppet/application/apply.rb +3 -3
  12. data/lib/puppet/application/device.rb +2 -16
  13. data/lib/puppet/application/doc.rb +2 -2
  14. data/lib/puppet/application/face_base.rb +22 -5
  15. data/lib/puppet/application/filebucket.rb +2 -0
  16. data/lib/puppet/application/inspect.rb +2 -1
  17. data/lib/puppet/application/kick.rb +25 -9
  18. data/lib/puppet/application/queue.rb +0 -23
  19. data/lib/puppet/configurer.rb +1 -0
  20. data/lib/puppet/configurer/downloader.rb +7 -3
  21. data/lib/puppet/defaults.rb +34 -29
  22. data/lib/puppet/face/ca.rb +1 -1
  23. data/lib/puppet/face/catalog.rb +1 -0
  24. data/lib/puppet/face/file/store.rb +1 -1
  25. data/lib/puppet/face/module/list.rb +23 -3
  26. data/lib/puppet/face/module/search.rb +21 -32
  27. data/lib/puppet/face/module/uninstall.rb +56 -15
  28. data/lib/puppet/file_bucket/dipper.rb +2 -2
  29. data/lib/puppet/file_serving/base.rb +6 -5
  30. data/lib/puppet/file_serving/configuration/parser.rb +1 -1
  31. data/lib/puppet/file_serving/content.rb +1 -1
  32. data/lib/puppet/forge.rb +153 -0
  33. data/lib/puppet/{module_tool → forge}/cache.rb +1 -2
  34. data/lib/puppet/{module_tool → forge}/repository.rb +46 -4
  35. data/lib/puppet/indirector/exec.rb +1 -1
  36. data/lib/puppet/indirector/file_bucket_file/file.rb +3 -3
  37. data/lib/puppet/interface/action.rb +6 -2
  38. data/lib/puppet/module.rb +70 -10
  39. data/lib/puppet/module_tool.rb +2 -38
  40. data/lib/puppet/module_tool/applications.rb +15 -11
  41. data/lib/puppet/module_tool/applications/application.rb +2 -5
  42. data/lib/puppet/module_tool/applications/cleaner.rb +1 -1
  43. data/lib/puppet/module_tool/applications/installer.rb +10 -45
  44. data/lib/puppet/module_tool/applications/searcher.rb +2 -26
  45. data/lib/puppet/module_tool/applications/uninstaller.rb +39 -13
  46. data/lib/puppet/module_tool/applications/unpacker.rb +1 -1
  47. data/lib/puppet/module_tool/dependency.rb +1 -1
  48. data/lib/puppet/network/authconfig.rb +1 -1
  49. data/lib/puppet/network/handler/fileserver.rb +1 -1
  50. data/lib/puppet/network/http/handler.rb +4 -1
  51. data/lib/puppet/network/http/webrick.rb +4 -2
  52. data/lib/puppet/node/environment.rb +32 -6
  53. data/lib/puppet/parameter/path.rb +0 -4
  54. data/lib/puppet/parser/ast/relationship.rb +3 -16
  55. data/lib/puppet/parser/collector.rb +5 -3
  56. data/lib/puppet/parser/compiler.rb +2 -1
  57. data/lib/puppet/parser/functions/file.rb +1 -1
  58. data/lib/puppet/parser/functions/generate.rb +8 -2
  59. data/lib/puppet/parser/grammar.ra +16 -15
  60. data/lib/puppet/parser/parser.rb +959 -881
  61. data/lib/puppet/parser/relationship.rb +32 -15
  62. data/lib/puppet/parser/resource.rb +0 -1
  63. data/lib/puppet/parser/type_loader.rb +1 -2
  64. data/lib/puppet/provider/augeas/augeas.rb +17 -29
  65. data/lib/puppet/provider/exec/windows.rb +25 -3
  66. data/lib/puppet/provider/file/posix.rb +1 -1
  67. data/lib/puppet/provider/file/windows.rb +1 -1
  68. data/lib/puppet/provider/group/windows_adsi.rb +1 -1
  69. data/lib/puppet/provider/package/aix.rb +1 -1
  70. data/lib/puppet/provider/package/appdmg.rb +1 -1
  71. data/lib/puppet/provider/package/dpkg.rb +1 -1
  72. data/lib/puppet/provider/package/gem.rb +21 -23
  73. data/lib/puppet/provider/package/macports.rb +1 -1
  74. data/lib/puppet/provider/package/msi.rb +7 -1
  75. data/lib/puppet/provider/package/openbsd.rb +13 -16
  76. data/lib/puppet/provider/package/pacman.rb +1 -1
  77. data/lib/puppet/provider/package/pip.rb +3 -0
  78. data/lib/puppet/provider/package/pkg.rb +1 -1
  79. data/lib/puppet/provider/package/pkgdmg.rb +1 -1
  80. data/lib/puppet/provider/package/pkgutil.rb +1 -1
  81. data/lib/puppet/provider/package/portage.rb +2 -2
  82. data/lib/puppet/provider/package/rpm.rb +1 -1
  83. data/lib/puppet/provider/package/sun.rb +1 -1
  84. data/lib/puppet/provider/package/zypper.rb +35 -3
  85. data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +6 -2
  86. data/lib/puppet/provider/selmodule/semodule.rb +2 -2
  87. data/lib/puppet/provider/service/base.rb +1 -1
  88. data/lib/puppet/provider/service/launchd.rb +4 -0
  89. data/lib/puppet/provider/service/src.rb +2 -2
  90. data/lib/puppet/provider/service/upstart.rb +1 -1
  91. data/lib/puppet/provider/service/windows.rb +5 -4
  92. data/lib/puppet/provider/user/aix.rb +3 -3
  93. data/lib/puppet/provider/user/pw.rb +6 -0
  94. data/lib/puppet/provider/user/windows_adsi.rb +1 -1
  95. data/lib/puppet/resource/catalog.rb +6 -6
  96. data/lib/puppet/resource/type.rb +2 -0
  97. data/lib/puppet/ssl/certificate_request.rb +0 -70
  98. data/lib/puppet/transaction.rb +1 -1
  99. data/lib/puppet/transaction/report.rb +3 -2
  100. data/lib/puppet/type.rb +1 -1
  101. data/lib/puppet/type/cron.rb +5 -2
  102. data/lib/puppet/type/exec.rb +8 -0
  103. data/lib/puppet/type/file.rb +27 -18
  104. data/lib/puppet/type/file/checksum.rb +2 -2
  105. data/lib/puppet/type/file/content.rb +14 -9
  106. data/lib/puppet/type/file/ensure.rb +5 -4
  107. data/lib/puppet/type/file/group.rb +10 -2
  108. data/lib/puppet/type/file/mode.rb +46 -18
  109. data/lib/puppet/type/file/owner.rb +10 -2
  110. data/lib/puppet/type/file/source.rb +27 -40
  111. data/lib/puppet/type/file/target.rb +6 -6
  112. data/lib/puppet/type/group.rb +13 -9
  113. data/lib/puppet/type/k5login.rb +1 -1
  114. data/lib/puppet/type/package.rb +24 -8
  115. data/lib/puppet/type/scheduled_task.rb +77 -131
  116. data/lib/puppet/type/service.rb +22 -8
  117. data/lib/puppet/type/user.rb +29 -9
  118. data/lib/puppet/util.rb +24 -33
  119. data/lib/puppet/util/colors.rb +98 -0
  120. data/lib/puppet/util/diff.rb +3 -1
  121. data/lib/puppet/util/log.rb +5 -1
  122. data/lib/puppet/util/log/destinations.rb +37 -44
  123. data/lib/puppet/util/monkey_patches.rb +32 -0
  124. data/lib/puppet/util/pidlock.rb +70 -21
  125. data/lib/puppet/util/rdoc/parser.rb +4 -2
  126. data/lib/puppet/util/selinux.rb +1 -1
  127. data/lib/puppet/util/suidmanager.rb +2 -12
  128. data/lib/puppet/util/windows.rb +2 -0
  129. data/lib/puppet/util/windows/process.rb +33 -0
  130. data/lib/puppet/util/windows/security.rb +6 -4
  131. data/lib/puppet/util/windows/user.rb +44 -0
  132. data/lib/semver.rb +55 -4
  133. data/spec/fixtures/unit/provider/package/openbsd/pkginfo.detail +19 -0
  134. data/spec/fixtures/unit/provider/package/openbsd/pkginfo.list +10 -0
  135. data/spec/fixtures/unit/provider/package/openbsd/pkginfo.query +1 -0
  136. data/spec/fixtures/unit/provider/package/zypper/zypper-list-updates-SLES11sp1.out +369 -0
  137. data/spec/integration/defaults_spec.rb +10 -0
  138. data/spec/integration/indirector/direct_file_server_spec.rb +1 -1
  139. data/spec/integration/module_tool_spec.rb +10 -12
  140. data/spec/integration/parser/compiler_spec.rb +147 -0
  141. data/spec/integration/type/file_spec.rb +1 -1
  142. data/spec/integration/util/windows/user_spec.rb +59 -0
  143. data/spec/lib/puppet/face/basetest.rb +5 -0
  144. data/spec/lib/puppet_spec/modules.rb +26 -0
  145. data/spec/spec_helper.rb +25 -0
  146. data/spec/unit/agent/locker_spec.rb +12 -0
  147. data/spec/unit/agent_backward_compatibility_spec.rb +152 -0
  148. data/spec/unit/agent_spec.rb +28 -8
  149. data/spec/unit/application/agent_spec.rb +4 -36
  150. data/spec/unit/application/device_spec.rb +55 -10
  151. data/spec/unit/application/face_base_spec.rb +32 -10
  152. data/spec/unit/application/filebucket_spec.rb +5 -0
  153. data/spec/unit/application/kick_spec.rb +6 -0
  154. data/spec/unit/application_spec.rb +8 -1
  155. data/spec/unit/configurer/downloader_spec.rb +4 -5
  156. data/spec/unit/face/ca_spec.rb +15 -4
  157. data/spec/unit/file_bucket/dipper_spec.rb +1 -1
  158. data/spec/unit/file_serving/base_spec.rb +60 -42
  159. data/spec/unit/file_serving/configuration/parser_spec.rb +5 -3
  160. data/spec/unit/file_serving/content_spec.rb +26 -27
  161. data/spec/unit/file_serving/metadata_spec.rb +22 -21
  162. data/spec/unit/forge/repository_spec.rb +86 -0
  163. data/spec/unit/forge_spec.rb +114 -0
  164. data/spec/unit/indirector/exec_spec.rb +8 -6
  165. data/spec/unit/indirector/facts/inventory_active_record_spec.rb +0 -1
  166. data/spec/unit/indirector/file_bucket_file/file_spec.rb +1 -1
  167. data/spec/unit/indirector/node/exec_spec.rb +1 -1
  168. data/spec/unit/indirector/resource/active_record_spec.rb +0 -4
  169. data/spec/unit/interface/action_builder_spec.rb +7 -5
  170. data/spec/unit/module_spec.rb +228 -9
  171. data/spec/unit/module_tool/application_spec.rb +3 -3
  172. data/spec/unit/module_tool/uninstaller_spec.rb +107 -27
  173. data/spec/unit/module_tool_spec.rb +0 -33
  174. data/spec/unit/network/authconfig_spec.rb +22 -21
  175. data/spec/unit/network/http/webrick_spec.rb +13 -9
  176. data/spec/unit/node/environment_spec.rb +159 -66
  177. data/spec/unit/parser/collector_spec.rb +16 -8
  178. data/spec/unit/parser/functions/generate_spec.rb +60 -18
  179. data/spec/unit/parser/resource_spec.rb +44 -0
  180. data/spec/unit/provider/augeas/augeas_spec.rb +160 -179
  181. data/spec/unit/provider/confine/feature_spec.rb +3 -5
  182. data/spec/unit/provider/package/dpkg_spec.rb +4 -2
  183. data/spec/unit/provider/package/gem_spec.rb +59 -43
  184. data/spec/unit/provider/package/openbsd_spec.rb +114 -0
  185. data/spec/unit/provider/package/pacman_spec.rb +1 -1
  186. data/spec/unit/provider/package/pip_spec.rb +10 -4
  187. data/spec/unit/provider/package/zypper_spec.rb +56 -14
  188. data/spec/unit/provider/selmodule_spec.rb +3 -3
  189. data/spec/unit/provider/service/launchd_spec.rb +22 -21
  190. data/spec/unit/provider/service/{upstart.rb → upstart_spec.rb} +7 -3
  191. data/spec/unit/provider/user/pw_spec.rb +19 -0
  192. data/spec/unit/resource/catalog_spec.rb +3 -3
  193. data/spec/unit/semver_spec.rb +117 -24
  194. data/spec/unit/transaction/report_spec.rb +11 -1
  195. data/spec/unit/type/cron_spec.rb +200 -213
  196. data/spec/unit/type/exec_spec.rb +7 -0
  197. data/spec/unit/type/file/content_spec.rb +2 -2
  198. data/spec/unit/type/file_spec.rb +12 -9
  199. data/spec/unit/type/package_spec.rb +25 -0
  200. data/spec/unit/type/schedule_spec.rb +31 -31
  201. data/spec/unit/util/diff_spec.rb +30 -0
  202. data/spec/unit/util/execution_stub_spec.rb +1 -2
  203. data/spec/unit/util/log/destinations_spec.rb +51 -0
  204. data/spec/unit/util/log_spec.rb +17 -1
  205. data/spec/unit/util/monkey_patches_spec.rb +119 -0
  206. data/spec/unit/util/rdoc/parser_spec.rb +25 -1
  207. data/spec/unit/util/selinux_spec.rb +2 -2
  208. data/spec/unit/util/suidmanager_spec.rb +6 -51
  209. data/spec/unit/util_spec.rb +82 -24
  210. data/test/lib/puppettest/certificates.rb +16 -0
  211. data/test/lib/puppettest/servertest.rb +4 -0
  212. data/test/util/pidlock.rb +125 -0
  213. metadata +23 -14
  214. data/ext/puppetstoredconfigclean.rb +0 -103
  215. data/lib/puppet/agent/disabler.rb +0 -27
  216. data/lib/puppet/util/anonymous_filelock.rb +0 -36
  217. data/spec/unit/agent/disabler_spec.rb +0 -60
  218. data/spec/unit/module_tool/repository_spec.rb +0 -52
  219. data/spec/unit/util/anonymous_filelock_spec.rb +0 -78
  220. data/spec/unit/util/pidlock_spec.rb +0 -208
@@ -75,7 +75,7 @@ Puppet::Face.define(:ca, '0.1.0') do
75
75
  raise "Unable to fetch the CA"
76
76
  end
77
77
 
78
- length = hosts.map{|x| x.name.length }.max + 1
78
+ length = hosts.map{|x| x.name.length }.max.to_i + 1
79
79
 
80
80
  hosts.map do |host|
81
81
  name = host.name.ljust(length)
@@ -66,6 +66,7 @@ Puppet::Indirector::Face.define(:catalog, '0.0.1') do
66
66
 
67
67
  report = Puppet::Transaction::Report.new("apply")
68
68
  report.configuration_version = catalog.version
69
+ report.environment = Puppet[:environment]
69
70
 
70
71
  Puppet::Util::Log.newdestination(report)
71
72
 
@@ -11,7 +11,7 @@ Puppet::Face.define(:file, '0.0.1') do
11
11
  EOT
12
12
 
13
13
  when_invoked do |path, options|
14
- file = Puppet::FileBucket::File.new(Puppet::Util.binread(path))
14
+ file = Puppet::FileBucket::File.new(IO.binread(path))
15
15
 
16
16
  Puppet::FileBucket::File.indirection.terminus_class = :file
17
17
  Puppet::FileBucket::File.indirection.save file
@@ -3,7 +3,9 @@ Puppet::Face.define(:module, '1.0.0') do
3
3
  summary "List installed modules"
4
4
  description <<-HEREDOC
5
5
  List puppet modules from a specific environment, specified modulepath or
6
- default to listing modules in the default modulepath:
6
+ default to listing modules in the default modulepath. The output will
7
+ include information about unmet module dependencies based on information
8
+ from module metadata.
7
9
  #{Puppet.settings[:modulepath]}
8
10
  HEREDOC
9
11
  returns "hash of paths to module objects"
@@ -29,6 +31,9 @@ Puppet::Face.define(:module, '1.0.0') do
29
31
  List installed modules from a specified environment:
30
32
 
31
33
  $ puppet module list --env 'test'
34
+ Missing dependency `stdlib`:
35
+ `rrd` (0.0.2) requires `puppetlabs/stdlib` (>= 2.2.0)
36
+
32
37
  /tmp/puppet/modules
33
38
  rrd (0.0.2)
34
39
 
@@ -48,11 +53,26 @@ Puppet::Face.define(:module, '1.0.0') do
48
53
  environment.modules_by_path
49
54
  end
50
55
 
51
- when_rendering :console do |modules_by_path|
56
+ when_rendering :console do |modules_by_path, options|
52
57
  output = ''
58
+
59
+ Puppet[:modulepath] = options[:modulepath] if options[:modulepath]
60
+ environment = Puppet::Node::Environment.new(options[:env])
61
+
62
+ dependency_errors = false
63
+
64
+ environment.modules.sort_by {|mod| mod.name}.each do |mod|
65
+ mod.unmet_dependencies.sort_by {|dep| dep[:name]}.each do |dep|
66
+ dependency_errors = true
67
+ $stderr.puts dep[:error]
68
+ end
69
+ end
70
+
71
+ output << "\n" if dependency_errors
72
+
53
73
  modules_by_path.each do |path, modules|
54
74
  output << "#{path}\n"
55
- modules.each do |mod|
75
+ modules.sort_by {|mod| mod.name }.each do |mod|
56
76
  version_string = mod.version ? "(#{mod.version})" : ''
57
77
  output << " #{mod.name} #{version_string}\n"
58
78
  end
@@ -11,32 +11,8 @@ Puppet::Face.define(:module, '1.0.0') do
11
11
  Search the default repository for a module:
12
12
 
13
13
  $ puppet module search puppetlabs
14
- notice: Searching http://forge.puppetlabs.com
15
- notice: 24 found.
16
- puppetlabs/apache (0.0.3)
17
- puppetlabs/collectd (0.0.1)
18
- puppetlabs/ruby (0.0.1)
19
- puppetlabs/vcsrepo (0.0.4)
20
- puppetlabs/gcc (0.0.3)
21
- puppetlabs/passenger (0.0.2)
22
- puppetlabs/DeveloperBootstrap (0.0.5)
23
- jeffmccune/tomcat (1.0.1)
24
- puppetlabs/motd (1.0.0)
25
- puppetlabs/lvm (0.1.0)
26
- puppetlabs/rabbitmq (1.0.4)
27
- puppetlabs/prosvc_repo (1.0.1)
28
- puppetlabs/stdlib (2.2.0)
29
- puppetlabs/java (0.1.5)
30
- puppetlabs/activemq (0.1.6)
31
- puppetlabs/mcollective (0.1.8)
32
- puppetlabs/git (0.0.2)
33
- puppetlabs/ntp (0.0.4)
34
- puppetlabs/nginx (0.0.1)
35
- puppetlabs/cloud_provisioner (0.6.0rc1)
36
- puppetlabs/mrepo (0.1.1)
37
- puppetlabs/f5 (0.1.0)
38
- puppetlabs/firewall (0.0.3)
39
- puppetlabs/bprobe (0.0.3)
14
+ NAME DESCRIPTION AUTHOR KEYWORDS
15
+ bacula This is a generic Apache module @puppetlabs backups
40
16
  EOT
41
17
 
42
18
  arguments "<term>"
@@ -50,17 +26,30 @@ Puppet::Face.define(:module, '1.0.0') do
50
26
  end
51
27
 
52
28
  when_invoked do |term, options|
53
- Puppet.notice "Searching #{options[:module_repository]}"
54
29
  Puppet::Module::Tool::Applications::Searcher.run(term, options)
55
30
  end
56
31
 
57
32
  when_rendering :console do |return_value|
58
- Puppet.notice "#{return_value.size} found."
33
+
34
+ FORMAT = "%-10s %-32s %-14s %s\n"
35
+
36
+ def header
37
+ FORMAT % ['NAME', 'DESCRIPTION', 'AUTHOR', 'KEYWORDS']
38
+ end
39
+
40
+ def format_row(name, description, author, tag_list)
41
+ keywords = tag_list.join(' ')
42
+ FORMAT % [name[0..10], description[0..32], "@#{author[0..14]}", keywords]
43
+ end
44
+
45
+ output = ''
46
+ output << header unless return_value.empty?
47
+
59
48
  return_value.map do |match|
60
- # We reference the full_name here when referring to the full_module_name,
61
- # because full_name is what is returned from the forge API call.
62
- "#{match['full_name']} (#{match['version']})"
63
- end.join("\n")
49
+ output << format_row(match['name'], match['desc'], match['author'], match['tag_list'])
50
+ end
51
+
52
+ output
64
53
  end
65
54
  end
66
55
  end
@@ -7,44 +7,85 @@ Puppet::Face.define(:module, '1.0.0') do
7
7
  #{Puppet.settings[:modulepath].split(File::PATH_SEPARATOR).join(', ')}.
8
8
  EOT
9
9
 
10
- returns "Array of strings representing paths of uninstalled files."
10
+ returns "Hash of module objects representing uninstalled modules and related errors."
11
11
 
12
12
  examples <<-EOT
13
13
  Uninstall a module from all directories in the modulepath:
14
14
 
15
15
  $ puppet module uninstall ssh
16
- Removed /etc/puppet/modules/ssh
16
+ Removed /etc/puppet/modules/ssh (v1.0.0)
17
17
 
18
18
  Uninstall a module from a specific directory:
19
19
 
20
- $ puppet module uninstall --target-directory /usr/share/puppet/modules ssh
21
- Removed /usr/share/puppet/modules/ssh
20
+ $ puppet module uninstall --modulepath /usr/share/puppet/modules ssh
21
+ Removed /usr/share/puppet/modules/ssh (v1.0.0)
22
+
23
+ Uninstall a module from a specific environment:
24
+
25
+ $ puppet module uninstall --environment development
26
+ Removed /etc/puppet/environments/development/modules/ssh (v1.0.0)
27
+
28
+ Uninstall a specific version of a module:
29
+
30
+ $ puppet module uninstall --version 2.0.0 ssh
31
+ Removed /etc/puppet/modules/ssh (v2.0.0)
22
32
  EOT
23
33
 
24
34
  arguments "<name>"
25
35
 
26
- option "--target-directory=", "-t=" do
27
- default_to { Puppet.settings[:modulepath].split(File::PATH_SEPARATOR) }
28
- summary "The target directory to search from modules."
36
+ option "--environment=NAME", "--env=NAME" do
37
+ default_to { "production" }
38
+ summary "The target environment to search for modules."
39
+ description <<-EOT
40
+ The target environment to search for modules.
41
+ EOT
42
+ end
43
+
44
+ option "--version=" do
45
+ summary "The version of the module to uninstall"
46
+ description <<-EOT
47
+ The version of the module to uninstall. When using this option a module
48
+ that matches the specified version must be installed or an error is raised.
49
+ EOT
50
+ end
51
+
52
+ option "--modulepath=" do
53
+ summary "The target directory to search for modules."
29
54
  description <<-EOT
30
55
  The target directory to search for modules.
31
56
  EOT
32
57
  end
33
58
 
34
59
  when_invoked do |name, options|
35
-
36
- if options[:target_directory].is_a?(Array)
37
- options[:target_directories] = options[:target_directory]
38
- else
39
- options[:target_directories] = [ options[:target_directory] ]
60
+ if options[:modulepath]
61
+ unless File.directory?(options[:modulepath])
62
+ raise ArgumentError, "Directory #{options[:modulepath]} does not exist"
63
+ end
40
64
  end
41
- options.delete(:target_directory)
65
+
66
+ Puppet[:modulepath] = options[:modulepath] if options[:modulepath]
67
+ options[:name] = name
42
68
 
43
69
  Puppet::Module::Tool::Applications::Uninstaller.run(name, options)
44
70
  end
45
71
 
46
- when_rendering :console do |removed_modules|
47
- removed_modules.map { |path| "Removed #{path}" }.join('\n')
72
+ when_rendering :console do |return_value|
73
+ output = ''
74
+
75
+ return_value[:removed_mods].each do |mod|
76
+ output << "Removed #{mod.path} (v#{mod.version})\n"
77
+ end
78
+
79
+ return_value[:errors].map do |mod_name, errors|
80
+ if ! errors.empty?
81
+ header = "Could not uninstall module #{return_value[:options][:name]}"
82
+ header << " (v#{return_value[:options][:version]})" if return_value[:options][:version]
83
+ output << "#{header}:\n"
84
+ errors.map { |error| output << " #{error}\n" }
85
+ end
86
+ end
87
+
88
+ output
48
89
  end
49
90
  end
50
91
  end
@@ -31,7 +31,7 @@ class Puppet::FileBucket::Dipper
31
31
  # Back up a file to our bucket
32
32
  def backup(file)
33
33
  raise(ArgumentError, "File #{file} does not exist") unless ::File.exist?(file)
34
- contents = Puppet::Util.binread(file)
34
+ contents = IO.binread(file)
35
35
  begin
36
36
  file_bucket_file = Puppet::FileBucket::File.new(contents, :bucket_path => @local_path)
37
37
  files_original_path = absolutize_path(file)
@@ -64,7 +64,7 @@ class Puppet::FileBucket::Dipper
64
64
  def restore(file,sum)
65
65
  restore = true
66
66
  if FileTest.exists?(file)
67
- cursum = Digest::MD5.hexdigest(Puppet::Util.binread(file))
67
+ cursum = Digest::MD5.hexdigest(IO.binread(file))
68
68
 
69
69
  # if the checksum has changed...
70
70
  # this might be extra effort
@@ -1,4 +1,5 @@
1
1
  require 'puppet/file_serving'
2
+ require 'puppet/util'
2
3
 
3
4
  # The base class for Content and Metadata; provides common
4
5
  # functionality like the behaviour around links.
@@ -49,10 +50,7 @@ class Puppet::FileServing::Base
49
50
  # Set our base path.
50
51
  attr_reader :path
51
52
  def path=(path)
52
- unless path =~ /^#{::File::SEPARATOR}/ or path =~ /^[a-z]:[\/\\]/i
53
- raise ArgumentError.new("Paths must be fully qualified")
54
- end
55
-
53
+ raise ArgumentError.new("Paths must be fully qualified") unless Puppet::FileServing::Base.absolute?(path)
56
54
  @path = path
57
55
  end
58
56
 
@@ -60,7 +58,7 @@ class Puppet::FileServing::Base
60
58
  # the file's path relative to the initial recursion point.
61
59
  attr_reader :relative_path
62
60
  def relative_path=(path)
63
- raise ArgumentError.new("Relative paths must not be fully qualified") if path =~ /^#{::File::SEPARATOR}/
61
+ raise ArgumentError.new("Relative paths must not be fully qualified") if Puppet::FileServing::Base.absolute?(path)
64
62
  @relative_path = path
65
63
  end
66
64
 
@@ -84,4 +82,7 @@ class Puppet::FileServing::Base
84
82
  }
85
83
  end
86
84
 
85
+ def self.absolute?(path)
86
+ Puppet::Util.absolute_path?(path, :posix) or (Puppet.features.microsoft_windows? and Puppet::Util.absolute_path?(path, :windows))
87
+ end
87
88
  end
@@ -15,7 +15,7 @@ class Puppet::FileServing::Configuration::Parser < Puppet::Util::LoadedFile
15
15
 
16
16
  File.open(self.file) { |f|
17
17
  mount = nil
18
- f.each { |line|
18
+ f.each_line { |line|
19
19
  # Have the count increment at the top, in case we throw exceptions.
20
20
  @count += 1
21
21
 
@@ -35,7 +35,7 @@ class Puppet::FileServing::Content < Puppet::FileServing::Base
35
35
  # This stat can raise an exception, too.
36
36
  raise(ArgumentError, "Cannot read the contents of links unless following links") if stat.ftype == "symlink"
37
37
 
38
- @content = Puppet::Util.binread(full_path)
38
+ @content = IO.binread(full_path)
39
39
  end
40
40
  @content
41
41
  end
@@ -0,0 +1,153 @@
1
+ require 'net/http'
2
+ require 'open-uri'
3
+ require 'pathname'
4
+ require 'uri'
5
+ require 'puppet/forge/cache'
6
+ require 'puppet/forge/repository'
7
+
8
+ module Puppet::Forge
9
+ class Forge
10
+ def initialize(url=Puppet.settings[:module_repository])
11
+ @uri = URI.parse(url)
12
+ end
13
+
14
+ # Return a list of module metadata hashes that match the search query.
15
+ # This return value is used by the module_tool face install search,
16
+ # and displayed to on the console.
17
+ #
18
+ # Example return value:
19
+ #
20
+ # [
21
+ # {
22
+ # "author" => "puppetlabs",
23
+ # "name" => "bacula",
24
+ # "tag_list" => ["backup", "bacula"],
25
+ # "releases" => [{"version"=>"0.0.1"}, {"version"=>"0.0.2"}],
26
+ # "full_name" => "puppetlabs/bacula",
27
+ # "version" => "0.0.2",
28
+ # "project_url" => "http://github.com/puppetlabs/puppetlabs-bacula",
29
+ # "desc" => "bacula"
30
+ # }
31
+ # ]
32
+ #
33
+ def search(term)
34
+ request = Net::HTTP::Get.new("/modules.json?q=#{URI.escape(term)}")
35
+ response = repository.make_http_request(request)
36
+
37
+ case response.code
38
+ when "200"
39
+ matches = PSON.parse(response.body)
40
+ else
41
+ raise RuntimeError, "Could not execute search (HTTP #{response.code})"
42
+ matches = []
43
+ end
44
+
45
+ matches
46
+ end
47
+
48
+ # Return a Pathname object representing the path to the module
49
+ # release package in the `Puppet.settings[:module_working_dir]`.
50
+ def get_release_package(params)
51
+ cache_path = nil
52
+ case params[:source]
53
+ when :repository
54
+ if not (params[:author] && params[:modname])
55
+ raise ArgumentError, ":author and :modename required"
56
+ end
57
+ cache_path = get_release_package_from_repository(params[:author], params[:modname], params[:version])
58
+ when :filesystem
59
+ if not params[:filename]
60
+ raise ArgumentError, ":filename required"
61
+ end
62
+ cache_path = get_release_package_from_filesystem(params[:filename])
63
+ else
64
+ raise ArgumentError, "Could not determine installation source"
65
+ end
66
+
67
+ cache_path
68
+ end
69
+
70
+ def get_releases(author, modname)
71
+ request_string = "/#{author}/#{modname}"
72
+
73
+ begin
74
+ response = repository.make_http_request(request_string)
75
+ rescue => e
76
+ raise ArgumentError, "Could not find a release for this module (#{e.message})"
77
+ end
78
+
79
+ results = PSON.parse(response.body)
80
+ # At this point releases look like this:
81
+ # [{"version" => "0.0.1"}, {"version" => "0.0.2"},{"version" => "0.0.3"}]
82
+ #
83
+ # Lets fix this up a bit and return something like this to the caller
84
+ # ["0.0.1", "0.0.2", "0.0.3"]
85
+ results["releases"].collect {|release| release["version"]}
86
+ end
87
+
88
+ private
89
+
90
+ # Locate and download a module release package from the remote forge
91
+ # repository into the `Puppet.settings[:module_working_dir]`. Do not
92
+ # unpack it, just return the location of the package on disk.
93
+ def get_release_package_from_repository(author, modname, version=nil)
94
+ release = get_release(author, modname, version)
95
+ if release['file']
96
+ begin
97
+ cache_path = repository.retrieve(release['file'])
98
+ rescue OpenURI::HTTPError => e
99
+ raise RuntimeError, "Could not download module: #{e.message}"
100
+ end
101
+ else
102
+ raise RuntimeError, "Malformed response from module repository."
103
+ end
104
+
105
+ cache_path
106
+ end
107
+
108
+ # Locate a module release package on the local filesystem and move it
109
+ # into the `Puppet.settings[:module_working_dir]`. Do not unpack it, just
110
+ # return the location of the package on disk.
111
+ def get_release_package_from_filesystem(filename)
112
+ if File.exist?(File.expand_path(filename))
113
+ repository = Repository.new('file:///')
114
+ uri = URI.parse("file://#{URI.escape(File.expand_path(filename))}")
115
+ cache_path = repository.retrieve(uri)
116
+ else
117
+ raise ArgumentError, "File does not exists: #{filename}"
118
+ end
119
+
120
+ cache_path
121
+ end
122
+
123
+ def repository
124
+ @repository ||= Puppet::Forge::Repository.new(@uri)
125
+ end
126
+
127
+ # Connect to the remote repository and locate a specific module release
128
+ # by author/name combination. If a version requirement is specified, search
129
+ # for that exact version, or grab the latest release available.
130
+ #
131
+ # Return the following response to the caller:
132
+ #
133
+ # {"file"=>"/system/releases/p/puppetlabs/puppetlabs-apache-0.0.3.tar.gz", "version"=>"0.0.3"}
134
+ #
135
+ #
136
+ def get_release(author, modname, version_requirement=nil)
137
+ request_string = "/users/#{author}/modules/#{modname}/releases/find.json"
138
+ if version_requirement
139
+ request_string + "?version=#{URI.escape(version_requirement)}"
140
+ end
141
+ request = Net::HTTP::Get.new(request_string)
142
+
143
+ begin
144
+ response = repository.make_http_request(request)
145
+ rescue => e
146
+ raise ArgumentError, "Could not find a release for this module (#{e.message})"
147
+ end
148
+
149
+ PSON.parse(response.body)
150
+ end
151
+ end
152
+ end
153
+