facter 4.1.1 → 4.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +202 -0
  3. data/lib/facter.rb +11 -17
  4. data/lib/facter/config.rb +2 -0
  5. data/lib/facter/custom_facts/core/execution/posix.rb +2 -2
  6. data/lib/facter/custom_facts/core/execution/windows.rb +1 -1
  7. data/lib/facter/custom_facts/core/file_loader.rb +0 -1
  8. data/lib/facter/custom_facts/core/legacy_facter.rb +0 -2
  9. data/lib/facter/custom_facts/core/resolvable.rb +1 -1
  10. data/lib/facter/custom_facts/util/collection.rb +6 -4
  11. data/lib/facter/custom_facts/util/confine.rb +9 -3
  12. data/lib/facter/custom_facts/util/directory_loader.rb +19 -7
  13. data/lib/facter/custom_facts/util/fact.rb +12 -10
  14. data/lib/facter/custom_facts/util/loader.rb +5 -1
  15. data/lib/facter/custom_facts/util/parser.rb +8 -2
  16. data/lib/facter/custom_facts/util/resolution.rb +5 -1
  17. data/lib/facter/custom_facts/util/windows_root.rb +2 -1
  18. data/lib/facter/facts/freebsd/is_virtual.rb +1 -5
  19. data/lib/facter/facts/freebsd/virtual.rb +1 -2
  20. data/lib/facter/facts/linux/az_metadata.rb +1 -5
  21. data/lib/facter/facts/linux/cloud/provider.rb +1 -5
  22. data/lib/facter/facts/linux/ec2_metadata.rb +1 -5
  23. data/lib/facter/facts/linux/ec2_userdata.rb +1 -5
  24. data/lib/facter/facts/linux/hypervisors/xen.rb +1 -2
  25. data/lib/facter/facts/linux/is_virtual.rb +1 -5
  26. data/lib/facter/facts/linux/virtual.rb +1 -2
  27. data/lib/facter/facts/macosx/os/macosx/version.rb +6 -3
  28. data/lib/facter/facts/windows/az_metadata.rb +1 -1
  29. data/lib/facter/facts/windows/cloud/provider.rb +1 -1
  30. data/lib/facter/facts/windows/ec2_metadata.rb +1 -1
  31. data/lib/facter/facts/windows/ec2_userdata.rb +1 -1
  32. data/lib/facter/facts/windows/gce.rb +1 -1
  33. data/lib/facter/facts/windows/hypervisors/hyperv.rb +1 -1
  34. data/lib/facter/facts/windows/hypervisors/kvm.rb +2 -1
  35. data/lib/facter/facts/windows/hypervisors/virtualbox.rb +2 -2
  36. data/lib/facter/facts/windows/hypervisors/vmware.rb +1 -1
  37. data/lib/facter/facts/windows/hypervisors/xen.rb +3 -1
  38. data/lib/facter/facts/windows/is_virtual.rb +15 -0
  39. data/lib/facter/facts/windows/virtual.rb +15 -0
  40. data/lib/facter/framework/cli/cli.rb +13 -15
  41. data/lib/facter/framework/core/cache_manager.rb +2 -2
  42. data/lib/facter/framework/core/fact/external/external_fact_manager.rb +0 -1
  43. data/lib/facter/framework/core/fact/internal/internal_fact_manager.rb +39 -39
  44. data/lib/facter/framework/core/fact_filter.rb +4 -14
  45. data/lib/facter/framework/core/fact_loaders/fact_loader.rb +0 -1
  46. data/lib/facter/framework/core/fact_manager.rb +11 -0
  47. data/lib/facter/framework/core/file_loader.rb +1 -1
  48. data/lib/facter/framework/logging/logger.rb +61 -0
  49. data/lib/facter/framework/parsers/query_parser.rb +6 -16
  50. data/lib/facter/models/fact_collection.rb +20 -3
  51. data/lib/facter/models/resolved_fact.rb +2 -3
  52. data/lib/facter/models/searched_fact.rb +2 -3
  53. data/lib/facter/resolvers/ec2.rb +8 -1
  54. data/lib/facter/resolvers/linux/networking.rb +18 -1
  55. data/lib/facter/resolvers/lsb_release.rb +1 -2
  56. data/lib/facter/resolvers/mountpoints.rb +16 -8
  57. data/lib/facter/resolvers/networking.rb +3 -1
  58. data/lib/facter/resolvers/os_release.rb +7 -4
  59. data/lib/facter/resolvers/partitions.rb +1 -3
  60. data/lib/facter/resolvers/ruby.rb +1 -1
  61. data/lib/facter/resolvers/windows/ffi/identity_ffi.rb +5 -0
  62. data/lib/facter/resolvers/windows/ffi/kernel_ffi.rb +1 -1
  63. data/lib/facter/resolvers/windows/identity.rb +1 -6
  64. data/lib/facter/resolvers/windows/virtualization.rb +46 -44
  65. data/lib/facter/resolvers/xen.rb +6 -1
  66. data/lib/facter/util/facts/posix/virtual_detector.rb +74 -0
  67. data/lib/facter/util/linux/dhcp.rb +4 -1
  68. data/lib/facter/util/linux/if_inet6.rb +73 -0
  69. data/lib/facter/util/linux/socket_parser.rb +17 -2
  70. data/lib/facter/version.rb +1 -1
  71. metadata +48 -11
  72. data/lib/facter/custom_facts/core/logging.rb +0 -203
  73. data/lib/facter/facts/windows/virtualization/is_virtual.rb +0 -17
  74. data/lib/facter/facts/windows/virtualization/virtual.rb +0 -17
  75. data/lib/facter/framework/core/fact_augmenter.rb +0 -54
  76. data/lib/facter/util/facts/virtual_detector.rb +0 -83
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Facts
4
+ module Windows
5
+ class Virtual
6
+ FACT_NAME = 'virtual'
7
+
8
+ def call_the_resolver
9
+ fact_value = Facter::Resolvers::Windows::Virtualization.resolve(:virtual)
10
+
11
+ Facter::ResolvedFact.new(FACT_NAME, fact_value)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -97,6 +97,11 @@ module Facter
97
97
  type: :boolean,
