rspec-puppet-facts 2.0.5 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,6 @@ module RspecPuppetFacts
2
2
  # This module contains the current version constant
3
3
  module Version
4
4
  # The current version of this gem
5
- STRING = '2.0.5'
5
+ STRING = '3.0.0'
6
6
  end
7
7
  end
@@ -2,6 +2,7 @@ require 'puppet'
2
2
  require 'facter'
3
3
  require 'facterdb'
4
4
  require 'json'
5
+ require 'deep_merge'
5
6
 
6
7
  # The purpose of this module is to simplify the Puppet
7
8
  # module's RSpec tests by looping through all supported
@@ -56,7 +57,7 @@ module RspecPuppetFacts
56
57
  #
57
58
  # @api private
58
59
  def on_supported_os_implementation(opts = {})
59
- unless (facterversion = opts[:facterversion]) =~ /\A\d+\.\d+(?:\.\d+)*\z/
60
+ unless /\A\d+\.\d+(?:\.\d+)*\z/.match?((facterversion = opts[:facterversion]))
60
61
  raise ArgumentError, ":facterversion must be in the format 'n.n' or " \
61
62
  "'n.n.n' (n is numeric), not '#{facterversion}'"
62
63
  end
@@ -68,19 +69,20 @@ module RspecPuppetFacts
68
69
  opts[:hardwaremodels].each do |hardwaremodel|
69
70
 
70
71
  os_release_filter = "/^#{Regexp.escape(operatingsystemmajrelease.split(' ')[0])}/"
71
- if os_sup['operatingsystem'] =~ /BSD/i
72
+ case os_sup['operatingsystem']
73
+ when /BSD/i
72
74
  hardwaremodel = 'amd64'
73
- elsif os_sup['operatingsystem'] =~ /Solaris/i
75
+ when /Solaris/i
74
76
  hardwaremodel = 'i86pc'
75
- elsif os_sup['operatingsystem'] =~ /AIX/i
77
+ when /AIX/i
76
78
  hardwaremodel = '/^IBM,.*/'
77
79
  os_release_filter = if operatingsystemmajrelease =~ /\A(\d+)\.(\d+)\Z/
78
80
  "/^#{$~[1]}#{$~[2]}00-/"
79
81
  else
80
82
  "/^#{operatingsystemmajrelease}-/"
81
83
  end
82
- elsif os_sup['operatingsystem'] =~ /Windows/i
83
- hardwaremodel = facterversion =~ /^[12]\./ ? 'x64' : 'x86_64'
84
+ when /Windows/i
85
+ hardwaremodel = /^[12]\./.match?(facterversion) ? 'x64' : 'x86_64'
84
86
  os_sup['operatingsystem'] = os_sup['operatingsystem'].downcase
85
87
  operatingsystemmajrelease = operatingsystemmajrelease[/\A(?:Server )?(.+)/i, 1]
86
88
 
@@ -90,7 +92,7 @@ module RspecPuppetFacts
90
92
  if operatingsystemmajrelease == '2016' && Puppet::Util::Package.versioncmp(facterversion, '3.4') < 0
91
93
  os_release_filter = '/^10\\.0\\./'
92
94
  end
93
- elsif os_sup['operatingsystem'] =~ /Amazon/i
95
+ when /Amazon/i
94
96
  # Tighten the regex for Amazon Linux 2 so that we don't pick up Amazon Linux 2016 or 2017 facts
95
97
  os_release_filter = "/^2$/" if operatingsystemmajrelease == '2'
96
98
  end
@@ -112,35 +114,33 @@ module RspecPuppetFacts
112
114
  end
113
115
  end
114
116
 
115
- facterversion_obj = Gem::Version.new(facterversion)
117
+ strict_requirement = RspecPuppetFacts::facter_version_to_strict_requirement(facterversion)
118
+
119
+ loose_requirement = RspecPuppetFacts::facter_version_to_loose_requirement(facterversion)
120
+ received_facts = []
116
121
 
117
122
  # FacterDB may have newer versions of facter data for which it contains a subset of all possible
118
123
  # facter data (see FacterDB 0.5.2 for Facter releases 3.8 and 3.9). In this situation we need to
