facter 4.0.39 → 4.0.44

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/bin/facter +3 -4
  3. data/lib/facter.rb +107 -28
  4. data/lib/facter/config.rb +354 -0
  5. data/lib/facter/custom_facts/core/aggregate.rb +51 -17
  6. data/lib/facter/custom_facts/core/execution.rb +27 -35
  7. data/lib/facter/custom_facts/core/execution/base.rb +13 -7
  8. data/lib/facter/custom_facts/util/directory_loader.rb +1 -1
  9. data/lib/facter/custom_facts/util/fact.rb +1 -1
  10. data/lib/facter/custom_facts/util/resolution.rb +40 -11
  11. data/lib/facter/facts/aix/disks.rb +1 -1
  12. data/lib/facter/facts/linux/ec2_metadata.rb +5 -29
  13. data/lib/facter/facts/linux/ec2_userdata.rb +5 -27
  14. data/lib/facter/facts/linux/is_virtual.rb +7 -46
  15. data/lib/facter/facts/linux/virtual.rb +3 -58
  16. data/lib/facter/facts/rhel/os/release.rb +1 -1
  17. data/lib/facter/facts/solaris/disks.rb +1 -1
  18. data/lib/facter/facts/solaris/zones.rb +1 -1
  19. data/lib/facter/facts_utils/virtual_detector.rb +78 -0
  20. data/lib/facter/framework/benchmarking/timer.rb +4 -2
  21. data/lib/facter/framework/cli/cli.rb +83 -36
  22. data/lib/facter/framework/cli/cli_launcher.rb +34 -38
  23. data/lib/facter/framework/config/fact_groups.rb +41 -7
  24. data/lib/facter/framework/core/cache_manager.rb +43 -23
  25. data/lib/facter/framework/core/fact_loaders/fact_loader.rb +14 -11
  26. data/lib/facter/framework/core/options/config_file_options.rb +5 -3
  27. data/lib/facter/framework/core/options/option_store.rb +60 -27
  28. data/lib/facter/framework/detector/os_hierarchy.rb +5 -9
  29. data/lib/facter/framework/logging/logger.rb +1 -5
  30. data/lib/facter/resolvers/aix/architecture_resolver.rb +15 -1
  31. data/lib/facter/resolvers/aix/os_level.rb +1 -1
  32. data/lib/facter/resolvers/augeas_resolver.rb +7 -1
  33. data/lib/facter/resolvers/bsd/processors.rb +11 -7
  34. data/lib/facter/resolvers/disk_resolver.rb +11 -3
  35. data/lib/facter/resolvers/dmi_decode.rb +1 -0
  36. data/lib/facter/resolvers/dmi_resolver.rb +2 -2
  37. data/lib/facter/resolvers/freebsd/geom_resolver.rb +12 -20
  38. data/lib/facter/resolvers/freebsd/processors.rb +11 -7
  39. data/lib/facter/resolvers/memory_resolver.rb +12 -14
  40. data/lib/facter/resolvers/mountpoints_resolver.rb +50 -22
  41. data/lib/facter/resolvers/networking_linux_resolver.rb +10 -5
  42. data/lib/facter/resolvers/partitions.rb +60 -57
  43. data/lib/facter/resolvers/processors_resolver.rb +5 -1
  44. data/lib/facter/resolvers/solaris/dmi.rb +2 -0
  45. data/lib/facter/resolvers/solaris/mountpoints.rb +60 -0
  46. data/lib/facter/resolvers/solaris/networking.rb +1 -2
  47. data/lib/facter/resolvers/solaris/os_release.rb +4 -3
  48. data/lib/facter/resolvers/ssh_resolver.rb +4 -4
  49. data/lib/facter/version.rb +1 -1
  50. metadata +5 -4
  51. data/lib/facter/fact_groups.conf +0 -308
  52. data/lib/facter/os_hierarchy.json +0 -36
@@ -1,59 +1,55 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'thor'
5
4
  require 'facter/framework/logging/logger.rb'
6
5
  Facter::Log.output(STDERR)
7
6
  require 'facter'
8
7
  require 'facter/framework/cli/cli'
9
8
 
10
9
  class CliLauncher
11
- def initialize(args)
12
- @args = args
13
- end
14
-
15
- def validate_options
16
- Facter::OptionsValidator.validate(@args)
17
- end
10
+ class << self
11
+ def prepare_arguments(args, task = Facter::Cli.default_task)
12
+ args.unshift(task) unless
13
+ check_if_arguments_is_known(Facter::Cli.all_tasks, args) ||
14
+ check_if_arguments_is_known(Facter::Cli.instance_variable_get(:@map), args) ||
15
+ !task
16
+
17
+ reorder_program_arguments(args)
18
+ end
18
19
 
