facter 4.1.1 → 4.2.3

Sign up to get free protection for your applications and to get access to all the features.
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