98
98
  desc: 'Resolve facts sequentially'
99
99
 
100
+ class_option :puppet,
101
+ type: :boolean,
102
+ aliases: '-p',
103
+ desc: 'Load the Puppet libraries, thus allowing Facter to load Puppet-specific facts.'
104
+
100
105
  desc '--man', 'Display manual.', hide: true
101
106
  map ['--man'] => :man
102
107
  def man(*args)
@@ -111,6 +116,7 @@ module Facter
111
116
 
112
117
  desc 'query', 'Default method', hide: true
113
118
  def query(*args)
119
+ Facter.puppet_facts if options[:puppet]
114
120
  output, status = Facter.to_user_output(@options, *args)
115
121
  puts output
116
122
 
@@ -126,7 +132,7 @@ module Facter
126
132
  Facter.values(@options, args)
127
133
  end
128
134
 
129
- desc '--version, -v', 'Print the version', hide: true
135
+ desc '--version, -v', 'Print the version'
130
136
  map ['--version', '-v'] => :version
131
137
  def version(*_args)
132
138
  puts Facter::VERSION
@@ -156,19 +162,7 @@ module Facter
156
162
  puts cache_groups
157
163
  end
158
164
 
159
- desc '--puppet, -p', 'Load the Puppet libraries, thus allowing Facter to load Puppet-specific facts.'
160
- map ['--puppet', '-p'] => :puppet
161
- def puppet(*args)
162
- Facter.puppet_facts
163
-
164
- output, status = Facter.to_user_output(@options, *args)
165
- puts output
166
-
167
- status = 1 if Facter::Log.errors?
168
- exit status
169
- end
170
-
171
- desc 'help', 'Help for all arguments'
165
+ desc '--help, -h', 'Help for all arguments'
172
166
  def help(*args)
173
167
  help_string = +''
174
168
  help_string << help_header(args)
