puppet 2.7.13 → 2.7.14

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 (215) hide show
  1. data/CHANGELOG +144 -1
  2. data/conf/osx/preflight +1 -1
  3. data/conf/redhat/puppet.spec +9 -5
  4. data/conf/suse/puppet.spec +4 -1
  5. data/conf/windows/eventlog/Rakefile +32 -0
  6. data/conf/windows/eventlog/puppetres.dll +0 -0
  7. data/conf/windows/eventlog/puppetres.mc +18 -0
  8. data/ext/rack/files/apache2.conf +3 -0
  9. data/install.rb +23 -1
  10. data/lib/puppet.rb +1 -1
  11. data/lib/puppet/agent.rb +1 -14
  12. data/lib/puppet/application/kick.rb +1 -1
  13. data/lib/puppet/application/module.rb +11 -0
  14. data/lib/puppet/daemon.rb +74 -3
  15. data/lib/puppet/defaults.rb +1 -1
  16. data/lib/puppet/face/certificate.rb +1 -1
  17. data/lib/puppet/face/help/man.erb +1 -1
  18. data/lib/puppet/face/module.rb +17 -0
  19. data/lib/puppet/face/module/build.rb +10 -4
  20. data/lib/puppet/face/module/changes.rb +5 -5
  21. data/lib/puppet/face/module/generate.rb +6 -4
  22. data/lib/puppet/face/module/install.rb +122 -32
  23. data/lib/puppet/face/module/list.rb +234 -33
  24. data/lib/puppet/face/module/search.rb +56 -23
  25. data/lib/puppet/face/module/uninstall.rb +33 -38
  26. data/lib/puppet/face/module/upgrade.rb +84 -0
  27. data/lib/puppet/feature/eventlog.rb +6 -0
  28. data/lib/puppet/forge.rb +67 -122
  29. data/lib/puppet/forge/cache.rb +1 -1
  30. data/lib/puppet/forge/repository.rb +6 -25
  31. data/lib/puppet/indirector/facts/network_device.rb +1 -1
  32. data/lib/puppet/interface/action.rb +1 -1
  33. data/lib/puppet/module.rb +79 -28
  34. data/lib/puppet/module_tool.rb +72 -34
  35. data/lib/puppet/module_tool/applications.rb +12 -14
  36. data/lib/puppet/module_tool/applications/application.rb +21 -19
  37. data/lib/puppet/module_tool/applications/builder.rb +4 -4
  38. data/lib/puppet/module_tool/applications/checksummer.rb +12 -3
  39. data/lib/puppet/module_tool/applications/generator.rb +1 -1
  40. data/lib/puppet/module_tool/applications/installer.rb +163 -34
  41. data/lib/puppet/module_tool/applications/searcher.rb +2 -3
  42. data/lib/puppet/module_tool/applications/uninstaller.rb +84 -36
  43. data/lib/puppet/module_tool/applications/unpacker.rb +4 -26
  44. data/lib/puppet/module_tool/applications/upgrader.rb +109 -0
  45. data/lib/puppet/module_tool/checksums.rb +2 -2
  46. data/lib/puppet/module_tool/contents_description.rb +1 -1
  47. data/lib/puppet/module_tool/dependency.rb +2 -2
  48. data/lib/puppet/module_tool/errors.rb +9 -0
  49. data/lib/puppet/module_tool/errors/base.rb +15 -0
  50. data/lib/puppet/module_tool/errors/installer.rb +90 -0
  51. data/lib/puppet/module_tool/errors/shared.rb +115 -0
  52. data/lib/puppet/module_tool/errors/uninstaller.rb +45 -0
  53. data/lib/puppet/module_tool/errors/upgrader.rb +72 -0
  54. data/lib/puppet/module_tool/metadata.rb +2 -2
  55. data/lib/puppet/module_tool/modulefile.rb +7 -7
  56. data/lib/puppet/module_tool/shared_behaviors.rb +161 -0
  57. data/lib/puppet/module_tool/skeleton.rb +1 -1
  58. data/lib/puppet/node/environment.rb +4 -2
  59. data/lib/puppet/parser/ast/leaf.rb +1 -1
  60. data/lib/puppet/parser/functions/create_resources.rb +3 -2
  61. data/lib/puppet/parser/scope.rb +44 -9
  62. data/lib/puppet/provider/augeas/augeas.rb +2 -2
  63. data/lib/puppet/provider/exec.rb +8 -3
  64. data/lib/puppet/provider/exec/shell.rb +1 -2
  65. data/lib/puppet/provider/nameservice/directoryservice.rb +10 -4
  66. data/lib/puppet/provider/package/gem.rb +1 -1
  67. data/lib/puppet/provider/package/pkg.rb +10 -21
  68. data/lib/puppet/provider/selmodule/semodule.rb +1 -2
  69. data/lib/puppet/provider/service/upstart.rb +33 -17
  70. data/lib/puppet/provider/ssh_authorized_key/parsed.rb +1 -1
  71. data/lib/puppet/rails/inventory_node.rb +7 -7
  72. data/lib/puppet/reports/http.rb +4 -1
  73. data/lib/puppet/reports/tagmail.rb +8 -1
  74. data/lib/puppet/resource/type.rb +1 -1
  75. data/lib/puppet/test/test_helper.rb +138 -0
  76. data/lib/puppet/type.rb +9 -1
  77. data/lib/puppet/type/file.rb +18 -10
  78. data/lib/puppet/type/package.rb +13 -9
  79. data/lib/puppet/type/resources.rb +1 -1
  80. data/lib/puppet/type/ssh_authorized_key.rb +3 -4
  81. data/lib/puppet/type/sshkey.rb +4 -4
  82. data/lib/puppet/type/user.rb +1 -0
  83. data/lib/puppet/type/vlan.rb +1 -1
  84. data/lib/puppet/util.rb +31 -14
  85. data/lib/puppet/util/autoload.rb +1 -1
  86. data/lib/puppet/util/command_line.rb +2 -6
  87. data/lib/puppet/util/instrumentation/indirection_probe.rb +1 -1
  88. data/lib/puppet/util/instrumentation/instrumentable.rb +1 -1
  89. data/lib/puppet/util/instrumentation/listeners/log.rb +1 -1
  90. data/lib/puppet/util/instrumentation/listeners/performance.rb +1 -1
  91. data/lib/puppet/util/log.rb +3 -1
  92. data/lib/puppet/util/log/destinations.rb +38 -0
  93. data/lib/puppet/util/monkey_patches.rb +45 -0
  94. data/lib/puppet/util/network_device/base.rb +1 -1
  95. data/lib/puppet/util/network_device/cisco.rb +1 -1
  96. data/lib/puppet/util/network_device/cisco/facts.rb +1 -1
  97. data/lib/puppet/util/network_device/cisco/interface.rb +1 -1
  98. data/lib/puppet/util/network_device/config.rb +1 -1
  99. data/lib/puppet/util/network_device/ipcalc.rb +1 -1
  100. data/lib/puppet/util/network_device/transport.rb +1 -1
  101. data/lib/puppet/util/network_device/transport/base.rb +1 -1
  102. data/lib/puppet/util/network_device/transport/ssh.rb +1 -1
  103. data/lib/puppet/util/settings.rb +2 -11
  104. data/lib/puppet/util/settings/file_setting.rb +3 -5
  105. data/lib/puppet/util/terminal.rb +16 -0
  106. data/lib/puppet/util/zaml.rb +3 -1
  107. data/lib/semver.rb +15 -7
  108. data/spec/fixtures/releases/jamtur01-apache/metadata.json +1 -1
  109. data/spec/fixtures/unit/parser/lexer/arithmetic_expression.pp +1 -1
  110. data/spec/fixtures/unit/provider/package/pkg/dummy +1 -0
  111. data/spec/fixtures/unit/provider/package/pkg/incomplete +1 -0
  112. data/spec/fixtures/unit/provider/package/pkg/publisher +2 -0
  113. data/spec/fixtures/unit/provider/package/pkg/simple +4 -0
  114. data/spec/fixtures/unit/reports/tagmail/tagmail_email.conf +2 -0
  115. data/spec/fixtures/yaml/report0.25.x.yaml +1 -1
  116. data/spec/fixtures/yaml/report2.6.x.yaml +1 -1
  117. data/spec/integration/faces/documentation_spec.rb +1 -1
  118. data/spec/integration/network/rest_authconfig_spec.rb +1 -1
  119. data/spec/lib/puppet_spec/compiler.rb +6 -0
  120. data/spec/lib/puppet_spec/database.rb +30 -0
  121. data/spec/lib/puppet_spec/files.rb +4 -2
  122. data/spec/shared_behaviours/path_parameters.rb +2 -29
  123. data/spec/shared_contexts/platform.rb +43 -0
  124. data/spec/spec_helper.rb +36 -65
  125. data/spec/unit/agent_spec.rb +0 -32
  126. data/spec/unit/application/kick_spec.rb +2 -2
  127. data/spec/unit/daemon_spec.rb +1 -17
  128. data/spec/unit/face/module/install_spec.rb +158 -0
  129. data/spec/unit/face/module/list_spec.rb +182 -0
  130. data/spec/unit/face/module/search_spec.rb +163 -0
  131. data/spec/unit/face/module/uninstall_spec.rb +77 -0
  132. data/spec/unit/face/module/upgrade_spec.rb +26 -0
  133. data/spec/unit/forge/repository_spec.rb +0 -30
  134. data/spec/unit/forge_spec.rb +28 -86
  135. data/spec/unit/indirector/catalog/active_record_spec.rb +45 -65
  136. data/spec/unit/indirector/facts/inventory_active_record_spec.rb +5 -18
  137. data/spec/unit/indirector/resource/active_record_spec.rb +2 -11
  138. data/spec/unit/indirector/resource/ral_spec.rb +7 -2
  139. data/spec/unit/module_spec.rb +240 -107
  140. data/spec/unit/module_tool/application_spec.rb +3 -5
  141. data/spec/unit/module_tool/applications/application_spec.rb +19 -0
  142. data/spec/unit/module_tool/applications/installer_spec.rb +205 -0
  143. data/spec/unit/module_tool/applications/uninstaller_spec.rb +206 -0
  144. data/spec/unit/module_tool/applications/upgrader_spec.rb +37 -0
  145. data/spec/unit/module_tool/metadata_spec.rb +2 -2
  146. data/spec/unit/module_tool_spec.rb +109 -1
  147. data/spec/unit/node/environment_spec.rb +16 -1
  148. data/spec/unit/parser/ast/leaf_spec.rb +16 -1
  149. data/spec/unit/parser/collector_spec.rb +2 -12
  150. data/spec/unit/parser/functions/create_resources_spec.rb +135 -86
  151. data/spec/unit/parser/functions/generate_spec.rb +2 -10
  152. data/spec/unit/parser/scope_spec.rb +345 -16
  153. data/spec/unit/provider/augeas/augeas_spec.rb +19 -0
  154. data/spec/unit/provider/exec/shell_spec.rb +17 -14
  155. data/spec/unit/provider/exec/windows_spec.rb +1 -7
  156. data/spec/unit/provider/exec_spec.rb +35 -0
  157. data/spec/unit/provider/nameservice/directoryservice_spec.rb +10 -0
  158. data/spec/unit/provider/package/dpkg_spec.rb +2 -1
  159. data/spec/unit/provider/package/gem_spec.rb +15 -0
  160. data/spec/unit/provider/package/openbsd_spec.rb +5 -4
  161. data/spec/unit/provider/package/pacman_spec.rb +3 -2
  162. data/spec/unit/provider/package/pkg_spec.rb +56 -33
  163. data/spec/unit/provider/selmodule_spec.rb +11 -4
  164. data/spec/unit/provider/service/redhat_spec.rb +1 -3
  165. data/spec/unit/provider/service/smf_spec.rb +1 -3
  166. data/spec/unit/provider/service/upstart_spec.rb +38 -0
  167. data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +28 -0
  168. data/spec/unit/rails/host_spec.rb +6 -12
  169. data/spec/unit/rails/param_value_spec.rb +3 -8
  170. data/spec/unit/rails/resource_spec.rb +2 -8
  171. data/spec/unit/reports/http_spec.rb +47 -31
  172. data/spec/unit/reports/tagmail_spec.rb +77 -0
  173. data/spec/unit/resource/type_spec.rb +2 -2
  174. data/spec/unit/resource_spec.rb +18 -20
  175. data/spec/unit/semver_spec.rb +31 -13
  176. data/spec/unit/type/exec_spec.rb +8 -15
  177. data/spec/unit/type/group_spec.rb +0 -9
  178. data/spec/unit/type/package_spec.rb +10 -0
  179. data/spec/unit/type/resources_spec.rb +4 -5
  180. data/spec/unit/type/ssh_authorized_key_spec.rb +4 -15
  181. data/spec/unit/type/sshkey_spec.rb +9 -11
  182. data/spec/unit/type/user_spec.rb +123 -127
  183. data/spec/unit/type_spec.rb +20 -0
  184. data/spec/unit/util/command_line_spec.rb +2 -2
  185. data/spec/unit/util/instrumentation/data_spec.rb +1 -1
  186. data/spec/unit/util/instrumentation/indirection_probe_spec.rb +1 -1
  187. data/spec/unit/util/instrumentation/instrumentable_spec.rb +1 -1
  188. data/spec/unit/util/instrumentation/listener_spec.rb +1 -1
  189. data/spec/unit/util/instrumentation/listeners/log_spec.rb +1 -1
  190. data/spec/unit/util/instrumentation/listeners/performance_spec.rb +1 -1
  191. data/spec/unit/util/instrumentation_spec.rb +1 -1
  192. data/spec/unit/util/log/destinations_spec.rb +4 -8
  193. data/spec/unit/util/log_spec.rb +47 -0
  194. data/spec/unit/util/reference_spec.rb +1 -1
  195. data/spec/unit/util/settings/file_setting_spec.rb +9 -0
  196. data/spec/unit/util/settings_spec.rb +0 -53
  197. data/spec/unit/util/terminal_spec.rb +42 -0
  198. data/spec/unit/util/zaml_spec.rb +7 -0
  199. data/spec/unit/util_spec.rb +63 -20
  200. data/tasks/rake/manpages.rake +1 -1
  201. data/test/data/snippets/arithmetic_expression.pp +1 -1
  202. data/test/other/puppet.rb +0 -1
  203. data/test/util/log.rb +6 -6
  204. metadata +41 -16
  205. data/lib/puppet/external/event-loop.rb +0 -1
  206. data/lib/puppet/external/event-loop/better-definers.rb +0 -367
  207. data/lib/puppet/external/event-loop/event-loop.rb +0 -355
  208. data/lib/puppet/external/event-loop/signal-system.rb +0 -218
  209. data/lib/puppet/face/module/clean.rb +0 -30
  210. data/lib/puppet/module_tool/applications/cleaner.rb +0 -16
  211. data/lib/puppet/module_tool/skeleton/templates/generator/metadata.json +0 -12
  212. data/lib/puppet/module_tool/utils.rb +0 -5
  213. data/lib/puppet/module_tool/utils/interrogation.rb +0 -25
  214. data/spec/integration/module_tool_spec.rb +0 -475
  215. data/spec/unit/module_tool/uninstaller_spec.rb +0 -124