19
- def prepare_arguments
20
- @args.unshift(Facter::Cli.default_task) unless
21
- check_if_arguments_is_known(Facter::Cli.all_tasks, @args) ||
22
- check_if_arguments_is_known(Facter::Cli.instance_variable_get(:@map), @args)
20
+ def start(args)
21
+ # stop parsing arguments if we don't recognize them
22
+ Thor.check_unknown_options!
23
+ Facter::Cli.start(args, debug: true)
24
+ rescue Thor::UnknownArgumentError => e
25
+ Facter::OptionsValidator.write_error_and_exit("unrecognised option '#{e.unknown.first}'")
26
+ end
23
27
 
24
- @args = reorder_program_arguments(@args)
25
- end
28
+ private
26
29
 
27
- def start
28
- Facter::Cli.start(@args, debug: true)
29
- rescue Thor::UnknownArgumentError => e
30
- Facter::OptionsValidator.write_error_and_exit("unrecognised option '#{e.unknown.first}'")
31
- end
32
-
33
- private
30
+ def check_if_arguments_is_known(known_arguments, program_arguments)
31
+ program_arguments.each do |argument|
32
+ return true if known_arguments.key?(argument)
33
+ end
34
34
 
35
- def check_if_arguments_is_known(known_arguments, program_arguments)
36
- program_arguments.each do |argument|
37
- return true if known_arguments.key?(argument)
35
+ false
38
36
  end
39
37
 
40
- false
41
- end
42
-
43
- def reorder_program_arguments(program_arguments)
44
- priority_arguments = Facter::Cli.instance_variable_get(:@map)
38
+ def reorder_program_arguments(program_arguments)
39
+ priority_arguments = Facter::Cli.instance_variable_get(:@map)
45
40
 
46
- priority_args = []
47
- normal_args = []
41
+ priority_args = []
42
+ normal_args = []
48
43
 
49
- program_arguments.each do |argument|
50
- if priority_arguments.include?(argument)
51
- priority_args << argument
52
- else
53
- normal_args << argument
44
+ program_arguments.each do |argument|
45
+ if priority_arguments.include?(argument)
46
+ priority_args << argument
47
+ else
48
+ normal_args << argument
49
+ end
54
50
  end
55
- end
56
51
 
57
- priority_args.concat(normal_args)
52
+ priority_args.concat(normal_args)
53
+ end
58
54
  end
59
55
  end
@@ -1,19 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'facter/config'
4
+
3
5
  module Facter
4
6
  class FactGroups
5
- attr_reader :groups, :block_list
7
+ attr_reader :groups, :block_list, :facts_ttls
6
8
 
7
9
  @groups_ttls = []
8
10
 
9
11
  STRING_TO_SECONDS = { 'seconds' => 1, 'minutes' => 60, 'hours' => 3600, 'days' => 3600 * 24 }.freeze
10
12
 
11
- def initialize(group_list_path = nil)
12
- default_path = File.join(File.dirname(__FILE__), '../../fact_groups.conf')
13
- @groups_file_path = group_list_path || default_path
14
- @groups ||= File.readable?(@groups_file_path) ? Hocon.load(@groups_file_path) : {}
13
+ def initialize
14
+ @groups = Facter::Config::FACT_GROUPS.dup
15
15
  load_groups
16
16
  load_groups_from_options
17
+ load_facts_ttls
18
+
19
+ # Reverse sort facts so that children have precedence when caching. eg: os.macosx vs os
20
+ @facts_ttls = @facts_ttls.sort.reverse.to_h
17
21
  end
18
22
 
19
23
  # Breakes down blocked groups in blocked facts
@@ -31,6 +35,9 @@ module Facter
31
35
 
32
36
  # Get the group name a fact is part of
33
37
  def get_fact_group(fact_name)
