puppet 5.3.4 → 5.3.5

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 (42) hide show
  1. data/CONTRIBUTING.md +15 -15
  2. data/Gemfile +3 -0
  3. data/README.md +11 -11
  4. data/Rakefile +7 -5
  5. data/ext/project_data.yaml +6 -4
  6. data/lib/puppet/application/agent.rb +1 -3
  7. data/lib/puppet/application/apply.rb +1 -3
  8. data/lib/puppet/application/cert.rb +4 -1
  9. data/lib/puppet/configurer.rb +17 -4
  10. data/lib/puppet/configurer/downloader_factory.rb +1 -1
  11. data/lib/puppet/defaults.rb +1 -1
  12. data/lib/puppet/environments.rb +1 -1
  13. data/lib/puppet/functions/strftime.rb +1 -1
  14. data/lib/puppet/indirector/file_content/http.rb +3 -1
  15. data/lib/puppet/indirector/indirection.rb +3 -3
  16. data/lib/puppet/indirector/request.rb +6 -2
  17. data/lib/puppet/module_tool/tar/mini.rb +2 -2
  18. data/lib/puppet/node.rb +4 -3
  19. data/lib/puppet/pops/evaluator/evaluator_impl.rb +1 -1
  20. data/lib/puppet/pops/resource/resource_type_impl.rb +1 -1
  21. data/lib/puppet/pops/types/tree_iterators.rb +5 -1
  22. data/lib/puppet/provider/package/dnf.rb +1 -1
  23. data/lib/puppet/provider/package/gem.rb +1 -1
  24. data/lib/puppet/type/tidy.rb +8 -1
  25. data/lib/puppet/util/http_proxy.rb +4 -2
  26. data/lib/puppet/version.rb +1 -1
  27. data/locales/ja/puppet.po +38 -38
  28. data/locales/puppet.pot +37 -37
  29. data/spec/integration/parser/pcore_resource_spec.rb +1 -1
  30. data/spec/unit/application/agent_spec.rb +0 -9
  31. data/spec/unit/application/apply_spec.rb +0 -9
  32. data/spec/unit/application/cert_spec.rb +28 -1
  33. data/spec/unit/configurer/downloader_factory_spec.rb +1 -1
  34. data/spec/unit/configurer_spec.rb +14 -0
  35. data/spec/unit/functions/strftime_spec.rb +2 -2
  36. data/spec/unit/functions/tree_each_spec.rb +49 -0
  37. data/spec/unit/indirector/indirection_spec.rb +24 -2
  38. data/spec/unit/node_spec.rb +9 -0
  39. data/spec/unit/provider/package/gem_spec.rb +10 -0
  40. data/spec/unit/type/tidy_spec.rb +14 -0
  41. data/spec/unit/util/http_proxy_spec.rb +20 -0
  42. metadata +3368 -3374
@@ -22,18 +22,17 @@ be added in modules. Exceptions would be things like new cross-OS providers
22
22
  and updates to existing core types.
23
23
 
24
24
  If you are unsure of whether your contribution should be implemented as a