@@ -205,7 +199,11 @@ module Facter
205
199
  Cli.commands
206
200
  .select { |_k, command_class| command_class.instance_of?(Thor::Command) }
207
201
  .each do |_k, command|
208
- help_command_options << build_option(command['name'], [], command['description'])
202
+ help_command_options << build_option(
203
+ command['name'],
204
+ [command['usage'].split(',')[1]],
205
+ command['description']
206
+ )
209
207
  end
210
208
 
211
209
  help_command_options
@@ -123,7 +123,7 @@ cache_format_version is incorrect!")
123
123
  return unless data[searched_fact.name]
124
124
 
125
125
  [Facter::ResolvedFact.new(searched_fact.name, data[searched_fact.name], searched_fact.type,
126
- searched_fact.user_query, searched_fact.filter_tokens)]
126
+ searched_fact.user_query)]
127
127
  end
128
128
  end
129
129
 
@@ -133,7 +133,7 @@ cache_format_version is incorrect!")
133
133
  next if fact_name == 'cache_format_version'
134
134
 
135
135
  fact = Facter::ResolvedFact.new(fact_name, fact_value, searched_fact.type,
136
- searched_fact.user_query, searched_fact.filter_tokens)
136
+ searched_fact.user_query)
137
137
  fact.file = searched_fact.file
138
138
  facts << fact
139
139
  end
@@ -19,7 +19,6 @@ module Facter
19
19
  custom_facts.each do |custom_fact|
20
20
  fact = LegacyFacter[custom_fact.name]
21
21
  resolved_fact = ResolvedFact.new(custom_fact.name, fact.value, :custom)
22
- resolved_fact.filter_tokens = []
23
22
  resolved_fact.user_query = custom_fact.user_query
24
23
  resolved_fact.file = fact.options[:file]
25
24
 
@@ -2,20 +2,23 @@
2
2
 
3
3
  module Facter
4
4
  class InternalFactManager
5
- @@log = Facter::Log.new(self)
6
-
5
+ # resolves each SearchFact and filter out facts that do not match the given user query
6
+ # @param searched_facts [Array<Facter::SearchedFact>] array of searched facts
7
+ #
8
+ # @return [Array<Facter::ResolvedFact>]
9
+ #
10
+ # @api private
7
11
  def resolve_facts(searched_facts)
8
12
  internal_searched_facts = filter_internal_facts(searched_facts)
9
-
10
13
  resolved_facts = if Options[:sequential]
11
- @@log.debug('Resolving facts sequentially')
12
14
  resolve_sequentially(internal_searched_facts)
13
15
  else
14
- @@log.debug('Resolving fact in parallel')
15
- threads = start_threads(internal_searched_facts)
16
- join_threads(threads, internal_searched_facts)
16
+ resolve_in_parallel(internal_searched_facts)
17
17
  end
18
18
 
19
+ resolved_facts.flatten!
20
+ resolved_facts.compact!
21
+
19
22
  nil_resolved_facts = resolve_nil_facts(searched_facts)
20
23
 
21
24
  resolved_facts.concat(nil_resolved_facts)
@@ -27,6 +30,17 @@ module Facter
27
30
  searched_facts.select { |searched_fact| %i[core legacy].include? searched_fact.type }
28
31
  end
29
32
 
33
+ def valid_fact?(searched_fact, resolved_fact)
34
+ return if resolved_fact.value.nil?
35
+
36
+ searched_fact_name = searched_fact.name
37
+ if searched_fact_name.include?('.*')
38
+ resolved_fact.name.match(searched_fact_name)
39
+ else
40
+ resolved_fact.name == searched_fact_name
41
+ end
42
+ end
43
+
30
44
  def resolve_nil_facts(searched_facts)
31
45
  resolved_facts = []
32
46
  searched_facts.select { |fact| fact.type == :nil }.each do |fact|
@@ -37,49 +51,35 @@ module Facter
37
51
  end
38
52
 
39
53
  def resolve_sequentially(searched_facts)