119
124
  # cycle through and downgrade Facter versions per platform type until we find matching Facter data.
120
125
  filter.each do |filter_spec|
121
- facter_version_filter = RspecPuppetFacts.facter_version_to_filter(facterversion)
122
- db = FacterDB.get_facts(filter_spec.merge({ :facterversion => facter_version_filter }))
123
-
124
- if db.empty?
125
- if RspecPuppetFacts.spec_facts_strict?
126
- raise ArgumentError, "No facts were found in the FacterDB for Facter v#{facterversion} on #{filter_spec}, aborting"
127
- end
126
+ versions = FacterDB.get_facts(filter_spec).to_h { |facts| [Gem::Version.new(facts[:facterversion]), facts] }
128
127
 
129
- version = FacterDB.get_facts(filter_spec).map { |facts| Gem::Version.new(facts[:facterversion]) }.sort.reverse.detect { |v| v <= facterversion_obj }
128
+ version, facts = versions.select { |v, _f| strict_requirement =~ v }.max_by { |v, _f| v }
130
129
 
130
+ unless version
131
+ version, facts = versions.select { |v, _f| loose_requirement =~ v }.max_by { |v, _f| v } if loose_requirement
131
132
  next unless version
132
- version = version.to_s
133
- facter_version_filter = "/\\A#{Regexp.escape(version)}/"
134
133
 
135
- unless version == facterversion
136
- RspecPuppetFacts.warning "No facts were found in the FacterDB for Facter v#{facterversion} on #{filter_spec}, using v#{version} instead"
134
+ if RspecPuppetFacts.spec_facts_strict?
135
+ raise ArgumentError, "No facts were found in the FacterDB for Facter v#{facterversion} on #{filter_spec}, aborting"
137
136
  end
137
+
138
+ RspecPuppetFacts.warning "No facts were found in the FacterDB for Facter v#{facterversion} on #{filter_spec}, using v#{version} instead"
138
139
  end
139
140
 
140
- filter_spec[:facterversion] = facter_version_filter
141
+ received_facts << facts
141
142
  end
142
143
 
143
- received_facts = FacterDB::get_facts(filter)
144
144
  unless received_facts.any?
145
145
  RspecPuppetFacts.warning "No facts were found in the FacterDB for: #{filter.inspect}"
146
146
  return {}
@@ -178,8 +178,9 @@ module RspecPuppetFacts
178
178
  os_facts_hash
179
179
  end
180
180
 
181
+ # @api private
181
182
  def stringify_keys(hash)
182
- Hash[hash.collect { |k,v| [k.to_s, v.is_a?(Hash) ? stringify_keys(v) : v] }]
183
+ hash.to_h { |k, v| [k.to_s, v.is_a?(Hash) ? stringify_keys(v) : v] }
183
184
  end
184
185
 
185
186
  # Register a custom fact that will be included in the facts hash.
@@ -210,7 +211,8 @@ module RspecPuppetFacts
210
211
  # @api private
211
212
  def self.register_custom_fact(name, value, options)
212
213
  @custom_facts ||= {}
213
- @custom_facts[name.to_s] = {:options => options, :value => value}
214
+ name = RSpec.configuration.facterdb_string_keys ? name.to_s : name.to_sym
215
+ @custom_facts[name] = {:options => options, :value => value}
214
216
  end
215
217
 
216
218
  # Adds any custom facts according to the rules defined for the operating
@@ -226,7 +228,13 @@ module RspecPuppetFacts
226
228
  next if fact[:options][:confine] && !fact[:options][:confine].include?(os)
227
229
  next if fact[:options][:exclude] && fact[:options][:exclude].include?(os)
228
230
 
229
- facts[name] = fact[:value].respond_to?(:call) ? fact[:value].call(os, facts) : fact[:value]
231
+ value = fact[:value].respond_to?(:call) ? fact[:value].call(os, facts) : fact[:value]
232
+ # if merge_facts passed, merge supplied facts into facts hash
233
+ if fact[:options][:merge_facts]
234
+ facts.deep_merge!({name => value})
235
+ else
236
+ facts[name] = value
237
+ end
230
238
  end
