puppet 6.14.0 → 6.15.0

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 (195) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +15 -15
  3. data/ext/windows/service/daemon.rb +3 -3
  4. data/lib/puppet.rb +1 -1
  5. data/lib/puppet/agent.rb +2 -10
  6. data/lib/puppet/application/agent.rb +2 -1
  7. data/lib/puppet/application/filebucket.rb +5 -14
  8. data/lib/puppet/application/ssl.rb +2 -2
  9. data/lib/puppet/configurer.rb +7 -3
  10. data/lib/puppet/configurer/plugin_handler.rb +1 -1
  11. data/lib/puppet/defaults.rb +22 -2
  12. data/lib/puppet/environments.rb +4 -5
  13. data/lib/puppet/face/plugin.rb +1 -1
  14. data/lib/puppet/file_system/file_impl.rb +13 -9
  15. data/lib/puppet/forge/repository.rb +1 -1
  16. data/lib/puppet/functions/call.rb +1 -1
  17. data/lib/puppet/functions/reduce.rb +2 -4
  18. data/lib/puppet/http.rb +2 -0
  19. data/lib/puppet/http/client.rb +191 -52
  20. data/lib/puppet/http/external_client.rb +96 -0
  21. data/lib/puppet/http/redirector.rb +34 -0
  22. data/lib/puppet/http/resolver.rb +46 -3
  23. data/lib/puppet/http/resolver/server_list.rb +75 -15
  24. data/lib/puppet/http/resolver/settings.rb +22 -2
  25. data/lib/puppet/http/resolver/srv.rb +28 -2
  26. data/lib/puppet/http/response.rb +63 -1
  27. data/lib/puppet/http/retry_after_handler.rb +39 -0
  28. data/lib/puppet/http/service.rb +67 -1
  29. data/lib/puppet/http/service/ca.rb +71 -9
  30. data/lib/puppet/http/service/compiler.rb +213 -11
  31. data/lib/puppet/http/service/file_server.rb +105 -4
  32. data/lib/puppet/http/service/report.rb +36 -3
  33. data/lib/puppet/http/session.rb +59 -8
  34. data/lib/puppet/indirector/catalog/rest.rb +2 -1
  35. data/lib/puppet/indirector/facts/rest.rb +2 -1
  36. data/lib/puppet/indirector/file_bucket_file/rest.rb +48 -0
  37. data/lib/puppet/indirector/file_metadata/rest.rb +4 -2
  38. data/lib/puppet/indirector/node/rest.rb +2 -1
  39. data/lib/puppet/indirector/report/yaml.rb +23 -0
  40. data/lib/puppet/indirector/status/rest.rb +2 -1
  41. data/lib/puppet/metatype/manager.rb +80 -80
  42. data/lib/puppet/network/http/base_pool.rb +6 -1
  43. data/lib/puppet/network/http/pool.rb +2 -4
  44. data/lib/puppet/network/http_pool.rb +1 -0
  45. data/lib/puppet/node/environment.rb +11 -1
  46. data/lib/puppet/pal/pal_impl.rb +1 -29
  47. data/lib/puppet/parser/compiler.rb +14 -7
  48. data/lib/puppet/parser/functions.rb +18 -13
  49. data/lib/puppet/pops/loaders.rb +7 -5
  50. data/lib/puppet/provider/group/windows_adsi.rb +3 -3
  51. data/lib/puppet/provider/package/apt.rb +61 -1
  52. data/lib/puppet/provider/package/dnfmodule.rb +39 -12
  53. data/lib/puppet/provider/package/gem.rb +41 -7
  54. data/lib/puppet/provider/package/pacman.rb +2 -5
  55. data/lib/puppet/provider/package/pip.rb +105 -33
  56. data/lib/puppet/provider/package/pip3.rb +0 -2
  57. data/lib/puppet/provider/package/pkgdmg.rb +1 -1
  58. data/lib/puppet/provider/package/pkgng.rb +16 -4
  59. data/lib/puppet/provider/package/puppet_gem.rb +6 -2
  60. data/lib/puppet/provider/package/rpm.rb +6 -213
  61. data/lib/puppet/provider/package/yum.rb +92 -19
  62. data/lib/puppet/provider/service/systemd.rb +2 -1
  63. data/lib/puppet/reports/http.rb +13 -11
  64. data/lib/puppet/resource/type_collection.rb +20 -16
  65. data/lib/puppet/ssl.rb +1 -0
  66. data/lib/puppet/ssl/host.rb +4 -4
  67. data/lib/puppet/ssl/oids.rb +1 -0
  68. data/lib/puppet/ssl/state_machine.rb +50 -33
  69. data/lib/puppet/transaction/report.rb +2 -2
  70. data/lib/puppet/type.rb +6 -1
  71. data/lib/puppet/type/file/source.rb +4 -2
  72. data/lib/puppet/type/package.rb +25 -2
  73. data/lib/puppet/type/user.rb +0 -19
  74. data/lib/puppet/util/at_fork.rb +1 -1
  75. data/lib/puppet/util/autoload.rb +3 -0
  76. data/lib/puppet/util/instance_loader.rb +14 -10
  77. data/lib/puppet/util/package/version/debian.rb +175 -0
  78. data/lib/puppet/util/package/version/gem.rb +15 -0
  79. data/lib/puppet/util/package/version/pip.rb +167 -0
  80. data/lib/puppet/util/package/version/range.rb +50 -0
  81. data/lib/puppet/util/package/version/range/gt.rb +14 -0
  82. data/lib/puppet/util/package/version/range/gt_eq.rb +14 -0
  83. data/lib/puppet/util/package/version/range/lt.rb +14 -0
  84. data/lib/puppet/util/package/version/range/lt_eq.rb +14 -0
  85. data/lib/puppet/util/package/version/range/min_max.rb +21 -0
  86. data/lib/puppet/util/package/version/range/simple.rb +11 -0
  87. data/lib/puppet/util/package/version/rpm.rb +73 -0
  88. data/lib/puppet/util/pidlock.rb +13 -7
  89. data/lib/puppet/util/platform.rb +5 -0
  90. data/lib/puppet/util/rpm_compare.rb +193 -0
  91. data/lib/puppet/util/windows/adsi.rb +2 -2
  92. data/lib/puppet/util/windows/process.rb +15 -14
  93. data/lib/puppet/util/windows/security.rb +1 -0
  94. data/lib/puppet/util/windows/sid.rb +3 -3
  95. data/lib/puppet/version.rb +1 -1
  96. data/locales/puppet.pot +207 -201
  97. data/man/man5/puppet.conf.5 +11 -3
  98. data/man/man8/puppet-agent.8 +1 -1
  99. data/man/man8/puppet-apply.8 +1 -1
  100. data/man/man8/puppet-catalog.8 +1 -1
  101. data/man/man8/puppet-config.8 +1 -1
  102. data/man/man8/puppet-describe.8 +1 -1
  103. data/man/man8/puppet-device.8 +1 -1
  104. data/man/man8/puppet-doc.8 +1 -1
  105. data/man/man8/puppet-epp.8 +1 -1
  106. data/man/man8/puppet-facts.8 +1 -1
  107. data/man/man8/puppet-filebucket.8 +1 -1
  108. data/man/man8/puppet-generate.8 +1 -1
  109. data/man/man8/puppet-help.8 +1 -1
  110. data/man/man8/puppet-key.8 +1 -1
  111. data/man/man8/puppet-lookup.8 +1 -1
  112. data/man/man8/puppet-man.8 +1 -1
  113. data/man/man8/puppet-module.8 +1 -1
  114. data/man/man8/puppet-node.8 +1 -1
  115. data/man/man8/puppet-parser.8 +1 -1
  116. data/man/man8/puppet-plugin.8 +1 -1
  117. data/man/man8/puppet-report.8 +1 -1
  118. data/man/man8/puppet-resource.8 +1 -1
  119. data/man/man8/puppet-script.8 +1 -1
  120. data/man/man8/puppet-ssl.8 +1 -1
  121. data/man/man8/puppet-status.8 +1 -1
  122. data/man/man8/puppet.8 +2 -2
  123. data/spec/fixtures/ssl/unknown-127.0.0.1-key.pem +67 -0
  124. data/spec/fixtures/ssl/unknown-127.0.0.1.pem +48 -0
  125. data/spec/fixtures/ssl/unknown-ca-key.pem +67 -0
  126. data/spec/fixtures/ssl/unknown-ca.pem +59 -0
  127. data/spec/fixtures/unit/provider/package/dnfmodule/{dnf-module-list-installed.txt → dnf-module-list-enabled.txt} +2 -0
  128. data/spec/fixtures/unit/provider/package/pkgng/pkg.version +2 -0
  129. data/spec/fixtures/unit/provider/package/yum/yum-check-update-subscription-manager.txt +9 -0
  130. data/spec/fixtures/unit/provider/service/systemd/list_unit_files_services +9 -0
  131. data/spec/integration/application/agent_spec.rb +329 -0
  132. data/spec/integration/application/apply_spec.rb +132 -3
  133. data/spec/integration/application/filebucket_spec.rb +190 -0
  134. data/spec/integration/application/plugin_spec.rb +50 -0
  135. data/spec/integration/http/client_spec.rb +34 -40
  136. data/spec/integration/indirector/report/yaml.rb +83 -0
  137. data/spec/integration/module_tool/forge_spec.rb +2 -15
  138. data/spec/integration/network/http_pool_spec.rb +11 -19
  139. data/spec/integration/node/environment_spec.rb +15 -0
  140. data/spec/integration/util/windows/adsi_spec.rb +1 -1
  141. data/spec/lib/puppet/test_ca.rb +2 -2
  142. data/spec/lib/puppet_spec/https.rb +10 -7
  143. data/spec/lib/puppet_spec/puppetserver.rb +119 -0
  144. data/spec/shared_contexts/https.rb +29 -0
  145. data/spec/unit/agent_spec.rb +33 -25
  146. data/spec/unit/application/agent_spec.rb +5 -1
  147. data/spec/unit/application/device_spec.rb +2 -2
  148. data/spec/unit/application/filebucket_spec.rb +22 -2
  149. data/spec/unit/configurer_spec.rb +1 -1
  150. data/spec/unit/defaults_spec.rb +24 -1
  151. data/spec/unit/environments_spec.rb +8 -0
  152. data/spec/unit/file_system_spec.rb +10 -0
  153. data/spec/unit/http/client_spec.rb +105 -46
  154. data/spec/unit/http/external_client_spec.rb +201 -0
  155. data/spec/unit/http/resolver_spec.rb +20 -0
  156. data/spec/unit/http/service/ca_spec.rb +25 -2
  157. data/spec/unit/http/service/compiler_spec.rb +184 -6
  158. data/spec/unit/http/service/file_server_spec.rb +35 -3
  159. data/spec/unit/http/service/report_spec.rb +3 -1
  160. data/spec/unit/http/service_spec.rb +3 -3
  161. data/spec/unit/http/session_spec.rb +56 -7
  162. data/spec/unit/indirector/file_bucket_file/rest_spec.rb +82 -2
  163. data/spec/unit/network/http/pool_spec.rb +3 -3
  164. data/spec/unit/node/environment_spec.rb +16 -0
  165. data/spec/unit/provider/group/windows_adsi_spec.rb +43 -10
  166. data/spec/unit/provider/package/apt_spec.rb +30 -0
  167. data/spec/unit/provider/package/dnfmodule_spec.rb +33 -14
  168. data/spec/unit/provider/package/gem_spec.rb +40 -0
  169. data/spec/unit/provider/package/pacman_spec.rb +6 -21
  170. data/spec/unit/provider/package/pip_spec.rb +26 -3
  171. data/spec/unit/provider/package/pkgdmg_spec.rb +1 -1
  172. data/spec/unit/provider/package/pkgng_spec.rb +38 -0
  173. data/spec/unit/provider/package/puppet_gem_spec.rb +8 -0
  174. data/spec/unit/provider/package/rpm_spec.rb +0 -212
  175. data/spec/unit/provider/package/yum_spec.rb +235 -1
  176. data/spec/unit/provider/service/systemd_spec.rb +10 -1
  177. data/spec/unit/provider/user/windows_adsi_spec.rb +3 -3
  178. data/spec/unit/puppet_pal_2pec.rb +0 -29
  179. data/spec/unit/reports/http_spec.rb +70 -52
  180. data/spec/unit/ssl/host_spec.rb +4 -2
  181. data/spec/unit/ssl/oids_spec.rb +1 -0
  182. data/spec/unit/ssl/state_machine_spec.rb +38 -6
  183. data/spec/unit/transaction/report_spec.rb +4 -0
  184. data/spec/unit/util/at_fork_spec.rb +2 -2
  185. data/spec/unit/util/package/version/debian_spec.rb +83 -0
  186. data/spec/unit/util/package/version/pip_spec.rb +464 -0
  187. data/spec/unit/util/package/version/range_spec.rb +154 -0
  188. data/spec/unit/util/package/version/rpm_spec.rb +121 -0
  189. data/spec/unit/util/pidlock_spec.rb +83 -47
  190. data/spec/unit/util/rpm_compare_spec.rb +196 -0
  191. data/spec/unit/util/windows/adsi_spec.rb +4 -4
  192. data/spec/unit/util/windows/sid_spec.rb +2 -2
  193. data/tasks/generate_cert_fixtures.rake +15 -1
  194. metadata +51 -6
  195. data/spec/integration/faces/plugin_spec.rb +0 -63
