facter 4.0.38 → 4.0.43
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.
- checksums.yaml +4 -4
- data/bin/facter +3 -4
- data/lib/facter.rb +138 -27
- data/lib/facter/custom_facts/core/aggregate.rb +51 -17
- data/lib/facter/custom_facts/core/execution.rb +27 -35
- data/lib/facter/custom_facts/core/execution/base.rb +42 -6
- data/lib/facter/custom_facts/util/directory_loader.rb +1 -1
- data/lib/facter/custom_facts/util/resolution.rb +40 -11
- data/lib/facter/facts/aix/disks.rb +1 -1
- data/lib/facter/facts/aix/kernel.rb +1 -1
- data/lib/facter/facts/aix/kernelmajversion.rb +1 -1
- data/lib/facter/facts/aix/kernelrelease.rb +1 -1
- data/lib/facter/facts/aix/kernelversion.rb +1 -1
- data/lib/facter/facts/aix/os/release.rb +1 -1
- data/lib/facter/facts/linux/cloud.rb +15 -0
- data/lib/facter/facts/linux/disks.rb +1 -1
- data/lib/facter/facts/linux/ec2_metadata.rb +5 -27
- data/lib/facter/facts/linux/ec2_userdata.rb +5 -27
- data/lib/facter/facts/linux/is_virtual.rb +7 -46
- data/lib/facter/facts/linux/virtual.rb +3 -58
- data/lib/facter/facts/solaris/disks.rb +1 -1
- data/lib/facter/facts/solaris/zones.rb +1 -1
- data/lib/facter/facts_utils/virtual_detector.rb +78 -0
- data/lib/facter/framework/cli/cli.rb +83 -36
- data/lib/facter/framework/cli/cli_launcher.rb +34 -38
- data/lib/facter/framework/config/fact_groups.rb +36 -2
- data/lib/facter/framework/core/cache_manager.rb +40 -23
- data/lib/facter/framework/core/fact_loaders/fact_loader.rb +14 -11
- data/lib/facter/framework/core/options/config_file_options.rb +5 -3
- data/lib/facter/framework/core/options/option_store.rb +27 -10
- data/lib/facter/framework/logging/logger.rb +1 -5
- data/lib/facter/patches/sysfilesystem/sys/statvfs.rb +92 -0
- data/lib/facter/resolvers/aix/os_level.rb +27 -0
- data/lib/facter/resolvers/cloud.rb +39 -0
- data/lib/facter/resolvers/dmi_decode.rb +1 -0
- data/lib/facter/resolvers/dmi_resolver.rb +2 -2
- data/lib/facter/resolvers/memory_resolver.rb +12 -14
- data/lib/facter/resolvers/mountpoints_resolver.rb +5 -2
- data/lib/facter/resolvers/networking_linux_resolver.rb +10 -5
- data/lib/facter/resolvers/processors_resolver.rb +5 -1
- data/lib/facter/resolvers/solaris/mountpoints.rb +60 -0
- data/lib/facter/resolvers/solaris/networking.rb +1 -1
- data/lib/facter/resolvers/utils/filesystem_helper.rb +3 -1
- data/lib/facter/version.rb +1 -1
- metadata +8 -4
- data/lib/facter/resolvers/aix/os_level_resolver.rb +0 -25
- data/lib/facter/resolvers/os_level_resolver.rb +0 -28
@@ -3,10 +3,6 @@
|
|
3
3
|
module Facter
|
4
4
|
module Core
|
5
5
|
module Execution
|
6
|
-
# require_relative 'execution/base'
|
7
|
-
# require_relative 'execution/windows'
|
8
|
-
# require_relative 'execution/posix'
|
9
|
-
|
10
6
|
@@impl = if LegacyFacter::Util::Config.windows?
|
11
7
|
Facter::Core::Execution::Windows.new
|
12
8
|
else
|
@@ -20,24 +16,22 @@ module Facter
|
|
20
16
|
module_function
|
21
17
|
|
22
18
|
# Returns the locations to be searched when looking for a binary. This
|
23
|
-
#
|
24
|
-
#
|
19
|
+
# is currently determined by the +PATH+ environment variable plus
|
20
|
+
# `/sbin` and `/usr/sbin` when run on unix
|
21
|
+
#
|
22
|
+
# @return [Array<String>] The paths to be searched for binaries
|
25
23
|
#
|
26
|
-
# @return [Array<String>] the paths to be searched for binaries
|
27
24
|
# @api private
|
28
25
|
def search_paths
|
29
26
|
@@impl.search_paths
|
30
27
|
end
|
31
28
|
|
32
29
|
# Determines the full path to a binary. If the supplied filename does not
|
33
|
-
#
|
34
|
-
#
|
30
|
+
# already describe an absolute path then different locations (determined
|
31
|
+
# by {search_paths}) will be searched for a match.
|
32
|
+
# @param bin [String] The executable to locate
|
35
33
|
#
|
36
|
-
#
|
37
|
-
# the expanded pathname.
|
38
|
-
#
|
39
|
-
# @param bin [String] the executable to locate
|
40
|
-
# @return [String,nil] the full path to the executable or nil if not
|
34
|
+
# @return [String/nil] The full path to the executable or nil if not
|
41
35
|
# found
|
42
36
|
#
|
43
37
|
# @api public
|
@@ -46,10 +40,12 @@ module Facter
|
|
46
40
|
end
|
47
41
|
|
48
42
|
# Determine in a platform-specific way whether a path is absolute. This
|
49
|
-
#
|
43
|
+
# defaults to the local platform if none is specified.
|
44
|
+
# @param path [String] The path to check
|
45
|
+
|
46
|
+
# @param platform [:posix/:windows/nil] The platform logic to use
|
50
47
|
#
|
51
|
-
# @
|
52
|
-
# @param platform [:posix,:windows,nil] the platform logic to use
|
48
|
+
# @api private
|
53
49
|
def absolute_path?(path, platform = nil)
|
54
50
|
case platform
|
55
51
|
when :posix
|
@@ -62,38 +58,35 @@ module Facter
|
|
62
58
|
end
|
63
59
|
|
64
60
|
# Given a command line, this returns the command line with the
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
61
|
+
# executable written as an absolute path. If the executable contains
|
62
|
+
# spaces, it has to be put in double quotes to be properly recognized.
|
68
63
|
# @param command [String] the command line
|
69
64
|
#
|
70
|
-
# @return [String
|
71
|
-
#
|
65
|
+
# @return [String/nil] The command line with the executable's path
|
66
|
+
# expanded, or nil if the executable cannot be found.
|
67
|
+
#
|
68
|
+
# @api private
|
72
69
|
def expand_command(command)
|
73
70
|
@@impl.expand_command(command)
|
74
71
|
end
|
75
72
|
|
76
73
|
# Overrides environment variables within a block of code. The
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
# @overload with_env(values, { || ... })
|
81
|
-
#
|
74
|
+
# specified values will be set for the duration of the block, after
|
75
|
+
# which the original values (if any) will be restored.
|
82
76
|
# @param values [Hash<String=>String>] A hash of the environment
|
83
77
|
# variables to override
|
84
78
|
#
|
85
|
-
# @return [
|
79
|
+
# @return [String] The block's return string
|
86
80
|
#
|
87
|
-
# @api
|
81
|
+
# @api private
|
88
82
|
def with_env(values, &block)
|
89
83
|
@@impl.with_env(values, &block)
|
90
84
|
end
|
91
85
|
|
92
86
|
# Try to execute a command and return the output.
|
87
|
+
# @param command [String] Command to run
|
93
88
|
#
|
94
|
-
# @
|
95
|
-
#
|
96
|
-
# @return [String] the output of the program, or nil if the command does
|
89
|
+
# @return [String/nil] Output of the program, or nil if the command does
|
97
90
|
# not exist or could not be executed.
|
98
91
|
#
|
99
92
|
# @deprecated Use #{execute} instead
|
@@ -103,9 +96,9 @@ module Facter
|
|
103
96
|
end
|
104
97
|
|
105
98
|
# Execute a command and return the output of that program.
|
99
|
+
# @param command [String] Command to run
|
106
100
|
#
|
107
|
-
# @param
|
108
|
-
# @param options [Hash]
|
101
|
+
# @param options [Hash] Hash with options for the aggregate fact
|
109
102
|
#
|
110
103
|
# @option options [Object] :on_fail How to behave when the command could
|
111
104
|
# not be run. Specifying :raise will raise an error, anything else will
|
@@ -118,7 +111,6 @@ module Facter
|
|
118
111
|
# command execution failed and :on_fail was specified.
|
119
112
|
#
|
120
113
|
# @api public
|
121
|
-
# @since 2.0.1
|
122
114
|
def execute(command, options = {})
|
123
115
|
@@impl.execute(command, options)
|
124
116
|
end
|
@@ -6,6 +6,10 @@ module Facter
|
|
6
6
|
class Base
|
7
7
|
STDERR_MESSAGE = 'Command %s resulted with the following stderr message: %s'
|
8
8
|
|
9
|
+
def initialize
|
10
|
+
@log = Log.new(self)
|
11
|
+
end
|
12
|
+
|
9
13
|
# This is part of the public API. No race condition can happen
|
10
14
|
# here because custom facts are executed sequentially
|
11
15
|
def with_env(values)
|
@@ -36,9 +40,7 @@ module Facter
|
|
36
40
|
end
|
37
41
|
|
38
42
|
def execute(command, options = {})
|
39
|
-
on_fail = options
|
40
|
-
expand = options.fetch(:expand, true)
|
41
|
-
logger = options[:logger]
|
43
|
+
on_fail, expand, logger, time_limit = extract_options(options)
|
42
44
|
|
43
45
|
expanded_command = if !expand && builtin_command?(command) || logger
|
44
46
|
command
|
@@ -55,11 +57,21 @@ module Facter
|
|
55
57
|
return on_fail
|
56
58
|
end
|
57
59
|
|
58
|
-
execute_command(expanded_command, on_fail, logger)
|
60
|
+
execute_command(expanded_command, on_fail, logger, time_limit)
|
59
61
|
end
|
60
62
|
|
61
63
|
private
|
62
64
|
|
65
|
+
def extract_options(options)
|
66
|
+
on_fail = options.fetch(:on_fail, :raise)
|
67
|
+
expand = options.fetch(:expand, true)
|
68
|
+
logger = options[:logger]
|
69
|
+
time_limit = options[:limit].to_i
|
70
|
+
time_limit = time_limit.positive? ? time_limit : nil
|
71
|
+
|
72
|
+
[on_fail, expand, logger, time_limit]
|
73
|
+
end
|
74
|
+
|
63
75
|
def log_stderr(msg, command, logger)
|
64
76
|
return if !msg || msg.empty?
|
65
77
|
|
@@ -77,12 +89,36 @@ module Facter
|
|
77
89
|
output.chomp =~ /builtin/ ? true : false
|
78
90
|
end
|
79
91
|
|
80
|
-
def execute_command(command, on_fail, logger = nil)
|
92
|
+
def execute_command(command, on_fail, logger = nil, time_limit = nil)
|
93
|
+
time_limit ||= 300
|
81
94
|
begin
|
82
95
|
# Set LC_ALL and LANG to force i18n to C for the duration of this exec;
|
83
96
|
# this ensures that any code that parses the
|
84
97
|
# output of the command can expect it to be in a consistent / predictable format / locale
|
85
|
-
|
98
|
+
opts = { 'LC_ALL' => 'C', 'LANG' => 'C' }
|
99
|
+
require 'timeout'
|
100
|
+
@log.debug("Executing command: #{command}")
|
101
|
+
out, stderr = Open3.popen3(opts, command.to_s) do |_, stdout, stderr, wait_thr|
|
102
|
+
pid = wait_thr.pid
|
103
|
+
stdout_messages = +''
|
104
|
+
stderr_messages = +''
|
105
|
+
out_reader = Thread.new { stdout.read }
|
106
|
+
err_reader = Thread.new { stderr.read }
|
107
|
+
begin
|
108
|
+
Timeout.timeout(time_limit) do
|
109
|
+
stdout_messages << out_reader.value
|
110
|
+
stderr_messages << err_reader.value
|
111
|
+
end
|
112
|
+
rescue Timeout::Error
|
113
|
+
message = "Timeout encounter after #{time_limit}s, killing process with pid: #{pid}"
|
114
|
+
Process.kill('KILL', pid)
|
115
|
+
on_fail == :raise ? (raise StandardError, message) : @log.debug(message)
|
116
|
+
ensure
|
117
|
+
out_reader.kill
|
118
|
+
err_reader.kill
|
119
|
+
end
|
120
|
+
[stdout_messages, stderr_messages]
|
121
|
+
end
|
86
122
|
log_stderr(stderr, command, logger)
|
87
123
|
rescue StandardError => e
|
88
124
|
return '' if logger
|
@@ -59,7 +59,7 @@ module LegacyFacter
|
|
59
59
|
basename = File.basename(file)
|
60
60
|
next if file_blocked?(basename)
|
61
61
|
|
62
|
-
if facts.find { |f| f.name == basename } && cm.
|
62
|
+
if facts.find { |f| f.name == basename } && cm.fact_cache_enabled?(basename)
|
63
63
|
Facter.log_exception(Exception.new("Caching is enabled for group \"#{basename}\" while "\
|
64
64
|
'there are at least two external facts files with the same filename'))
|
65
65
|
else
|
@@ -14,6 +14,8 @@ module Facter
|
|
14
14
|
class Resolution
|
15
15
|
# @api private
|
16
16
|
attr_accessor :code, :fact_type
|
17
|
+
|
18
|
+
# @api private
|
17
19
|
attr_writer :value
|
18
20
|
|
19
21
|
extend Facter::Core::Execution
|
@@ -24,7 +26,12 @@ module Facter
|
|
24
26
|
# compatibility.
|
25
27
|
#
|
26
28
|
# @deprecated
|
27
|
-
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
public :which, :exec
|
32
|
+
|
33
|
+
# @api private
|
34
|
+
public :with_env
|
28
35
|
end
|
29
36
|
|
30
37
|
include LegacyFacter::Core::Resolvable
|
@@ -32,22 +39,27 @@ module Facter
|
|
32
39
|
|
33
40
|
# @!attribute [rw] name
|
34
41
|
# The name of this resolution. The resolution name should be unique with
|
35
|
-
#
|
42
|
+
# respect to the given fact.
|
43
|
+
#
|
36
44
|
# @return [String]
|
45
|
+
#
|
37
46
|
# @api public
|
38
47
|
attr_accessor :name
|
39
48
|
|
40
49
|
# @!attribute [r] fact
|
41
|
-
#
|
50
|
+
#
|
51
|
+
# @return [Facter::Util::Fact] Associated fact with this resolution.
|
52
|
+
#
|
42
53
|
# @api private
|
43
54
|
attr_reader :fact
|
44
55
|
|
45
56
|
# Create a new resolution mechanism.
|
46
57
|
#
|
47
58
|
# @param name [String] The name of the resolution.
|
48
|
-
# @return [void]
|
49
59
|
#
|
50
|
-
# @
|
60
|
+
# @return [Facter::Util::Resolution] The created resolution
|
61
|
+
#
|
62
|
+
# @api public
|
51
63
|
def initialize(name, fact)
|
52
64
|
@name = name
|
53
65
|
@fact = fact
|
@@ -57,6 +69,11 @@ module Facter
|
|
57
69
|
@weight = nil
|
58
70
|
end
|
59
71
|
|
72
|
+
# Returns the fact's resolution type
|
73
|
+
#
|
74
|
+
# @return [Symbol] The fact's type
|
75
|
+
#
|
76
|
+
# @api private
|
60
77
|
def resolution_type
|
61
78
|
:simple
|
62
79
|
end
|
@@ -64,7 +81,9 @@ module Facter
|
|
64
81
|
# Evaluate the given block in the context of this resolution. If a block has
|
65
82
|
# already been evaluated emit a warning to that effect.
|
66
83
|
#
|
67
|
-
# @return [
|
84
|
+
# @return [String] Result of the block's evaluation
|
85
|
+
#
|
86
|
+
# @api private
|
68
87
|
def evaluate(&block)
|
69
88
|
if @last_evaluated
|
70
89
|
msg = "Already evaluated #{@name}"
|
@@ -85,6 +104,11 @@ module Facter
|
|
85
104
|
end
|
86
105
|
end
|
87
106
|
|
107
|
+
# Sets options for the aggregate fact
|
108
|
+
#
|
109
|
+
# @return [nil]
|
110
|
+
#
|
111
|
+
# @api private
|
88
112
|
def options(options)
|
89
113
|
accepted_options = %i[name value timeout weight fact_type file]
|
90
114
|
|
@@ -98,8 +122,6 @@ module Facter
|
|
98
122
|
# Sets the code block or external program that will be evaluated to
|
99
123
|
# get the value of the fact.
|
100
124
|
#
|
101
|
-
# @return [void]
|
102
|
-
#
|
103
125
|
# @overload setcode(string)
|
104
126
|
# Sets an external program to call to get the value of the resolution
|
105
127
|
# @param [String] string the external program to run to get the
|
@@ -111,6 +133,8 @@ module Facter
|
|
111
133
|
# This block is run when the fact is evaluated. Errors raised from
|
112
134
|
# inside the block are rescued and printed to stderr.
|
113
135
|
#
|
136
|
+
# @return [Facter::Util::Resolution] Returns itself
|
137
|
+
#
|
114
138
|
# @api public
|
115
139
|
def setcode(string = nil, &block)
|
116
140
|
if string
|
@@ -127,11 +151,16 @@ module Facter
|
|
127
151
|
else
|
128
152
|
raise ArgumentError, 'You must pass either code or a block'
|
129
153
|
end
|
154
|
+
self
|
130
155
|
end
|
131
156
|
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
157
|
+
# Comparison is done based on weight and fact type.
|
158
|
+
# The greater the weight, the higher the priority.
|
159
|
+
# If weights are equal, we consider external facts greater than custom facts.
|
160
|
+
#
|
161
|
+
# @return [bool] Weight comparison result
|
162
|
+
#
|
163
|
+
# @api private
|
135
164
|
def <=>(other)
|
136
165
|
return compare_equal_weights(other) if weight == other.weight
|
137
166
|
return 1 if weight > other.weight
|
@@ -24,7 +24,7 @@ module Facts
|
|
24
24
|
|
25
25
|
def add_legacy_facts(disks, facts)
|
26
26
|
disks.each do |disk_name, disk_info|
|
27
|
-
facts.push(Facter::ResolvedFact.new("blockdevice_#{disk_name}_size", disk_info[:size_bytes]
|
27
|
+
facts.push(Facter::ResolvedFact.new("blockdevice_#{disk_name}_size", disk_info[:size_bytes], :legacy))
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
@@ -6,7 +6,7 @@ module Facts
|
|
6
6
|
FACT_NAME = 'kernelmajversion'
|
7
7
|
|
8
8
|
def call_the_resolver
|
9
|
-
fact_value = Facter::Resolvers::OsLevel.resolve(:build)
|
9
|
+
fact_value = Facter::Resolvers::Aix::OsLevel.resolve(:build)
|
10
10
|
kernelmajversion = fact_value.split('-')[0]
|
11
11
|
|
12
12
|
Facter::ResolvedFact.new(FACT_NAME, kernelmajversion)
|
@@ -6,7 +6,7 @@ module Facts
|
|
6
6
|
FACT_NAME = 'kernelversion'
|
7
7
|
|
8
8
|
def call_the_resolver
|
9
|
-
fact_value = Facter::Resolvers::OsLevel.resolve(:build)
|
9
|
+
fact_value = Facter::Resolvers::Aix::OsLevel.resolve(:build)
|
10
10
|
kernelversion = fact_value.split('-')[0]
|
11
11
|
|
12
12
|
Facter::ResolvedFact.new(FACT_NAME, kernelversion)
|
@@ -8,7 +8,7 @@ module Facts
|
|
8
8
|
ALIASES = %w[operatingsystemmajrelease operatingsystemrelease].freeze
|
9
9
|
|
10
10
|
def call_the_resolver
|
11
|
-
fact_value = Facter::Resolvers::OsLevel.resolve(:build)
|
11
|
+
fact_value = Facter::Resolvers::Aix::OsLevel.resolve(:build)
|
12
12
|
major = fact_value.split('-')[0]
|
13
13
|
|
14
14
|
[Facter::ResolvedFact.new(FACT_NAME, full: fact_value.strip, major: major),
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Facts
|
4
|
+
module Linux
|
5
|
+
class Cloud
|
6
|
+
FACT_NAME = 'cloud'
|
7
|
+
|
8
|
+
def call_the_resolver
|
9
|
+
cloud_provider = Facter::Resolvers::Cloud.resolve(:cloud_provider)
|
10
|
+
|
11
|
+
Facter::ResolvedFact.new(FACT_NAME, cloud_provider)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -25,7 +25,7 @@ module Facts
|
|
25
25
|
def add_legacy_facts(disks, facts)
|
26
26
|
disks.each do |disk_name, disk_info|
|
27
27
|
facts.push(Facter::ResolvedFact.new("blockdevice_#{disk_name}_model", disk_info[:model], :legacy))
|
28
|
-
facts.push(Facter::ResolvedFact.new("blockdevice_#{disk_name}_size", disk_info[:size_bytes]
|
28
|
+
facts.push(Facter::ResolvedFact.new("blockdevice_#{disk_name}_size", disk_info[:size_bytes], :legacy))
|
29
29
|
facts.push(Facter::ResolvedFact.new("blockdevice_#{disk_name}_vendor", disk_info[:vendor], :legacy))
|
30
30
|
end
|
31
31
|
end
|
@@ -5,6 +5,10 @@ module Facts
|
|
5
5
|
class Ec2Metadata
|
6
6
|
FACT_NAME = 'ec2_metadata'
|
7
7
|
|
8
|
+
def initialize
|
9
|
+
@virtual = Facter::VirtualDetector.new
|
10
|
+
end
|
11
|
+
|
8
12
|
def call_the_resolver
|
9
13
|
return Facter::ResolvedFact.new(FACT_NAME, nil) unless aws_hypervisors?
|
10
14
|
|
@@ -16,33 +20,7 @@ module Facts
|
|
16
20
|
private
|
17
21
|
|
18
22
|
def aws_hypervisors?
|
19
|
-
virtual
|
20
|
-
|
21
|
-
virtual == 'kvm' || virtual =~ /xen/
|
22
|
-
end
|
23
|
-
|
24
|
-
def check_virt_what
|
25
|
-
Facter::Resolvers::VirtWhat.resolve(:vm)
|
26
|
-
end
|
27
|
-
|
28
|
-
def check_xen
|
29
|
-
Facter::Resolvers::Xen.resolve(:vm)
|
30
|
-
end
|
31
|
-
|
32
|
-
def check_product_name
|
33
|
-
product_name = Facter::Resolvers::Linux::DmiBios.resolve(:product_name)
|
34
|
-
return unless product_name
|
35
|
-
|
36
|
-
Facter::FactsUtils::HYPERVISORS_HASH.each { |key, value| return value if product_name.include?(key) }
|
37
|
-
end
|
38
|
-
|
39
|
-
def check_bios_vendor
|
40
|
-
bios_vendor = Facter::Resolvers::Linux::DmiBios.resolve(:bios_vendor)
|
41
|
-
return 'kvm' if bios_vendor&.include?('Amazon EC2')
|
42
|
-
end
|
43
|
-
|
44
|
-
def check_lspci
|
45
|
-
Facter::Resolvers::Lspci.resolve(:vm)
|
23
|
+
@virtual.platform =~ /kvm|xen|aws/
|
46
24
|
end
|
47
25
|
end
|
48
26
|
end
|