@@ -39,7 +39,7 @@ module Puppet::Forge
39
39
 
40
40
  # Return Pathname for repository's cache directory, create it if needed.
41
41
  def path
42
- return @path ||= (self.class.base_path + @repository.cache_key).tap{ |o| o.mkpath }
42
+ (self.class.base_path + @repository.cache_key).tap{ |o| o.mkpath }
43
43
  end
44
44
 
45
45
  # Return the base Pathname for all the caches.
@@ -2,26 +2,18 @@ require 'net/http'
2
2
  require 'digest/sha1'
3
3
  require 'uri'
4
4
 
5
- require 'puppet/module_tool/utils'
6
-
7
5
  module Puppet::Forge
8
- # Directory names that should not be checksummed.
9
- ARTIFACTS = ['pkg', /^\./, /^~/, /^#/, 'coverage']
10
- FULL_MODULE_NAME_PATTERN = /\A([^-\/|.]+)[-|\/](.+)\z/
11
- REPOSITORY_URL = Puppet.settings[:module_repository]
12
-
13
6
  # = Repository
14
7
  #
15
8
  # This class is a file for accessing remote repositories with modules.
16
9
  class Repository
17
- include Puppet::Module::Tool::Utils::Interrogation
18
10
 
19
11
  attr_reader :uri, :cache
20
12
 
21
13
  # Instantiate a new repository instance rooted at the optional string
22
14
  # +url+, else an instance of the default Puppet modules repository.
23
15
  def initialize(url=Puppet[:module_repository])
24
- @uri = url.is_a?(::URI) ? url : ::URI.parse(url)
16
+ @uri = url.is_a?(::URI) ? url : ::URI.parse(url.sub(/^(?!https?:\/\/)/, 'http://'))
25
17
  @cache = Cache.new(self)
26
18
  end
27
19
 
@@ -62,13 +54,7 @@ module Puppet::Forge
62
54
  end
63
55
 
64
56
  # Return a Net::HTTPResponse read for this +request+.
65
- #
66
- # Options:
67
- # * :authenticate => Request authentication on the terminal. Defaults to false.
68
57
  def make_http_request(request, options = {})
69
- if options[:authenticate]
70
- authenticate(request)
71
- end
72
58
  if ! @uri.user.nil? && ! @uri.password.nil?
73
59
  request.basic_auth(@uri.user, @uri.password)
74
60
  end
@@ -85,19 +71,14 @@ module Puppet::Forge
85
71
  http.request(request)
86
72
  end
87
73
  rescue Errno::ECONNREFUSED, SocketError
88
- raise RuntimeError, "Could not reach remote repository"
74
+ msg = "Error: Could not connect to #{@uri}\n"
75
+ msg << " There was a network communications problem\n"
76
+ msg << " Check your network connection and try again\n"
77
+ Puppet.err msg
78
+ exit(1)
89
79
  end
90
80
  end
91
81
 
92
- # Set the HTTP Basic Authentication parameters for the Net::HTTPRequest
93
- # +request+ by asking the user for input on the console.
94
- def authenticate(request)
95
- Puppet.notice "Authenticating for #{@uri}"
96
- email = prompt('Email Address')
97
- password = prompt('Password', true)
98
- request.basic_auth(email, password)
99
- end
100
-
101
82
  # Return the local file name containing the data downloaded from the
102
83
  # repository at +release+ (e.g. "myuser-mymodule").
103
84
  def retrieve(release)
@@ -22,4 +22,4 @@ class Puppet::Node::Facts::NetworkDevice < Puppet::Indirector::Code
22
22
  def save(facts)
23
23
  raise Puppet::DevError, "You cannot save facts to the code store; it is only used for getting facts from a remote device"
24
24
  end
25
- end
25
+ end
@@ -212,7 +212,7 @@ WRAPPER
212
212
 
213
213
  if @face.is_a?(Class)
214
214
  @face.class_eval do eval wrapper, nil, file, line end
215
- @face.define_method(internal_name, &block)
215
+ @face.send(:define_method, internal_name, &block)
216
216
  @when_invoked = @face.instance_method(name)
217
217
  else
218
218
  @face.instance_eval do eval wrapper, nil, file, line end
@@ -119,6 +119,18 @@ class Puppet::Module
119
119
  raise MissingMetadata, "No #{attr} module metadata provided for #{self.name}"
120
120
  end
121
121
  end
122
+
123
+ # NOTICE: The fallback to `versionRequirement` is something we'd like to
124
+ # not have to support, but we have a reasonable number of releases that
125
+ # don't use `version_requirement`. When we can deprecate this, we should.
126
+ if attr == :dependencies
127
+ value.tap do |dependencies|
128
+ dependencies.each do |dep|
129
+ dep['version_requirement'] ||= dep['versionRequirement'] || '>= 0.0.0'
130
+ end
131
+ end
132
+ end
133
+
122
134
  send(attr.to_s + "=", value)
123
135
  end
124
136
  end
@@ -144,6 +156,10 @@ class Puppet::Module
144
156
  @path ||= environment.modulepath.collect { |path| File.join(path, name) }.find { |d| FileTest.directory?(d) }
145
157
  end
146
158
 
159
+ def modulepath
160
+ File.dirname(path) if path
161
+ end
162
+
147
163
  # Find all plugin directories. This is used by the Plugins fileserving mount.
148
164
  def plugin_directory
149
165
  subpath("plugins")
@@ -176,55 +192,90 @@ class Puppet::Module
176
192
  end
177
193
 
178
194
  def has_local_changes?
179
- changes = Puppet::Module::Tool::Applications::Checksummer.run(path)
195
+ changes = Puppet::ModuleTool::Applications::Checksummer.run(path)
180
196
  !changes.empty?
181
197
  end
182
198
 
183
- def unmet_dependencies
184
- return [] unless dependencies
199
+ def local_changes
200
+ Puppet::ModuleTool::Applications::Checksummer.run(path)
201
+ end
185
202
 
203
+ # Identify and mark unmet dependencies. A dependency will be marked unmet
204
+ # for the following reasons:
205
+ #
206
+ # * not installed and is thus considered missing
207
+ # * installed and does not meet the version requirements for this module
208
+ # * installed and doesn't use semantic versioning
209
+ #
210
+ # Returns a list of hashes representing the details of an unmet dependency.
211
+ #
212
+ # Example:
213
+ #
214
+ # [
215
+ # {
216
+ # :reason => :missing,
217
+ # :name => 'puppetlabs-mysql',
218
+ # :version_constraint => 'v0.0.1',
219
+ # :mod_details => {
220
+ # :installed_version => '0.0.1'
221
+ # }
222
+ # :parent => {
223
+ # :name => 'puppetlabs-bacula',
224
+ # :version => 'v1.0.0'
225
+ # }
226
+ # }
227
+ # ]
228
+ #
229
+ def unmet_dependencies
186
230
  unmet_dependencies = []
231
+ return unmet_dependencies unless dependencies
187
232
 
188
233
  dependencies.each do |dependency|
189
234
  forge_name = dependency['name']
190
- author, dep_name = forge_name.split('/')
191
- version_string = dependency['version_requirement']
235
+ version_string = dependency['version_requirement'] || '>= 0.0.0'
192
236
 
193
- equality, dep_version = version_string ? version_string.split("\s") : [nil, nil]
194
-
195
- unless dep_mod = environment.module(dep_name)
196
- msg = "Missing dependency `#{dep_name}`:\n"
197
- msg += " `#{self.name}` (#{self.version}) requires `#{forge_name}` (#{version_string})\n"
198
- unmet_dependencies << { :name => forge_name, :error => msg }
199
- next
237
+ dep_mod = begin
238
+ environment.module_by_forge_name(forge_name)
239
+ rescue => e
240
+ nil
200
241
  end
201
242
 
202
- if dep_version && !dep_mod.version
203
- msg = "Unversioned dependency `#{dep_mod.name}`:\n"
204
- msg += " `#{self.name}` (#{self.version}) requires `#{forge_name}` (#{version_string})\n"
205
- unmet_dependencies << { :name => forge_name, :error => msg }
243
+ error_details = {
244
+ :name => forge_name,
245
+ :version_constraint => version_string.gsub(/^(?=\d)/, "v"),
246
+ :parent => {
247
+ :name => self.forge_name,
248
+ :version => self.version.gsub(/^(?=\d)/, "v")
249
+ },
250
+ :mod_details => {
251
+ :installed_version => dep_mod.nil? ? nil : dep_mod.version
252
+ }
253
+ }
254
+
255
+ unless dep_mod
256
+ error_details[:reason] = :missing
257
+ unmet_dependencies << error_details
206
258
  next
207
259
  end
208
260
 
209
- if dep_version
261
+ if version_string
210
262
  begin
211
- required_version_semver = SemVer.new(dep_version)
263
+ required_version_semver_range = SemVer[version_string]
212
264
  actual_version_semver = SemVer.new(dep_mod.version)
213
265
  rescue ArgumentError
214
- msg = "Non semantic version dependency `#{dep_mod.name}` (#{dep_mod.version}):\n"
215
- msg += " `#{self.name}` (#{self.version}) requires `#{forge_name}` (#{version_string})\n"
216
- unmet_dependencies << { :name => forge_name, :error => msg }
266
+ error_details[:reason] = :non_semantic_version
267
+ unmet_dependencies << error_details
217
268
  next
218
269
  end
219
270
 
220
- if !actual_version_semver.send(equality, required_version_semver)
221
- msg = "Version dependency mismatch `#{dep_mod.name}` (#{dep_mod.version}):\n"
222
- msg += " `#{self.name}` (#{self.version}) requires `#{forge_name}` (#{version_string})\n"
223
- unmet_dependencies << { :name => forge_name, :error => msg }
271
+ unless required_version_semver_range.include? actual_version_semver
272
+ error_details[:reason] = :version_mismatch
273
+ unmet_dependencies << error_details
224
274
  next
225
275
  end
226
276
  end
227
277
  end
278
+
228
279
  unmet_dependencies
229
280
  end
230
281
 
@@ -256,8 +307,8 @@ class Puppet::Module
256
307
 
257
308
  def ==(other)
258
309
  self.name == other.name &&
259
- self.version == other.version &&
260
- self.path == other.path &&
261
- self.environment == other.environment
310
+ self.version == other.version &&
311
+ self.path == other.path &&
312
+ self.environment == other.environment
262
313
  end
263
314
  end
@@ -1,55 +1,93 @@
1
+ # encoding: UTF-8
1
2
  # Load standard libraries
2
3
  require 'pathname'
3
4
  require 'fileutils'
4
- require 'puppet/module_tool/utils'
5
+ require 'puppet/util/colors'
5
6
 
6
7
  # Define tool
7
8
  module Puppet
8
- class Module
9
- module Tool
10
-
11
- # Directory names that should not be checksummed.
12
- ARTIFACTS = ['pkg', /^\./, /^~/, /^#/, 'coverage']
13
- FULL_MODULE_NAME_PATTERN = /\A([^-\/|.]+)[-|\/](.+)\z/
14
- REPOSITORY_URL = Puppet.settings[:module_repository]
15
-
16
- # Is this a directory that shouldn't be checksummed?
17
- #
18
- # TODO: Should this be part of Checksums?
19
- # TODO: Rename this method to reflect it's purpose?
20
- # TODO: Shouldn't this be used when building packages too?
21
- def self.artifact?(path)
22
- case File.basename(path)
23
- when *ARTIFACTS
24
- true
25
- else
26
- false
27
- end
9
+ module ModuleTool
10
+ extend Puppet::Util::Colors
11
+
12
+ # Directory and names that should not be checksummed.
13
+ ARTIFACTS = ['pkg', /^\./, /^~/, /^#/, 'coverage', 'metadata.json', 'REVISION']
14
+ FULL_MODULE_NAME_PATTERN = /\A([^-\/|.]+)[-|\/](.+)\z/
15
+ REPOSITORY_URL = Puppet.settings[:module_repository]
16
+
17
+ # Is this a directory that shouldn't be checksummed?
18
+ #
19
+ # TODO: Should this be part of Checksums?
20
+ # TODO: Rename this method to reflect it's purpose?
21
+ # TODO: Shouldn't this be used when building packages too?
22
+ def self.artifact?(path)
23
+ case File.basename(path)
24
+ when *ARTIFACTS
25
+ true
26
+ else
27
+ false
28
+ end
29
+ end
30
+
31
+ # Return the +username+ and +modname+ for a given +full_module_name+, or raise an
32
+ # ArgumentError if the argument isn't parseable.
33
+ def self.username_and_modname_from(full_module_name)
34
+ if matcher = full_module_name.match(FULL_MODULE_NAME_PATTERN)
35
+ return matcher.captures
36
+ else
37
+ raise ArgumentError, "Not a valid full name: #{full_module_name}"
28
38
  end
39
+ end
29
40
 
30
- # Return the +username+ and +modname+ for a given +full_module_name+, or raise an
31
- # ArgumentError if the argument isn't parseable.
32
- def self.username_and_modname_from(full_module_name)
33
- if matcher = full_module_name.match(FULL_MODULE_NAME_PATTERN)
34
- return matcher.captures
35
- else
36
- raise ArgumentError, "Not a valid full name: #{full_module_name}"
41
+ def self.find_module_root(path)
42
+ for dir in [path, Dir.pwd].compact
43
+ if File.exist?(File.join(dir, 'Modulefile'))
44
+ return dir
37
45
  end
38
46
  end
47
+ raise ArgumentError, "Could not find a valid module at #{path ? path.inspect : 'current directory'}"
48
+ end
49
+
50
+ # Builds a formatted tree from a list of node hashes containing +:text+
51
+ # and +:dependencies+ keys.
52
+ def self.format_tree(nodes, level = 0)
53
+ str = ''
54
+ nodes.each_with_index do |node, i|
55
+ last_node = nodes.length - 1 == i
56
+ deps = node[:dependencies] || []
57
+
58
+ str << (indent = " " * level)
59
+ str << (last_node ? "└" : "├")
60
+ str << "─"
61
+ str << (deps.empty? ? "─" : "┬")
62
+ str << " #{node[:text]}\n"
63
+
64
+ branch = format_tree(deps, level + 1)
65
+ branch.gsub!(/^#{indent} /, indent + '│') unless last_node
66
+ str << branch
67
+ end
39
68
 
40
- def self.find_module_root(path)
41
- for dir in [path, Dir.pwd].compact
42
- if File.exist?(File.join(dir, 'Modulefile'))
43
- return dir
44
- end
69
+ return str
70
+ end
71
+
72
+ def self.build_tree(mods, dir)
73
+ mods.each do |mod|
74
+ version_string = mod[:version][:vstring].sub(/^(?!v)/, 'v')
75
+
76
+ if mod[:action] == :upgrade
77
+ previous_version = mod[:previous_version].sub(/^(?!v)/, 'v')
78
+ version_string = "#{previous_version} -> #{version_string}"
45
79
  end
46
- raise ArgumentError, "Could not find a valid module at #{path ? path.inspect : 'current directory'}"
80
+
81
+ mod[:text] = "#{mod[:module]} (#{colorize(:cyan, version_string)})"
82
+ mod[:text] += " [#{mod[:path]}]" unless mod[:path] == dir
83
+ build_tree(mod[:dependencies], dir)
47
84
  end
48
85
  end
49
86
  end
50
87
  end
51
88
 
52
89
  # Load remaining libraries
90
+ require 'puppet/module_tool/errors'
53
91
  require 'puppet/module_tool/applications'
54
92
  require 'puppet/module_tool/checksums'
55
93
  require 'puppet/module_tool/contents_description'
@@ -1,17 +1,15 @@
1
- require 'puppet/module'
1
+ require 'puppet/module_tool'
2
2
 
3
- class Puppet::Module
4
- module Tool
5
- module Applications
6
- require 'puppet/module_tool/applications/application'
7
- require 'puppet/module_tool/applications/builder'
8
- require 'puppet/module_tool/applications/checksummer'
9
- require 'puppet/module_tool/applications/cleaner'
10
- require 'puppet/module_tool/applications/generator'
11
- require 'puppet/module_tool/applications/installer'
12
- require 'puppet/module_tool/applications/searcher'
13
- require 'puppet/module_tool/applications/unpacker'
14
- require 'puppet/module_tool/applications/uninstaller'
15
- end
3
+ module Puppet::ModuleTool
4
+ module Applications
5
+ require 'puppet/module_tool/applications/application'
6
+ require 'puppet/module_tool/applications/builder'
7
+ require 'puppet/module_tool/applications/checksummer'
8
+ require 'puppet/module_tool/applications/generator'
9
+ require 'puppet/module_tool/applications/installer'
10
+ require 'puppet/module_tool/applications/searcher'
11
+ require 'puppet/module_tool/applications/unpacker'
12
+ require 'puppet/module_tool/applications/uninstaller'
13
+ require 'puppet/module_tool/applications/upgrader'
16
14
  end
17
15
  end
@@ -1,11 +1,11 @@
1
1
  require 'net/http'
2
2
  require 'semver'
3
- require 'puppet/module_tool/utils/interrogation'
3
+ require 'puppet/util/colors'
4
4
 
5
- module Puppet::Module::Tool
5
+ module Puppet::ModuleTool
6
6
  module Applications
7
7
  class Application
8
- include Puppet::Module::Tool::Utils::Interrogation
8
+ include Puppet::Util::Colors
9
9
 
10
10
  def self.run(*args)
11
11
  new(*args).run
@@ -14,6 +14,9 @@ module Puppet::Module::Tool
14
14
  attr_accessor :options
15
15
 
16
16
  def initialize(options = {})
17
+ if Puppet.features.microsoft_windows?
18
+ raise Puppet::Error, "`puppet module` actions are currently not supported on Microsoft Windows"
19
+ end
17
20
  @options = options
18
21
  end
19
22
 
@@ -36,14 +39,14 @@ module Puppet::Module::Tool
36
39
  unless @path
37
40
  raise ArgumentError, "Could not determine module path"
38
41
  end
39
- @metadata = Puppet::Module::Tool::Metadata.new
42
+ @metadata = Puppet::ModuleTool::Metadata.new
40
43
  contents = ContentsDescription.new(@path)
41
44
  contents.annotate(@metadata)
42
45
  checksums = Checksums.new(@path)
43
46
  checksums.annotate(@metadata)
44
47
  modulefile_path = File.join(@path, 'Modulefile')
45
48
  if File.file?(modulefile_path)
46
- Puppet::Module::Tool::ModulefileReader.evaluate(@metadata, modulefile_path)
49
+ Puppet::ModuleTool::ModulefileReader.evaluate(@metadata, modulefile_path)
47
50
  elsif require_modulefile
48
51
  raise ArgumentError, "No Modulefile found."
49
52
  end
@@ -56,24 +59,23 @@ module Puppet::Module::Tool
56
59
  metadata(true)
57
60
  end
58
61
 
59
- # Use to extract and validate a module name and version from a
60
- # filename
61
- # Note: Must have @filename set to use this
62
- def parse_filename!
63
- @release_name = File.basename(@filename,'.tar.gz')
64
- match = /^(.*?)-(.*?)-(\d+\.\d+\.\d+.*?)$/.match(@release_name)
65
- if match then
66
- @username, @module_name, @version = match.captures
62
+ def parse_filename(filename)
63
+ if match = /^((.*?)-(.*?))-(\d+\.\d+\.\d+.*?)$/.match(File.basename(filename,'.tar.gz'))
64
+ module_name, author, shortname, version = match.captures
67
65
  else
68
66
  raise ArgumentError, "Could not parse filename to obtain the username, module name and version. (#{@release_name})"
69
67
  end
70
- @full_module_name = [@username, @module_name].join('-')
71
- unless @username && @module_name
72
- raise ArgumentError, "Username and Module name not provided"
73
- end
74
- unless SemVer.valid?(@version)
75
- raise ArgumentError, "Invalid version format: #{@version} (Semantic Versions are acceptable: http://semver.org)"
68
+
69
+ unless SemVer.valid?(version)
70
+ raise ArgumentError, "Invalid version format: #{version} (Semantic Versions are acceptable: http://semver.org)"
76
71
  end
72
+
73
+ return {
74
+ :module_name => module_name,
75
+ :author => author,
76
+ :dir_name => shortname,
77
+ :version => version
78
+ }
77
79
  end
78
80
  end
79
81
  end