@@ -1,8 +1,6 @@
1
1
  # Puppet package provider for Python's `pip3` package management frontend.
2
2
  # <http://pip.pypa.io/>
3
3
 
4
- require 'puppet/provider/package/pip'
5
-
6
4
  Puppet::Type.type(:package).provide :pip3,
7
5
  :parent => :pip do
8
6
 
@@ -102,7 +102,7 @@ Puppet::Type.type(:package).provide :pkgdmg, :parent => Puppet::Provider::Packag
102
102
  if source =~ /\.dmg$/i
103
103
  # If you fix this to use open-uri again, you must update the docs above. -NF
104
104
  File.open(cached_source) do |dmg|
105
- xml_str = hdiutil "mount", "-plist", "-nobrowse", "-readonly", "-noidme", "-mountrandom", "/tmp", dmg.path
105
+ xml_str = hdiutil "mount", "-plist", "-nobrowse", "-readonly", "-mountrandom", "/tmp", dmg.path
106
106
  hdiutil_info = Puppet::Util::Plist.parse_plist(xml_str)
107
107
  raise Puppet::Error.new(_("No disk entities returned by mount at %{path}") % { path: dmg.path }) unless hdiutil_info.has_key?("system-entities")
108
108
  mounts = hdiutil_info["system-entities"].collect { |entity|
@@ -11,6 +11,7 @@ Puppet::Type.type(:package).provide :pkgng, :parent => Puppet::Provider::Package
11
11
 
12
12
  has_feature :versionable
13
13
  has_feature :upgradeable
14
+ has_feature :install_options
14
15
 
15
16
  def self.get_query
16
17
  pkg(['query', '-a', '%n %v %o'])
@@ -31,7 +32,11 @@ Puppet::Type.type(:package).provide :pkgng, :parent => Puppet::Provider::Package
31
32
  def self.get_latest_version(origin)
32
33
  latest_version = cached_version_list.lines.find { |l| l =~ /^#{origin} / }
33
34
  if latest_version
34
- latest_version = latest_version.split(' ').last.split(')').first
35
+ _name, compare, status = latest_version.chomp.split(' ', 3)
36
+ if ['!', '?'].include?(compare)
37
+ return nil
38
+ end
39
+ latest_version = status.split(' ').last.split(')').first
35
40
  return latest_version
36
41
  end
37
42
  nil
@@ -110,13 +115,16 @@ Puppet::Type.type(:package).provide :pkgng, :parent => Puppet::Provider::Package
110
115
  end
111
116
 
112
117
  if not source # install using default repo logic
113
- args = ['install', '-qy', installname]
118
+ args = ['install', '-qy']
114
119
  elsif source.scheme == 'urn' # install from repo named in URN
115
120
  tag = repo_tag_from_urn(source.to_s)
116
- args = ['install', '-qy', '-r', tag, installname]
121
+ args = ['install', '-qy', '-r', tag]
117
122
  else # add package located at URL
118
- args = ['add', '-q', source.to_s]
123
+ args = ['add', '-q']
124
+ installname = source.to_s
119
125
  end
126
+ args += install_options if @resource[:install_options]
127
+ args << installname
120
128
 
121
129
  pkg(args)
122
130
  end
@@ -158,4 +166,8 @@ Puppet::Type.type(:package).provide :pkgng, :parent => Puppet::Provider::Package
158
166
  @property_hash[:origin]
159
167
  end
160
168
 
169
+ def install_options
170
+ join_options(@resource[:install_options])
171
+ end
172
+
161
173
  end
@@ -1,5 +1,3 @@
1
- require 'puppet/provider/package/gem'
2
-
3
1
  Puppet::Type.type(:package).provide :puppet_gem, :parent => :gem do
4
2
  desc "Puppet Ruby Gem support. This provider is useful for managing
5
3
  gems needed by the ruby provided in the puppet-agent package."
@@ -14,4 +12,10 @@ Puppet::Type.type(:package).provide :puppet_gem, :parent => :gem do
14
12
  else
15
13
  commands :gemcmd => "/opt/puppetlabs/puppet/bin/gem"
16
14
  end
15
+
16
+ def uninstall
17
+ super
18
+ Puppet.debug("Invalidating rubygems cache after uninstalling gem '#{resource[:name]}'")
19
+ Puppet::Util::Autoload.gem_source.clear_paths
20
+ end
17
21
  end
@@ -1,13 +1,17 @@
1
1
  require 'puppet/provider/package'
2
+ require 'puppet/util/rpm_compare'
2
3
 
3
4
  # RPM packaging. Should work anywhere that has rpm installed.
4
5
  Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Provider::Package do
6
+ # provides Rpm parsing and comparison
7
+ include Puppet::Util::RpmCompare
8
+
5
9
  desc "RPM packaging support; should work anywhere with a working `rpm`
6
10
  binary.
7
11
 
8
12
  This provider supports the `install_options` and `uninstall_options`
9
13
  attributes, which allow command-line flags to be passed to rpm.
10
- These options should be specified as an array where each element is either a string or a hash."
14
+ These options should be specified as an array where each element is either a string or a hash."
11
15
 
12
16
  has_feature :versionable
13
17
  has_feature :install_options
@@ -23,31 +27,6 @@ These options should be specified as an array where each element is either a str
23
27
  self::NEVRA_FIELDS = [:name, :epoch, :version, :release, :arch]
24
28
  self::MULTIVERSION_SEPARATOR = "; "
25
29
 
26
- ARCH_LIST = [
27
- 'noarch',
28
- 'i386',
29
- 'i686',
30
- 'ppc',
31
- 'ppc64',
32
- 'armv3l',
33
- 'armv4b',
34
- 'armv4l',
35
- 'armv4tl',
36
- 'armv5tel',
37
- 'armv5tejl',
38
- 'armv6l',
39
- 'armv7l',
40
- 'm68kmint',
41
- 's390',
42
- 's390x',
43
- 'ia64',
44
- 'x86_64',
45
- 'sh3',
46
- 'sh4',
47
- ]
48
-
49
- ARCH_REGEX = Regexp.new(ARCH_LIST.join('|\.'))
50
-
51
30
  commands :rpm => "rpm"
52
31
 
53
32
  if command('rpm')
@@ -204,200 +183,14 @@ These options should be specified as an array where each element is either a str
204
183
  join_options(resource[:uninstall_options])
205
184
  end
206
185
 
207
- # This is an attempt at implementing RPM's
208
- # lib/rpmvercmp.c rpmvercmp(a, b) in Ruby.
209
- #
210
- # Some of the things in here look REALLY
211
- # UGLY and/or arbitrary. Our goal is to
212
- # match how RPM compares versions, quirks
213
- # and all.
214
- #
215
- # I've kept a lot of C-like string processing
216
- # in an effort to keep this as identical to RPM
217
- # as possible.
218
- #
219
- # returns 1 if str1 is newer than str2,
220
- # 0 if they are identical
221
- # -1 if str1 is older than str2
222
- def rpmvercmp(str1, str2)
223
- return 0 if str1 == str2
224
-
225
- front_strip_re = /^[^A-Za-z0-9~]+/
226
-
227
- while str1.length > 0 or str2.length > 0
228
- # trim anything that's in front_strip_re and != '~' off the beginning of each string
229
- str1 = str1.gsub(front_strip_re, '')
230
- str2 = str2.gsub(front_strip_re, '')
231
-
232
- # "handle the tilde separator, it sorts before everything else"
233
- if str1 =~ /^~/ && str2 =~ /^~/
234
- # if they both have ~, strip it
235
- str1 = str1[1..-1]
236
- str2 = str2[1..-1]
237
- next
238
- elsif str1 =~ /^~/
239
- return -1
240
- elsif str2 =~ /^~/
241
- return 1
242
- end
243
-
244
- break if str1.length == 0 or str2.length == 0
245
-
246
- # "grab first completely alpha or completely numeric segment"
247
- isnum = false
248
- # if the first char of str1 is a digit, grab the chunk of continuous digits from each string
249
- if str1 =~ /^[0-9]+/
250
- if str1 =~ /^[0-9]+/
251
- segment1 = $~.to_s
252
- str1 = $~.post_match
253
- else
254
- segment1 = ''
255
- end
256
- if str2 =~ /^[0-9]+/
257
- segment2 = $~.to_s
258
- str2 = $~.post_match
259
- else
260
- segment2 = ''
261
- end
262
- isnum = true
263
- # else grab the chunk of continuous alphas from each string (which may be '')
264
- else
265
- if str1 =~ /^[A-Za-z]+/
266
- segment1 = $~.to_s
267
- str1 = $~.post_match
268
- else
269
- segment1 = ''
270
- end
271
- if str2 =~ /^[A-Za-z]+/
272
- segment2 = $~.to_s
273
- str2 = $~.post_match
274
- else
275
- segment2 = ''
276
- end
277
- end
278
-
279
- # if the segments we just grabbed from the strings are different types (i.e. one numeric one alpha),
280
- # where alpha also includes ''; "numeric segments are always newer than alpha segments"
281
- if segment2.length == 0
282
- return 1 if isnum
283
- return -1
284
- end
285
-
286
- if isnum
287
- # "throw away any leading zeros - it's a number, right?"
288
- segment1 = segment1.gsub(/^0+/, '')
289
- segment2 = segment2.gsub(/^0+/, '')
290
- # "whichever number has more digits wins"
291
- return 1 if segment1.length > segment2.length
292
- return -1 if segment1.length < segment2.length
293
- end
294
-
295
- # "strcmp will return which one is greater - even if the two segments are alpha
296
- # or if they are numeric. don't return if they are equal because there might
297
- # be more segments to compare"
298
- rc = segment1 <=> segment2
299
- return rc if rc != 0
300
- end #end while loop
301
-
302
- # if we haven't returned anything yet, "whichever version still has characters left over wins"
303
- if str1.length > str2.length
304
- return 1
305
- elsif str1.length < str2.length
306
- return -1
307
- else
308
- return 0
309
- end
310
- end
311
-
312
186
  def insync?(is)
313
187
  return false if [:purged, :absent].include?(is)
314
188
  return false if is.include?(self.class::MULTIVERSION_SEPARATOR) && !@resource[:install_only]
315
189
 
316
190
  should = resource[:ensure]
317
191
  is.split(self.class::MULTIVERSION_SEPARATOR).any? do |version|
318
- 0 == self.rpm_compareEVR(rpm_parse_evr(should), rpm_parse_evr(version))
319
- end
320
- end
321
-
322
- # parse a rpm "version" specification
323
- # this re-implements rpm's
324
- # rpmUtils.miscutils.stringToVersion() in ruby
325
- def rpm_parse_evr(s)
326
- ei = s.index(':')
327
- if ei
328
- e = s[0,ei]
329
- s = s[ei+1,s.length]
330
- else
331
- e = nil
332
- end
333
- begin
334
- e = String(Integer(e))
335
- rescue
336
- # If there are non-digits in the epoch field, default to nil
337
- e = nil
338
- end
339
- ri = s.index('-')
340
- if ri
341
- v = s[0,ri]
342
- r = s[ri+1,s.length]
343
- arch = r.scan(ARCH_REGEX)[0]
344
- if arch
345
- a = arch.delete('.')
346
- r.gsub!(ARCH_REGEX, '')
347
- end
348
- else
349
- v = s
350
- r = nil
351
- end
352
- return { :epoch => e, :version => v, :release => r, :arch => a }
353
- end
354
-
355
- # how rpm compares two package versions:
356
- # rpmUtils.miscutils.compareEVR(), which massages data types and then calls
357
- # rpm.labelCompare(), found in rpm.git/python/header-py.c, which
358
- # sets epoch to 0 if null, then compares epoch, then ver, then rel
359
- # using compare_values() and returns the first non-0 result, else 0.
360
- # This function combines the logic of compareEVR() and labelCompare().
361
- #
362
- # "version_should" can be v, v-r, or e:v-r.
363
- # "version_is" will always be at least v-r, can be e:v-r
364
- def rpm_compareEVR(should_hash, is_hash)
365
- # pass on to rpm labelCompare
366
-
367
- if !should_hash[:epoch].nil?
368
- rc = compare_values(should_hash[:epoch], is_hash[:epoch])
369
- return rc unless rc == 0
370
- end
371
-
372
- rc = compare_values(should_hash[:version], is_hash[:version])
373
- return rc unless rc == 0
374
-
375
- # here is our special case, PUP-1244.
376
- # if should_hash[:release] is nil (not specified by the user),
377
- # and comparisons up to here are equal, return equal. We need to
378
- # evaluate to whatever level of detail the user specified, so we
379
- # don't end up upgrading or *downgrading* when not intended.
380
- #
381
- # This should NOT be triggered if we're trying to ensure latest.
382
- return 0 if should_hash[:release].nil?
383
-
384
- rc = compare_values(should_hash[:release], is_hash[:release])
385
-
386
- return rc
387
- end
388
-
389
- # this method is a native implementation of the
390
- # compare_values function in rpm's python bindings,
391
- # found in python/header-py.c, as used by rpm.
392
- def compare_values(s1, s2)
393
- if s1.nil? && s2.nil?
394
- return 0
395
- elsif ( not s1.nil? ) && s2.nil?
396
- return 1
397
- elsif s1.nil? && (not s2.nil?)
398
- return -1
192
+ 0 == rpm_compareEVR(should, version)
399
193
  end
400
- return rpmvercmp(s1, s2)
401
194
  end
402
195
 
403
196
  private
@@ -1,4 +1,11 @@
1
+ require 'puppet/util/package/version/range'
2
+ require 'puppet/util/package/version/rpm'
3
+ require 'puppet/util/rpm_compare'
4
+
1
5
  Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
6
+ # provides Rpm parsing and comparison
7
+ include Puppet::Util::RpmCompare
8
+
2
9
  desc "Support via `yum`.
3
10
 
4
11
  Using this provider's `uninstallable` feature will not remove dependent packages. To
@@ -10,6 +17,9 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
10
17
 
11
18
  has_feature :install_options, :versionable, :virtual_packages, :install_only
12
19
 
20
+ RPM_VERSION = Puppet::Util::Package::Version::Rpm
21
+ RPM_VERSION_RANGE = Puppet::Util::Package::Version::Range
22
+
13
23
  commands :cmd => "yum", :rpm => "rpm"
14
24
 
15
25
  if command('rpm')
@@ -25,6 +35,32 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
25
35
  defaultfor :operatingsystem => :amazon
26
36
  defaultfor :osfamily => :redhat, :operatingsystemmajrelease => (4..7).to_a
27
37
 
38
+ def insync?(is)
39
+ return false if [:purged, :absent].include?(is)
40
+ return false if is.include?(self.class::MULTIVERSION_SEPARATOR) && !@resource[:install_only]
41
+
42
+ should = @resource[:ensure]
43
+ if should.is_a?(String)
44
+ begin
45
+ should_version = RPM_VERSION_RANGE.parse(should, RPM_VERSION)
46
+ rescue RPM_VERSION_RANGE::ValidationFailure, RPM_VERSION::ValidationFailure
47
+ Puppet.debug("Cannot parse #{should} as a RPM version range")
48
+ return super
49
+ end
50
+
51
+ is.split(self.class::MULTIVERSION_SEPARATOR).any? do |version|
52
+ begin
53
+ is_version = RPM_VERSION.parse(version)
54
+ should_version.include?(is_version)
55
+ rescue RPM_VERSION::ValidationFailure
56
+ Puppet.debug("Cannot parse #{is} as a RPM version")
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ VERSION_REGEX = /^(?:(\d+):)?(\S+)-(\S+)$/
63
+
28
64
  def self.prefetch(packages)
29
65
  raise Puppet::Error, _("The yum provider can only be used as root") if Process.euid != 0
30
66
  super
@@ -86,23 +122,24 @@ defaultfor :osfamily => :redhat, :operatingsystemmajrelease => (4..7).to_a
86
122
  end
87
123
 
88
124
  def self.parse_updates(str)
89
- # Strip off all content before the first blank line
90
- body = str.partition(/^\s*\n/m).last
125
+ # Strip off all content that contains Obsoleting, Security: or Update
126
+ body = str.partition(/^(Obsoleting|Security:|Update)/).first
91
127
 
92
128
  updates = Hash.new { |h, k| h[k] = [] }
93
- body.split.each_slice(3) do |tuple|
94
- break if tuple[0] =~ /^(Obsoleting|Security:|Update)/
95
- break unless tuple[1] =~ /^(?:(\d+):)?(\S+)-(\S+)$/
96
- hash = update_to_hash(*tuple[0..1])
97
- # Create entries for both the package name without a version and a
98
- # version since yum considers those as mostly interchangeable.
99
- short_name = hash[:name]
100
- long_name = "#{hash[:name]}.#{hash[:arch]}"
101
-
102
- updates[short_name] << hash
103
- updates[long_name] << hash
104
- end
105
129
 
130
+ body.split(/^\s*\n/).each do |line|
131
+ line.split.each_slice(3) do |tuple|
132
+ next unless tuple[0].include?('.') && tuple[1] =~ VERSION_REGEX
133
+
134
+ hash = update_to_hash(*tuple[0..1])
135
+ # Create entries for both the package name without a version and a
136
+ # version since yum considers those as mostly interchangeable.
137
+ short_name = hash[:name]
138
+ long_name = "#{hash[:name]}.#{hash[:arch]}"
139
+ updates[short_name] << hash
140
+ updates[long_name] << hash
141
+ end
142
+ end
106
143
  updates
107
144
  end
108
145
 
@@ -117,7 +154,7 @@ defaultfor :osfamily => :redhat, :operatingsystemmajrelease => (4..7).to_a
117
154
  raise _("Failed to parse package name and architecture from '%{pkgname}'") % { pkgname: pkgname }
118
155
  end
119
156
 
120
- match = pkgversion.match(/^(?:(\d+):)?(\S+)-(\S+)$/)
157
+ match = pkgversion.match(VERSION_REGEX)
121
158
  epoch = match[1] || '0'
122
159
  version = match[2]
123
160
  release = match[3]
@@ -151,6 +188,41 @@ defaultfor :osfamily => :redhat, :operatingsystemmajrelease => (4..7).to_a
151
188
  'update'
152
189
  end
153
190
 
191
+ def best_version(should)
192
+ if should.is_a?(String)
193
+ begin
194
+ should_range = RPM_VERSION_RANGE.parse(should, RPM_VERSION)
195
+ rescue RPM_VERSION_RANGE::ValidationFailure, RPM_VERSION::ValidationFailure
196
+ Puppet.debug("Cannot parse #{should} as a RPM version range")
197
+ return should
198
+ end
199
+ sorted_versions = SortedSet.new
200
+ available_versions(@resource[:name]).each do |version|
201
+ begin
202
+ rpm_version = RPM_VERSION.parse(version)
203
+ sorted_versions << rpm_version if should_range.include?(rpm_version)
204
+ rescue RPM_VERSION::ValidationFailure
205
+ Puppet.debug("Cannot parse #{version} as a RPM version")
206
+ end
207
+ end
208
+
209
+ version = sorted_versions.entries.last
210
+
211
+ if version
212
+ version = version.to_s.sub(/^\d+:/, '')
213
+ return version
214
+ end
215
+
216
+ Puppet.debug("No available version for package #{@resource[:name]} is included in range #{should_range}")
217
+ should
218
+ end
219
+ end
220
+
221
+ def available_versions(package_name)
222
+ output = execute("yum list #{package_name} --showduplicates | sed -e '1,/Available Packages/ d' | awk '{print $2}'")
223
+ output.split("\n")
224
+ end
225
+
154
226
  def install
155
227
  wanted = @resource[:name]
156
228
  error_level = self.class.error_level
@@ -195,10 +267,11 @@ defaultfor :osfamily => :redhat, :operatingsystemmajrelease => (4..7).to_a
195
267
  self.debug "Installing directly from #{wanted}"
196
268
  else
197
269
  # No explicit source was specified, so add the package version
270
+ should = best_version(should)
198
271
  wanted += "-#{should}"
199
- if wanted.scan(ARCH_REGEX)
272
+ if wanted.scan(self.class::ARCH_REGEX)
200
273
  self.debug "Detected Arch argument in package! - Moving arch to end of version string"
201
- wanted.gsub!(/(.+)(#{ARCH_REGEX})(.+)/,'\1\3\2')
274
+ wanted.gsub!(/(.+)(#{self.class::ARCH_REGEX})(.+)/,'\1\3\2')
202
275
  end
203
276
  end
204
277
  current_package = self.query
@@ -206,10 +279,10 @@ defaultfor :osfamily => :redhat, :operatingsystemmajrelease => (4..7).to_a
206
279
  if @resource[:install_only]
207
280
  self.debug "Updating package #{@resource[:name]} from version #{current_package[:ensure]} to #{should} as install_only packages are never downgraded"
208
281
  operation = update_command
209
- elsif rpm_compareEVR(rpm_parse_evr(should), rpm_parse_evr(current_package[:ensure])) < 0
282
+ elsif rpm_compareEVR(should, current_package[:ensure]) < 0
210
283
  self.debug "Downgrading package #{@resource[:name]} from version #{current_package[:ensure]} to #{should}"
211
284
  operation = :downgrade
212
- elsif rpm_compareEVR(rpm_parse_evr(should), rpm_parse_evr(current_package[:ensure])) > 0
285
+ elsif rpm_compareEVR(should, current_package[:ensure]) > 0
213
286
  self.debug "Upgrading package #{@resource[:name]} from version #{current_package[:ensure]} to #{should}"
214
287
  operation = update_command
215
288
  end