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