25
- module or part of Puppet Core, you may visit
26
- [#puppet-dev on Freenode IRC](https://freenode.net) or ask on the
27
- [puppet-dev mailing list](https://groups.google.com/forum/#!forum/puppet-dev)
28
- for advice.
25
+ module or part of Puppet Core, you may visit [#puppet-dev on slack](https://puppetcommunity.slack.com/), or ask on
26
+ the [puppet-dev mailing list](https://groups.google.com/forum/#!forum/puppet-dev) for advice.
29
27
 
30
28
  ## Getting Started
31
29
 
32
30
  * Make sure you have a [Jira account](https://tickets.puppetlabs.com)
33
31
  * Make sure you have a [GitHub account](https://github.com/signup/free)
34
- * Submit a ticket for your issue, assuming one does not already exist.
35
- * Clearly describe the issue including steps to reproduce when it is a bug.
32
+ * Submit a Jira ticket for your issue if one does not already exist.
33
+ * Clearly describe the issue including steps to reproduce when it is a bug
36
34
  * Make sure you fill in the earliest version that you know has the issue.
35
+ * A ticket is not necessary for [trivial changes](https://docs.puppet.com/community/trivial_patch_exemption.html)
37
36
  * Fork the repository on GitHub
38
37
 
39
38
  ## Making Changes
@@ -45,7 +44,7 @@ for advice.
45
44
  * To quickly create a topic branch based on master; `git checkout -b
46
45
  fix/master/my_contribution master`. Please avoid working directly on the
47
46
  `master` branch.
48
- * Make commits of logical units.
47
+ * Make commits of logical and atomic units.
49
48
  * Check for unnecessary whitespace with `git diff --check` before committing.
50
49
  * Make sure your commit messages are in the proper format.
51
50
 
@@ -64,7 +63,10 @@ for advice.
64
63
  ````
65
64
 
66
65
  * Make sure you have added the necessary tests for your changes.
67
- * Run _all_ the tests to assure nothing else was accidentally broken.
66
+ * Run _all_ the tests to assure nothing else was accidentally broken. First
67
+ install all the test dependencies with `bundle install --path .bundle`. Then
68
+ either run all the tests serially with `bundle exec rspec spec` or in parallel
69
+ with `bundle exec rake parallel:spec[process_count]`
68
70
 
69
71
  ## Writing Translatable Code
70
72
 
@@ -85,15 +87,13 @@ user-facing strings are marked in new PRs before merging.
85
87
 
86
88
  ## Making Trivial Changes
87
89
 
88
- ### Documentation
89
-
90
- For changes of a trivial nature to comments and documentation, it is not
91
- always necessary to create a new ticket in Jira. In this case, it is
92
- appropriate to start the first line of a commit with '(doc)' instead of
93
- a ticket number.
90
+ For [changes of a trivial nature](https://docs.puppet.com/community/trivial_patch_exemption.html), it is not always necessary to create a new
91
+ ticket in Jira. In this case, it is appropriate to start the first line of a
92
+ commit with one of `(docs)`, `(maint)`, or `(packaging)` instead of a ticket
93
+ number.
94
94
 
95
95
  ````
96
- (doc) Add documentation commit example to CONTRIBUTING
96
+ (docs) Add documentation commit example to CONTRIBUTING
97
97
 
98
98
  There is no example for contributing a documentation commit
99
99
  to the Puppet repository. This is a problem because the contributor
data/Gemfile CHANGED
@@ -65,6 +65,9 @@ group(:development, :test) do
65
65
  gem 'rdoc', "~> 4.1", :platforms => [:ruby]
66
66
  gem 'yard'
67
67
 
68
+ # ronn is used for generating manpages.
69
+ gem 'ronn', '~> 0.7.3', :platforms => [:ruby]
70
+
68
71
  # webmock requires addressable as as of 2.5.0 addressable started
69
72
  # requiring the public_suffix gem which requires Ruby 2
70
73
  gem 'addressable', '< 2.5.0'
data/README.md CHANGED
@@ -12,41 +12,41 @@ Documentation
12
12
  -------------
13
13
 
14
14
  Documentation for Puppet and related projects can be found online at the
15
- [Puppet Docs site](https://docs.puppetlabs.com).
15
+ [Puppet Docs site](https://puppet.com/docs).
16
16
 
17
17
  HTTP API
18
18
  --------
19
- [HTTP API Index](https://docs.puppetlabs.com/puppet/latest/reference/http_api/http_api_index.html)
19
+ [HTTP API Index](https://puppet.com/docs/puppet/5.3/http_api/http_api_index.html)
20
20
 
21
21
  Installation
22
22
  ------------
23
23
 
24
- The best way to run Puppet is with [Puppet Enterprise](https://puppetlabs.com/puppet/puppet-enterprise),
24
+ The best way to run Puppet is with [Puppet Enterprise](https://puppet.com/puppet/puppet-enterprise),
25
25
  which also includes orchestration features, a web console, and professional support.
26
- [The PE documentation is available here.](https://docs.puppetlabs.com/pe/latest)
26
+ [The PE documentation is available here.](https://puppet.com/docs/pe/latest)
27
27
 
28
28
  To install an open source release of Puppet,
29
- [see the installation guide on the docs site.](https://docs.puppetlabs.com/puppet/latest/reference/install_pre.html)
29
+ [see the installation guide on the docs site.](http://puppet.com/docs/puppet/5.3/install_pre.html)
30
30
 
31
31
  If you need to run Puppet from source as a tester or developer,
32
- [see the running from source guide on the docs site.](https://docs.puppetlabs.com/guides/from_source.html)
32
+ [see the running from source guide on the docs site.](https://docs.puppet.com/puppet/3.8/from_source.html)
33
33
 
34
34
  Developing and Contributing
35
35
  ------
36
36
 
37
37
  We'd love to get contributions from you! For a quick guide to getting your
38
38
  system setup for developing take a look at our [Quickstart
39
- Guide](docs/quickstart.md). Once you are up and running, take a look at the
40
- [Contribution Documents](CONTRIBUTING.md) to see how to get your changes merged
39
+ Guide](https://github.com/puppetlabs/puppet/blob/master/docs/quickstart.md). Once you are up and running, take a look at the
40
+ [Contribution Documents](https://github.com/puppetlabs/puppet/blob/master/CONTRIBUTING.md) to see how to get your changes merged
41
41
  in.
42
42
 
43
43
  For more complete docs on developing with puppet you can take a look at the
44
- rest of the [developer documents](docs/index.md).
44
+ rest of the [developer documents](https://github.com/puppetlabs/puppet/blob/master/docs/index.md).
45
45
 
46
46
  License
47
47
  -------
48
48
 
49
- See [LICENSE](LICENSE) file.
49
+ See [LICENSE](https://github.com/puppetlabs/puppet/blob/master/LICENSE) file.
50
50
 
51
51
  Support
52
52
  -------
@@ -71,4 +71,4 @@ a best effort to backport that fix onto the latest Puppet 3 release.
71
71
  Long-term support, including security patches and bug fixes, is available for
72
72
  commercial customers. Please see the following page for more details:
73
73
 
74
- [Puppet Enterprise Support Lifecycle](https://puppetlabs.com/misc/puppet-enterprise-lifecycle)
74
+ [Puppet Enterprise Support Lifecycle](https://puppet.com/misc/puppet-enterprise-lifecycle)
data/Rakefile CHANGED
@@ -110,9 +110,11 @@ task(:commits) do
110
110
  end
111
111
  end
112
112
 
113
- begin
114
- spec = Gem::Specification.find_by_name 'gettext-setup'
115
- load "#{spec.gem_dir}/lib/tasks/gettext.rake"
116
- GettextSetup.initialize(File.absolute_path('locales', File.dirname(__FILE__)))
117
- rescue LoadError
113
+ if Rake.application.top_level_tasks.grep(/^gettext:/).any?
114
+ begin
115
+ spec = Gem::Specification.find_by_name 'gettext-setup'
116
+ load "#{spec.gem_dir}/lib/tasks/gettext.rake"
117
+ GettextSetup.initialize(File.absolute_path('locales', File.dirname(__FILE__)))
118
+ rescue LoadError
119
+ end
118
120
  end
@@ -17,11 +17,11 @@ gem_forge_project: 'puppet'
17
17
  gem_required_ruby_version: '>= 1.9.3'
18
18
  gem_required_rubygems_version: '> 1.3.1'
19
19
  gem_runtime_dependencies:
20
- facter: ['> 2.0', '< 4']
20
+ facter: ['> 2.0.1', '< 4']
21
21
  hiera: ['>= 3.2.1', '< 4']
22
22
  # PUP-7115 - return to a gem dependency in Puppet 5
23
23
  # semantic_puppet: ['>= 0.1.3', '< 2']
24
- gettext-setup: ['>= 0.10', '< 1']
24
+ fast_gettext: '~> 1.1.2'
25
25
  locale: '~> 2.1'
26
26
  gem_rdoc_options:
27
27
  - --title
@@ -36,7 +36,8 @@ gem_platform_dependencies:
36
36
  x86-mingw32:
37
37
  gem_runtime_dependencies:
38
38
  # Pinning versions that require native extensions
39
- ffi: '~> 1.9.6'
39
+ # ffi is pinned due to PUP-8438
40
+ ffi: '<= 1.9.18'
40
41
  # win32-xxxx gems are pinned due to PUP-6445
41
42
  win32-dir: '= 0.4.9'
42
43
  win32-process: '= 0.7.5'
@@ -46,7 +47,8 @@ gem_platform_dependencies:
46
47
  minitar: '~> 0.6.1'
47
48
  x64-mingw32:
48
49
  gem_runtime_dependencies:
49
- ffi: '~> 1.9.6'
50
+ # ffi is pinned due to PUP-8438
51
+ ffi: '<= 1.9.18'
50
52
  # win32-xxxx gems are pinned due to PUP-6445
51
53
  win32-dir: '= 0.4.9'
52
54
  win32-process: '= 0.7.5'
@@ -422,9 +422,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
422
422
  # we want the last report to be persisted locally
423
423
  Puppet::Transaction::Report.indirection.cache_class = :yaml
424
424
 
425
- if Puppet[:noop]
426
- Puppet::Resource::Catalog.indirection.cache_class = nil
427
- elsif Puppet[:catalog_cache_terminus]
425
+ if Puppet[:catalog_cache_terminus]
428
426
  Puppet::Resource::Catalog.indirection.cache_class = Puppet[:catalog_cache_terminus]
429
427
  end
430
428
 
@@ -322,9 +322,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
322
322
  Puppet.settings.use :main, :agent, :ssl
323
323
 
324
324
 
325
- if Puppet[:noop]
326
- Puppet::Resource::Catalog.indirection.cache_class = nil
327
- elsif Puppet[:catalog_cache_terminus]
325
+ if Puppet[:catalog_cache_terminus]
328
326
  Puppet::Resource::Catalog.indirection.cache_class = Puppet[:catalog_cache_terminus]
329
327
  end
330
328
 
@@ -268,7 +268,10 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
268
268
  hosts = command_line.args.collect { |h| h.downcase }
269
269
  end
270
270
  begin
271
- apply(@ca, :revoke, options.merge(:to => hosts)) if subcommand == :destroy
271
+ if subcommand == :destroy
272
+ signed_hosts = hosts - @ca.waiting?
273
+ apply(@ca, :revoke, options.merge(:to => signed_hosts))
274
+ end
272
275
  apply(@ca, subcommand, options.merge(:to => hosts, :digest => @digest))
273
276
  rescue => detail
274
277
  Puppet.log_exception(detail)
@@ -425,8 +425,13 @@ class Puppet::Configurer
425
425
  def retrieve_catalog_from_cache(query_options)
426
426
  result = nil
427
427
  @duration = thinmark do
428
- result = Puppet::Resource::Catalog.indirection.find(Puppet[:node_name_value],
429
- query_options.merge(:ignore_terminus => true, :environment => Puppet::Node::Environment.remote(@environment)))
428
+ result = Puppet::Resource::Catalog.indirection.find(
429
+ Puppet[:node_name_value],
430
+ query_options.merge(
431
+ :ignore_terminus => true,
432
+ :environment => Puppet::Node::Environment.remote(@environment)
433
+ )
434
+ )
430
435
  end
431
436
  result
432
437
  rescue => detail
@@ -437,8 +442,16 @@ class Puppet::Configurer
437
442
  def retrieve_new_catalog(query_options)
438
443
  result = nil
439
444
  @duration = thinmark do
440
- result = Puppet::Resource::Catalog.indirection.find(Puppet[:node_name_value],
441
- query_options.merge(:ignore_cache => true, :environment => Puppet::Node::Environment.remote(@environment), :fail_on_404 => true))
445
+ result = Puppet::Resource::Catalog.indirection.find(
446
+ Puppet[:node_name_value],
447
+ query_options.merge(
448
+ :ignore_cache => true,
449
+ # We never want to update the cached Catalog if we're running in noop mode.
450
+ :ignore_cache_save => Puppet[:noop],
451
+ :environment => Puppet::Node::Environment.remote(@environment),
452
+ :fail_on_404 => true
453
+ )
454
+ )
442
455
  end
443
456
  result
444
457
  rescue StandardError => detail
@@ -37,7 +37,7 @@ class Puppet::Configurer::DownloaderFactory
37
37
  "locales",
38
38
  Puppet[:localedest],
39
39
  Puppet[:localesource],
40
- Puppet[:pluginsignore] + " config.yaml",
40
+ Puppet[:pluginsignore] + " *.pot config.yaml",
41
41
  environment
42
42
  )
43
43
  end
@@ -1791,7 +1791,7 @@ EOT
1791
1791
  }
1792
1792
  },
1793
1793
  :pluginsignore => {
1794
- :default => ".svn CVS .git .hg *.pot",
1794
+ :default => ".svn CVS .git .hg",
1795
1795
  :desc => "What files to ignore when pulling down plugins.",
1796
1796
  }
1797
1797
  )
@@ -297,7 +297,7 @@ module Puppet::Environments
297
297
  end
298
298
 
299
299
  # Returns the end of time (the next Mesoamerican Long Count cycle-end after 2012 (5125+2012) = 7137,
300
- # of for a 32 bit machine using Ruby < 1.9.3, the year 2038.
300
+ # or for a 32 bit machine using Ruby < 1.9.3, the year 2038.
301
301
  def self.end_of_time
302
302
  begin
303
303
  Time.gm(7137)
@@ -36,7 +36,7 @@ Puppet::Functions.create_function(:strftime) do
36
36
  line = nil
37
37
  end
38
38
  Puppet.warn_once('deprecations', 'legacy#strftime',
39
- _('The argument signature (String format, [String timezone]) is deprecated for #strfime. See #strftime documentation and Timespan type for more info'),
39
+ _('The argument signature (String format, [String timezone]) is deprecated for #strftime. See #strftime documentation and Timespan type for more info'),
40
40
  file, line)
41
41
  Puppet::Pops::Time::Timestamp.format_time(format, Time.now.utc, timezone)
42
42
  end
@@ -1,15 +1,17 @@
1
1
  require 'puppet/file_serving/metadata'
2
2
  require 'puppet/indirector/generic_http'
3
+ require 'puppet/network/http'
3
4
 
4
5
  class Puppet::Indirector::FileContent::Http < Puppet::Indirector::GenericHttp
5
6
  desc "Retrieve file contents from a remote HTTP server."
6
7
 
7
8
  include Puppet::FileServing::TerminusHelper
9
+ include Puppet::Network::HTTP::Compression.module
8
10
 
9
11
  @http_method = :get
10
12
 
11
13
  def find(request)
12
14
  response = super
13
- model.from_binary(response.body)
15
+ model.from_binary(uncompress_body(response))
14
16
  end
15
17
  end
@@ -165,7 +165,7 @@ class Puppet::Indirector::Indirection
165
165
  def expire(key, options={})
166
166
  request = request(:expire, key, nil, options)
167
167
 
168
- return nil unless cache?
168
+ return nil unless cache? && !request.ignore_cache_save?
169
169
 
170
170
  return nil unless instance = cache.find(request(:find, key, nil, options))
171
171
 
@@ -198,7 +198,7 @@ class Puppet::Indirector::Indirection
198
198
  result = terminus.find(request)
199
199
  if not result.nil?
200
200
  result.expiration ||= self.expiration if result.respond_to?(:expiration)
201
- if cache?
201
+ if cache? && !request.ignore_cache_save?
202
202
  Puppet.info _("Caching %{indirection} for %{request}") % { indirection: self.name, request: request.key }
203
203
  begin
204
204
  cache.save request(:save, key, result, options)
@@ -289,7 +289,7 @@ class Puppet::Indirector::Indirection
289
289
  result = terminus.save(request)
290
290
 
291
291
  # If caching is enabled, save our document there
292
- cache.save(request) if cache?
292
+ cache.save(request) if cache? && !request.ignore_cache_save?
293
293
 
294
294
  result
295
295
  end
@@ -10,7 +10,7 @@ require 'puppet/util/psych_support'
10
10
  class Puppet::Indirector::Request
11
11
  include Puppet::Util::PsychSupport
12
12
 
13
- attr_accessor :key, :method, :options, :instance, :node, :ip, :authenticated, :ignore_cache, :ignore_terminus
13
+ attr_accessor :key, :method, :options, :instance, :node, :ip, :authenticated, :ignore_cache, :ignore_cache_save, :ignore_terminus
14
14
 
15
15
  attr_accessor :server, :port, :uri, :protocol
16
16
 
@@ -18,7 +18,7 @@ class Puppet::Indirector::Request
18
18
 
19
19
  # trusted_information is specifically left out because we can't serialize it
20
20
  # and keep it "trusted"
21
- OPTION_ATTRIBUTES = [:ip, :node, :authenticated, :ignore_terminus, :ignore_cache, :instance, :environment]
21
+ OPTION_ATTRIBUTES = [:ip, :node, :authenticated, :ignore_terminus, :ignore_cache, :ignore_cache_save, :instance, :environment]
22
22
 
23
23
  # Is this an authenticated request?
24
24
  def authenticated?
@@ -50,6 +50,10 @@ class Puppet::Indirector::Request
50
50
  ignore_cache
51
51
  end
52
52
 
53
+ def ignore_cache_save?
54
+ ignore_cache_save
55
+ end
56
+
53
57
  def ignore_terminus?
54
58
  ignore_terminus
55
59
  end
@@ -42,7 +42,7 @@ class Puppet::ModuleTool::Tar::Mini
42
42
  stats[:mode] = EXECUTABLE
43
43
  elsif stats.key?(:entry)
44
44
  old_mode = stats[:entry].instance_variable_get(:@mode)
45
- if old_mode.is_a?(Fixnum)
45
+ if old_mode.is_a?(Integer)
46
46
  stats[:entry].instance_variable_set(:@mode, EXECUTABLE)
47
47
  end
48
48
  end
@@ -61,7 +61,7 @@ class Puppet::ModuleTool::Tar::Mini
61
61
  elsif stats.key?(:entry)
62
62
  old_mode = stats[:entry].instance_variable_get(:@mode)
63
63
  # If the user can execute the file, set 0755, otherwise 0644.
64
- if old_mode.is_a?(Fixnum)
64
+ if old_mode.is_a?(Integer)
65
65
  new_mode = sanitized_mode(old_mode)
66
66
  stats[:entry].instance_variable_set(:@mode, new_mode)
67
67
  end
@@ -28,9 +28,10 @@ class Puppet::Node
28
28
  @classes = data['classes'] || []
29
29
  @parameters = data['parameters'] || {}
30
30
  env_name = data['environment'] || @parameters[ENVIRONMENT]
31
- env_name = env_name.intern unless env_name.nil?
32
- @environment_name = env_name
33
- self.environment = env_name
31
+ unless env_name.nil?
32
+ @parameters[ENVIRONMENT] = env_name
33
+ @environment_name = env_name.intern
34
+ end
34
35
  end
35
36
 
36
37
  def self.from_data_hash(data)
@@ -330,7 +330,7 @@ class EvaluatorImpl
330
330
  candidate
331
331
  when Hash
332
332
  candidate.to_a
333
- when Puppet::Pops::Types::Iterator
333
+ when Puppet::Pops::Types::Iterable
334
334
  candidate.to_a
335
335
  else
336
336
  # turns anything else into an array (so result can be unfolded)
@@ -149,7 +149,7 @@ class ResourceTypeImpl
149
149
  # Here it is silently ignored.
150
150
  nil
151
151
  when 1
152
- if @title_pattners_hash.nil?
152
+ if @title_patterns_hash.nil?
153
153
  [ [ /(.*)/m, [ [@key_attributes.first] ] ] ]
154
154
  else
155
155
  # TechDebt: The case of having one namevar and an empty title patterns is unspecified behavior in puppet.
@@ -67,7 +67,7 @@ class TreeIterator
67
67
  false
68
68
  end
69
69
 
70
- def to_array
70
+ def to_a
71
71
  result = []
72
72
  loop do
73
73
  result << self.next
@@ -75,6 +75,10 @@ class TreeIterator
75
75
  result
76
76
  end
77
77
 
78
+ def to_array
79
+ to_a
80
+ end
81
+
78
82
  def reverse_each(&block)
79
83
  r = Iterator.new(PAnyType::DEFAULT, to_array.reverse_each)
80
84
  block_given? ? r.each(&block) : r
@@ -28,7 +28,7 @@ Puppet::Type.type(:package).provide :dnf, :parent => :yum do
28
28
  end
29
29
  end
30
30
 
31
- defaultfor :operatingsystem => :fedora, :operatingsystemmajrelease => ['22', '23', '24', '25']
31
+ defaultfor :operatingsystem => :fedora, :operatingsystemmajrelease => (22..30).to_a
32
32
 
33
33
  def self.update_command
34
34
  # In DNF, update is deprecated for upgrade