40
- resolved_facts = []
41
-
42
- searched_facts
43
- .uniq { |searched_fact| searched_fact.fact_class.name }
44
- .each do |searched_fact|
45
- begin
46
- fact = CoreFact.new(searched_fact)
47
- fact_value = fact.create
48
- resolved_facts << fact_value unless fact_value.nil?
49
- rescue StandardError => e
50
- @@log.log_exception(e)
51
- end
52
- end
54
+ searched_facts.map! { |searched_fact| resolve_fact(searched_fact) }
55
+ end
53
56
 
54
- resolved_facts.flatten!
55
- FactAugmenter.augment_resolved_facts(searched_facts, resolved_facts)
57
+ def resolve_in_parallel(searched_facts)
58
+ searched_facts.map! do |searched_fact|
59
+ Thread.new { resolve_fact(searched_fact) }
60
+ end.map!(&:value)
56
61
  end
57
62
 
58
- def start_threads(searched_facts)
59
- # only resolve a fact once, even if multiple search facts depend on that fact
60
- searched_facts
61
- .uniq { |searched_fact| searched_fact.fact_class.name }
62
- .map do |searched_fact|
63
- Thread.new do
64
- resolve_fact(searched_fact)
63
+ def resolve_fact(searched_fact)
64
+ fact_value = core_fact(searched_fact)
65
+ Array(fact_value).map! do |resolved_fact|
66
+ if valid_fact?(searched_fact, resolved_fact)
67
+ resolved_fact.user_query = searched_fact.user_query
68
+ resolved_fact
65
69
  end
66
70
  end
67
71
  end
68
72
 
69
- def join_threads(threads, searched_facts)
70
- resolved_facts = threads.map(&:value)
71
- resolved_facts.compact!
72
- resolved_facts.flatten!
73
-
74
- FactAugmenter.augment_resolved_facts(searched_facts, resolved_facts)
75
- end
76
-
77
- def resolve_fact(searched_fact)
73
+ def core_fact(searched_fact)
78
74
  fact = CoreFact.new(searched_fact)
79
75
  fact.create
80
76
  rescue StandardError => e
81
- @@log.log_exception(e)
77
+ log.log_exception(e)
82
78
  nil
83
79
  end
80
+
81
+ def log
82
+ @log ||= Facter::Log.new(self)
83
+ end
84
84
  end
85
85
  end
@@ -1,21 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Facter
4
- # Filter inside value of a fact.
5
- # e.g. os.release.major is the user query, os.release is the fact
6
- # and major is the filter criteria inside tha fact
7
4
  class FactFilter
8
- def filter_facts!(searched_facts, user_query)
9
- filter_legacy_facts!(searched_facts) if user_query.empty?
10
- filter_blocked_legacy_facts!(searched_facts)
11
-
12
- searched_facts.each do |fact|
13
- fact.value = if fact.filter_tokens.any? && fact.value.respond_to?(:dig)
14
- fact.value.dig(*fact.filter_tokens)
15
- else
16
- fact.value
17
- end
18
- end
5
+ def filter_facts!(resolved_facts, user_query)
6
+ filter_legacy_facts!(resolved_facts) if user_query.empty?
7
+ filter_blocked_legacy_facts!(resolved_facts)
8
+ resolved_facts
19
9
  end
20
10
 
21
11
  private
@@ -29,7 +29,6 @@ module Facter
29
29
  end
30
30
 
31
31
  def load_internal_facts(user_query, options)
32
- @log.debug('Loading internal facts')
33
32
  internal_facts = []
34
33
  if user_query || options[:show_legacy]
35
34
  # if we have a user query, then we must search in core facts and legacy facts
@@ -13,6 +13,7 @@ module Facter
13
13
  end
14
14
 
15
15
  def resolve_facts(user_query = [])
16
+ log_resolving_method
16
17
  @options[:user_query] = user_query
17
18
  cache_manager = Facter::CacheManager.new
18
19
 
@@ -40,6 +41,7 @@ module Facter
40
41
  # - load all the core facts, external facts and env facts
41
42
  # - load all custom facts