38
+ fact = get_fact(fact_name)
39
+ return fact[:group] if fact
40
+
34
41
  @groups.detect { |k, v| break k if Array(v).find { |f| fact_name =~ /^#{f}.*/ } }
35
42
  end
36
43
 
@@ -41,6 +48,15 @@ module Facter
41
48
  ttls_to_seconds(ttls[group_name])
42
49
  end
43
50
 
51
+ def get_fact(fact_name)
52
+ return @facts_ttls[fact_name] if @facts_ttls[fact_name]
53
+
54
+ result = @facts_ttls.select { |name, fact| break fact if fact_name =~ /^#{name}\..*/ }
55
+ return nil if result == {}
56
+
57
+ result
58
+ end
59
+
44
60
  private
45
61
 
46
62
  def load_groups_from_options
@@ -55,10 +71,28 @@ module Facter
55
71
  end
56
72
  end
57
73
 
74
+ def load_facts_ttls
75
+ @facts_ttls ||= {}
76
+ return if @groups_ttls == []
77
+
78
+ @groups_ttls.reduce(:merge).each do |group, ttls|
79
+ ttls = ttls_to_seconds(ttls)
80
+ if @groups[group]
81
+ @groups[group].each do |fact|
82
+ if (@facts_ttls[fact] && @facts_ttls[fact][:ttls] < ttls) || @facts_ttls[fact].nil?
83
+ @facts_ttls[fact] = { ttls: ttls, group: group }
84
+ end
85
+ end
86
+ else
87
+ @facts_ttls[group] = { ttls: ttls, group: group }
88
+ end
89
+ end
90
+ end
91
+
58
92
  def load_groups
59
93
  config = ConfigReader.init(Options[:config])
60
- @block_list = config.block_list || {}
61
- @groups_ttls = config.ttls || {}
94
+ @block_list = config.block_list || []
95
+ @groups_ttls = config.ttls || []
62
96
  @groups.merge!(config.fact_groups) if config.fact_groups
63
97
  end
64
98
 
@@ -40,31 +40,47 @@ module Facter
40
40
  end
41
41
  end
42
42
 
43
- def group_cached?(group_name)
44
- cached = @fact_groups.get_group_ttls(group_name) ? true : false
45
- delete_cache(group_name) unless cached
43
+ def fact_cache_enabled?(fact_name)
44
+ fact = @fact_groups.get_fact(fact_name)
45
+ cached = if fact
46
+ !fact[:ttls].nil?
47
+ else
48
+ false
49
+ end
50
+
51
+ fact_group = @fact_groups.get_fact_group(fact_name)
52
+ delete_cache(fact_group) if fact_group && !cached
46
53
  cached
47
54
  end
48
55
 
49
56
  private
50
57
 
51
58
  def resolve_fact(searched_fact)
52
- group_name = if searched_fact.file
53
- searched_fact.name
54
- else
55
- @fact_groups.get_fact_group(searched_fact.name)
56
- end
59
+ fact_name = if searched_fact.file
60
+ File.basename(searched_fact.file)
61
+ else
62
+ searched_fact.name
63
+ end
57
64
 
58
- return unless group_name
65
+ return unless fact_cache_enabled?(fact_name)
59
66
 
60
- return unless group_cached?(group_name)
67
+ fact = @fact_groups.get_fact(fact_name)
61
68
 
62
- return unless check_ttls?(group_name)
69
+ return unless fact
63
70
 
64
- data = read_group_json(group_name)
71
+ return unless check_ttls?(fact[:group], fact[:ttls])
72
+
73
+ read_fact(searched_fact, fact[:group])
74
+ end
75
+
76
+ def read_fact(searched_fact, fact_group)
77
+ data = nil
78
+ Facter::Framework::Benchmarking::Timer.measure(searched_fact.name, 'cached') do
79
+ data = read_group_json(fact_group)
80
+ end
65
81
  return unless data
66
82
 
67
- @log.debug("loading cached values for #{group_name} facts")
83
+ @log.debug("loading cached values for #{searched_fact.name} facts")
68
84
 
69
85
  create_facts(searched_fact, data)
70
86
  end
@@ -86,14 +102,17 @@ module Facter
86
102
  end
87
103
 
88
104
  def cache_fact(fact)
89
- group_name = if fact.file
90
- File.basename(fact.file)
91
- else
92
- @fact_groups.get_fact_group(fact.name)
93
- end
105
+ fact_name = if fact.file
106
+ File.basename(fact.file)
107
+ else
108
+ fact.name
109
+ end
110
+
111
+ group_name = @fact_groups.get_fact_group(fact_name)
112
+
94
113
  return if !group_name || fact.value.nil?
95
114
 
96
- return unless group_cached?(group_name)
115
+ return unless fact_cache_enabled?(fact_name)
97
116
 
98
117
  @groups[group_name] ||= {}
99
118
  @groups[group_name][fact.name] = fact.value
@@ -106,10 +125,12 @@ module Facter
106
125
  end
107
126
 
108
127
  @groups.each do |group_name, data|
109
- next unless check_ttls?(group_name)
128
+ next unless check_ttls?(group_name, @fact_groups.get_group_ttls(group_name))
110
129
 
111
- @log.debug("caching values for #{group_name} facts")
112
130
  cache_file_name = File.join(@cache_dir, group_name)
131
+ next if File.readable?(cache_file_name)
132
+
133
+ @log.debug("caching values for #{group_name} facts")
113
134
  File.write(cache_file_name, JSON.pretty_generate(data))
114
135
  end
115
136
  end
@@ -128,8 +149,7 @@ module Facter
128
149
  @groups[group_name] = data
129
150
  end
130
151
 
131
- def check_ttls?(group_name)
132
- ttls = @fact_groups.get_group_ttls(group_name)
152
+ def check_ttls?(group_name, ttls)
133
153
  return false unless ttls
134
154
 
135
155
  cache_file_name = File.join(@cache_dir, group_name)
@@ -20,45 +20,48 @@ module Facter
20
20
 
21
21
  @facts = []
22
22
  @external_facts = []
23
- load_internal_facts(options)
24
- load_external_facts(options)
25
23
 
26
- @facts
24
+ @internal_facts = load_internal_facts(options)
25
+ @external_facts = load_external_facts(options)
26
+
27
+ @facts = @internal_facts + @external_facts
27
28
  end
28
29
 
29
30
  private
30
31
 
31
32
  def load_internal_facts(options)
32
33
  @log.debug('Loading internal facts')
34
+ internal_facts = []
33
35
 
34
36
  if options[:user_query] || options[:show_legacy]
35
37
  # if we have a user query, then we must search in core facts and legacy facts
36
38
  @log.debug('Loading all internal facts')
37
- @internal_facts = @internal_loader.facts
39
+ internal_facts = @internal_loader.facts
38
40
  else
39
41
  @log.debug('Load only core facts')
40
- @internal_facts = @internal_loader.core_facts
42
+ internal_facts = @internal_loader.core_facts
41
43
  end
42
44
 
43
- @internal_facts = block_facts(@internal_facts, options)
44
- @facts.concat(@internal_facts)
45
+ block_facts(internal_facts, options)
45
46
  end
46
47
 
47
48
  def load_external_facts(options)
48
49
  @log.debug('Loading external facts')
50
+ external_facts = []
51
+
49
52
  if options[:custom_facts]
50
53
  @log.debug('Loading custom facts')
51
- @external_facts.concat(@external_fact_loader.custom_facts)
54
+ external_facts += @external_fact_loader.custom_facts
52
55
  end
53
56
 
54
- @external_facts = block_facts(@external_facts, options)
57
+ external_facts = block_facts(external_facts, options)
55
58
 
56
59
  if options[:external_facts]
57
60
  @log.debug('Loading external facts')
58
- @external_facts.concat(@external_fact_loader.external_facts)
61
+ external_facts += @external_fact_loader.external_facts
59
62
  end
60
63
 
61
- @facts.concat(@external_facts)
64
+ external_facts
62
65
  end
63
66
 
64
67
  def block_facts(facts, options)
@@ -46,7 +46,9 @@ module Facter
46
46
  return unless file_global_conf
47
47
 
48
48
  if Options.cli?
49
- @options[:custom_facts] = !file_global_conf['no-custom-facts'] unless file_global_conf['no-custom-facts'].nil?
49
+ unless file_global_conf['no-custom-facts'].nil?
50
+ @options[:no_custom_facts] = file_global_conf['no-custom-facts']
51
+ end
50
52
  end
51
53
 
52
54
  @options[:custom_dir] = file_global_conf['custom-dir'] unless file_global_conf['custom-dir'].nil?
@@ -57,7 +59,7 @@ module Facter
57
59
  return unless global_conf
58
60
 
59
61
  if Options.cli?
60
- @options[:external_facts] = !global_conf['no-external-facts'] unless global_conf['no-external-facts'].nil?
62
+ @options[:no_external_facts] = global_conf['no-external-facts'] unless global_conf['no-external-facts'].nil?
61
63
  end
62
64
 
63
65
  @options[:external_dir] = [global_conf['external-dir']].flatten unless global_conf['external-dir'].nil?
@@ -67,7 +69,7 @@ module Facter
67
69
  def augment_ruby(global_conf)
68
70
  return unless global_conf
69
71
 
70
- @options[:ruby] = global_conf['no-ruby'].nil? ? true : !global_conf['no-ruby']
72
+ @options[:no_ruby] = global_conf['no-ruby'].nil? ? false : global_conf['no-ruby']
71
73
  end
72
74
 
73
75
  def augment_show_legacy(global_conf)
@@ -8,28 +8,36 @@ module Facter
8
8
  # TODO: constant is not yet available when running puppet facts
9
9
  @log_level = :warn
10
10
  @show_legacy = true
11
+ @custom_facts = true
12
+ @blocked_facts = []
13
+ @ruby = true
14
+ @external_facts = true
15
+ @config = nil
16
+ @user_query = []
17
+ @strict = false
18
+ @json = false
19
+ @cache = true
20
+ @yaml = false
21
+ @puppet = false
22
+ @ttls = []
11
23
  @block = true
12
- @custom_dir = []
24
+ @cli = nil
13
25
  @config_file_custom_dir = []
14
- @custom_facts = true
15
- @external_dir = []
16
26
  @config_file_external_dir = []
17
27
  @default_external_dir = []
18
- @external_facts = true
19
- @ruby = true
20
- @cache = true
21
- @blocked_facts = []
22
- @user_query = []
23
- @block_list = {}
24
28
  @fact_groups = {}
25
- @color = false
29
+ @block_list = []
30
+ @color = true
31
+ @trace = false
26
32
  @timing = false
33
+ @external_dir = []
34
+ @custom_dir = []
27
35
 
28
36
  class << self
29
- attr_reader :debug, :verbose, :log_level, :show_legacy, :ruby,
30
- :custom_facts, :blocked_facts
37
+ attr_reader :debug, :verbose, :log_level, :show_legacy,
38
+ :custom_facts, :blocked_facts, :ruby, :external_facts
31
39
 
32
- attr_accessor :config, :user_query, :strict, :json, :haml, :external_facts,
40
+ attr_accessor :config, :user_query, :strict, :json,
33
41
  :cache, :yaml, :puppet, :ttls, :block, :cli, :config_file_custom_dir,
34
42
  :config_file_external_dir, :default_external_dir, :fact_groups,
35
43
  :block_list, :color, :trace, :timing
@@ -45,16 +53,28 @@ module Facter
45
53
  options
46
54
  end
47
55
 
48
- def ruby=(bool)
49
- if bool == true
50
- @ruby = true
51
- else
56
+ def no_ruby=(bool)
57
+ if bool
52
58
  @ruby = false
53
59
  @custom_facts = false
54
60
  @blocked_facts << 'ruby'
61
+ else
62
+ @ruby = true
55
63
  end
56
64
  end
57
65
 
66
+ def no_block=(bool)
67
+ @block = !bool
68
+ end
69
+
70
+ def no_cache=(bool)
71
+ @cache = !bool
72
+ end
73
+
74
+ def no_color=(bool)
75
+ @color = !bool
76
+ end
77
+
58
78
  def external_dir
59
79
  return fallback_external_dir if @external_dir.empty? && @external_facts
60
80
 
@@ -99,8 +119,8 @@ module Facter
99
119
  end
100
120
  end
101
121
 
102
- def custom_facts=(bool)
103
- if bool == true
122
+ def no_custom_facts=(bool)
123
+ if bool == false
104
124
  @custom_facts = true
105
125
  @ruby = true
106
126
  else
@@ -108,6 +128,10 @@ module Facter
108
128
  end
109
129
  end
110
130
 
131
+ def no_external_facts=(bool)
132
+ @external_facts = !bool
133
+ end
134
+
111
135
  def log_level=(level)
112
136
  level = level.to_sym
113
137
  case level
@@ -142,25 +166,34 @@ module Facter
142
166
  # TODO: constant is not yet available when running puppet facts
143
167
  @log_level = :warn
144
168
  @show_legacy = true
145
- @block = true
146
169
  @ruby = true
147
170
  @user_query = []
148
- @cli = nil
171
+ @json = false
149
172
  @cache = true
150
- @trace = false
173
+ @yaml = false
174
+ @puppet = false
175
+ @ttls = []
176
+ @block = true
177
+ @cli = nil
151
178
  reset_config
152
179
  end
153
180
 
154
181
  def reset_config
155
- @custom_dir = []
156
182
  @custom_facts = true
157
- @external_dir = []
158
- @default_external_dir = []
159
- @external_facts = true
160
183
  @blocked_facts = []
184
+ @external_facts = true
185
+ @config = nil
186
+ @strict = false
187
+ @config_file_custom_dir = []
188
+ @config_file_external_dir = []
189
+ @default_external_dir = []
161
190
  @fact_groups = {}
162
- @block_list = {}
191
+ @block_list = []
192
+ @color = true
193
+ @trace = false
163
194
  @timing = false
195
+ @external_dir = []
196
+ @custom_dir = []
164
197
  end
165
198
 
166
199
  def fallback_external_dir