231
239
 
232
240
  facts
@@ -352,13 +360,47 @@ module RspecPuppetFacts
352
360
  @metadata = nil
353
361
  end
354
362
 
355
- # Generates a JGrep statement expression for a specific facter version
356
- # @return [String] JGrep statement expression
357
- # @param version [String] the Facter version
363
+ # Construct the strict facter version requirement
364
+ # @return [Gem::Requirement] The version requirement to match
358
365
  # @api private
359
- def self.facter_version_to_filter(version)
360
- major, minor = version.split('.')
361
- "/\\A#{major}\\.#{minor}\\./"
366
+ def self.facter_version_to_strict_requirement(version)
367
+ Gem::Requirement.new(facter_version_to_strict_requirement_string(version))
368
+ end
369
+
370
+ # Construct the strict facter version requirement string
371
+ # @return [String] The version requirement to match
372
+ # @api private
373
+ def self.facter_version_to_strict_requirement_string(version)
374
+ if /\A[0-9]+(\.[0-9]+)*\Z/.match?(version)
375
+ # Interpret 3 as ~> 3.0
376
+ "~> #{version}.0"
377
+ else
378
+ version
379
+ end
380
+ end
381
+
382
+ # Construct the loose facter version requirement
383
+ # @return [Optional[Gem::Requirement]] The version requirement to match
384
+ # @api private
385
+ def self.facter_version_to_loose_requirement(version)
386
+ string = facter_version_to_loose_requirement_string(version)
387
+ Gem::Requirement.new(string) if string
388
+ end
389
+
390
+ # Construct the facter version requirement string
391
+ # @return [String] The version requirement to match
392
+ # @api private
393
+ def self.facter_version_to_loose_requirement_string(version)
394
+ if (m = /\A(?<major>[0-9]+)\.(?<minor>[0-9]+)(?:\.(?<patch>[0-9]+))?\Z/.match(version))
395
+ # Interpret 3.1 as < 3.2 and 3.2.1 as < 3.3
396
+ "< #{m[:major]}.#{m[:minor].to_i + 1}"
397
+ elsif /\A[0-9]+\Z/.match?(version)
398
+ # Interpret 3 as < 4
399
+ "< #{version.to_i + 1}"
400
+ else
401
+ # This would be the same as the strict requirement
402
+ nil
403
+ end
362
404
  end
363
405
 
364
406
  def self.facter_version_for_puppet_version(puppet_version)
@@ -13,18 +13,20 @@ Gem::Specification.new do |s|
13
13
  s.description = 'Contains facts from many Facter version on many Operating Systems'
14
14
  s.licenses = 'Apache-2.0'
15
15
 
16
- # see .travis.yml for the supported ruby versions
17
- s.required_ruby_version = '>= 2.4.0'
16
+ s.required_ruby_version = '>= 2.7.0'
18
17
 
19
18
  s.files = `git ls-files`.split("\n")
20
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
19
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
22
20
 
23
- s.add_development_dependency 'mime-types'
24
- s.add_development_dependency 'rake'
25
- s.add_development_dependency 'rspec'
26
- s.add_development_dependency 'yard'
27
- s.add_runtime_dependency 'puppet'
28
- s.add_runtime_dependency 'facter'
29
- s.add_runtime_dependency 'facterdb', '>= 0.5.0'
21
+ s.add_development_dependency 'mime-types', '~> 3.5', '>= 3.5.2'
22
+ s.add_development_dependency 'rake', '~> 13.1'
23
+ s.add_development_dependency 'rspec', '~> 3.12'
24
+ s.add_development_dependency 'yard', '~> 0.9.34'
25
+
26
+ s.add_development_dependency 'voxpupuli-rubocop', '~> 2.6.0'
27
+
28
+ s.add_runtime_dependency 'deep_merge', '~> 1.2'
29
+ s.add_runtime_dependency 'facter', '< 5'
30
+ s.add_runtime_dependency 'facterdb', '>= 0.5.0', '< 2'
31
+ s.add_runtime_dependency 'puppet', '>= 7', '< 9'
30
32
  end