42
43
  def resolve_fact(user_query)
44
+ log_resolving_method
43
45
  @options[:user_query] = user_query
44
46
  @log.debug("resolving fact with user_query: #{user_query}")
45
47
 
@@ -58,12 +60,21 @@ module Facter
58
60
  end
59
61
 
60
62
  def resolve_core(user_query = [], options = {})
63
+ log_resolving_method
61
64
  @cache_manager = CacheManager.new
62
65
  core_fact(user_query, options)
63
66
  end
64
67
 
65
68
  private
66
69
 
70
+ def log_resolving_method
71
+ if Options[:sequential]
72
+ @log.debugonce('Resolving facts sequentially')
73
+ else
74
+ @log.debugonce('Resolving fact in parallel')
75
+ end
76
+ end
77
+
67
78
  def core_fact(user_query, options)
68
79
  loaded_facts_hash = @fact_loader.load_internal_facts(user_query, options)
69
80
 
@@ -37,6 +37,7 @@ load_dir(['config'])
37
37
  load_dir(['util'])
38
38
  load_dir(%w[util resolvers])
39
39
  load_dir(%w[util facts])
40
+ load_dir(%w[util facts posix])
40
41
  load_dir(%w[util resolvers networking])
41
42
 
42
43
  load_dir(['resolvers'])
@@ -58,5 +59,4 @@ os_hierarchy.each { |operating_system| load_dir(['resolvers', operating_system.d
58
59
  require 'facter/custom_facts/core/legacy_facter'
59
60
  load_dir(%w[framework utils])
60
61
 
61
- require 'facter/framework/core/fact_augmenter'
62
62
  require 'facter/framework/parsers/query_parser'
@@ -15,8 +15,16 @@ module Facter
15
15
  @@logger = nil
16
16
  @@message_callback = nil
17
17
  @@has_errors = false
18
+ @@debug_messages = []
19
+ @@warn_messages = []
20
+ @@timing = false
18
21
 
19
22
  class << self
23
+ def clear_messages
24
+ @@debug_messages.clear
25
+ @@warn_messages.clear
26
+ end
27
+
20
28
  def on_message(&block)
21
29
  @@message_callback = block
22
30
  end
@@ -47,6 +55,41 @@ module Facter
47
55
  "[#{datetime}] #{severity} #{msg} \n"
48
56
  end
49
57
  end
58
+
59
+ # Print an exception message, and optionally a backtrace if trace is set
60
+
61
+ # Print timing information
62
+ #
63
+ # @param string [String] the time to print
64
+ # @return [void]
65
+ #
66
+ # @api private
67
+ def show_time(string)
68
+ return unless string && timing?
69
+
70
+ if @@message_callback
71
+ @@message_callback.call(:info, string)
72
+ else
73
+ warn("#{GREEN}#{string}#{RESET}")
74
+ end
75
+ end
76
+
77
+ # Enable or disable logging of timing information
78
+ #
79
+ # @param bool [true, false]
80
+ # @return [void]
81
+ #
82
+ # @api private
83
+ def timing(bool)
84
+ @@timing = bool
85
+ end
86
+
87
+ # Returns whether timing output is turned on
88
+ #
89
+ # @api private
90
+ def timing?
91
+ @@timing
92
+ end
50
93
  end
51
94
 
52
95
  def initialize(logged_class)
@@ -68,6 +111,16 @@ module Facter
68
111
  end
69
112
  end
70
113
 
114
+ def debugonce(msg)
115
+ return unless debugging_active?
116
+
117
+ message_string = msg.to_s
118
+ return if @@debug_messages.include? message_string
119
+
120
+ @@debug_messages << message_string
121
+ debug(message_string)
122
+ end
123
+
71
124
  def info(msg)
72
125
  if msg.nil? || msg.empty?
73
126
  empty_message_error(msg)
@@ -88,6 +141,14 @@ module Facter
88
141
  end
89
142
  end
90
143
 
144
+ def warnonce(message)
145
+ message_string = message.to_s
146
+ return if @@warn_messages.include? message_string
147
+
148
+ @@warn_messages << message_string
149
+ warn(message_string)
150
+ end
151
+
91
152
  def error(msg, colorize = false)
92
153
  @@has_errors = true
93
154
 
@@ -24,13 +24,11 @@ module Facter
24
24
  # Returns a list of SearchedFact objects that resolve the users query.
25
25
  def parse(query_list, loaded_fact)
26
26
  matched_facts = []
27
- @log.debug "User query is: #{query_list}"
28
27
  @query_list = query_list
29
28
 
30
29
  return no_user_query(loaded_fact) unless query_list.any?
31
30
 
32
31
  query_list.each do |query|
33
- @log.debug "Query is #{query}"
34
32
  found_facts = search_for_facts(query, loaded_fact)
35
33
  matched_facts << found_facts
36
34
  end
@@ -41,7 +39,7 @@ module Facter
41
39
  def no_user_query(loaded_facts)
42
40
  searched_facts = []
43
41
  loaded_facts.each do |loaded_fact|
44
- searched_facts << SearchedFact.new(loaded_fact.name, loaded_fact.klass, [], '', loaded_fact.type)
42
+ searched_facts << SearchedFact.new(loaded_fact.name, loaded_fact.klass, '', loaded_fact.type)
45
43
  end
46
44
  searched_facts
47
45
  end
@@ -59,13 +57,12 @@ module Facter
59
57
  return resolvable_fact_list if resolvable_fact_list.any?
60
58
  end
61
59
 
62
- resolvable_fact_list << SearchedFact.new(query, nil, [], query, :nil) if resolvable_fact_list.empty?
60
+ resolvable_fact_list << SearchedFact.new(query, nil, query, :nil) if resolvable_fact_list.empty?
63
61
 
64
62
  resolvable_fact_list
65
63
  end
66
64
 
67
65
  def get_facts_matching_tokens(query_tokens, query_token_range, loaded_fact_hash)
68
- @log.debug "Checking query tokens #{query_tokens[query_token_range].join('.')}"
69
66
  resolvable_fact_list = []
70
67
 
71
68
  loaded_fact_hash.each do |loaded_fact|
@@ -73,11 +70,11 @@ module Facter
73
70
 
74
71
  next unless found_fact?(loaded_fact.name, query_fact)
75
72
 
76
- searched_fact = construct_loaded_fact(query_tokens, query_token_range, loaded_fact)
73
+ searched_fact = construct_loaded_fact(query_tokens, loaded_fact)
77
74
  resolvable_fact_list << searched_fact
78
75
  end
79
76
 
80
- @log.debug "List of resolvable facts: #{resolvable_fact_list.inspect}"
77
+ @log.debug "List of resolvable facts: #{resolvable_fact_list.inspect}" if resolvable_fact_list.any?
81
78
  resolvable_fact_list
82
79
  end
83
80
 
@@ -93,23 +90,16 @@ module Facter
93
90
  true
94
91
  end
95
92
 
96
- def construct_loaded_fact(query_tokens, query_token_range, loaded_fact)
97
- filter_tokens = construct_filter_tokens(query_tokens, query_token_range)
93
+ def construct_loaded_fact(query_tokens, loaded_fact)
98
94
  user_query = @query_list.any? ? query_tokens.join('.') : ''
99
95
  fact_name = loaded_fact.name.to_s
100
96
  klass_name = loaded_fact.klass
101
97
  type = loaded_fact.type
102
- sf = SearchedFact.new(fact_name, klass_name, filter_tokens, user_query, type)
98
+ sf = SearchedFact.new(fact_name, klass_name, user_query, type)
103
99
  sf.file = loaded_fact.file
104
100
 
105
101
  sf
106
102
  end
107
-
108
- def construct_filter_tokens(query_tokens, query_token_range)
109
- query_tokens.drop(query_token_range.size).map do |token|
110
- token =~ /^[0-9]+$/ ? token.to_i : token
111
- end
112
- end
113
103
  end
114
104
  end
115
105
  end