facter 1.7.6 → 2.0.1.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of facter might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/COMMITTERS.md +194 -0
- data/CONTRIBUTING.md +63 -235
- data/Gemfile +12 -8
- data/README.md +1 -2
- data/Rakefile +1 -1
- data/bin/facter +0 -4
- data/ext/build_defaults.yaml +2 -2
- data/ext/project_data.yaml +18 -0
- data/install.rb +1 -16
- data/lib/facter.rb +171 -171
- data/lib/facter/application.rb +65 -54
- data/lib/facter/core/aggregate.rb +220 -0
- data/lib/facter/core/directed_graph.rb +46 -0
- data/lib/facter/core/execution.rb +100 -0
- data/lib/facter/core/execution/base.rb +73 -0
- data/lib/facter/core/execution/posix.rb +50 -0
- data/lib/facter/core/execution/windows.rb +57 -0
- data/lib/facter/core/logging.rb +169 -0
- data/lib/facter/core/resolvable.rb +94 -0
- data/lib/facter/core/suitable.rb +117 -0
- data/lib/facter/domain.rb +15 -9
- data/lib/facter/filesystems.rb +1 -1
- data/lib/facter/hardwaremodel.rb +1 -1
- data/lib/facter/hostname.rb +3 -3
- data/lib/facter/interfaces.rb +6 -1
- data/lib/facter/ipaddress.rb +2 -2
- data/lib/facter/kernel.rb +1 -1
- data/lib/facter/kernelrelease.rb +1 -1
- data/lib/facter/ldom.rb +1 -1
- data/lib/facter/lsbdistcodename.rb +1 -1
- data/lib/facter/lsbdistdescription.rb +1 -1
- data/lib/facter/lsbdistid.rb +1 -1
- data/lib/facter/lsbdistrelease.rb +1 -1
- data/lib/facter/lsbrelease.rb +1 -1
- data/lib/facter/macaddress.rb +1 -14
- data/lib/facter/macosx.rb +2 -2
- data/lib/facter/memory.rb +8 -19
- data/lib/facter/operatingsystem.rb +1 -1
- data/lib/facter/operatingsystemrelease.rb +34 -1
- data/lib/facter/physicalprocessorcount.rb +6 -6
- data/lib/facter/processor.rb +11 -10
- data/lib/facter/selinux.rb +4 -15
- data/lib/facter/ssh.rb +5 -2
- data/lib/facter/util/architecture.rb +2 -2
- data/lib/facter/util/collection.rb +42 -38
- data/lib/facter/util/config.rb +19 -9
- data/lib/facter/util/confine.rb +34 -4
- data/lib/facter/util/ec2.rb +1 -1
- data/lib/facter/util/fact.rb +108 -36
- data/lib/facter/util/file_read.rb +7 -6
- data/lib/facter/util/formatter.rb +38 -0
- data/lib/facter/util/ip.rb +3 -3
- data/lib/facter/util/loader.rb +62 -42
- data/lib/facter/util/macosx.rb +7 -8
- data/lib/facter/util/manufacturer.rb +3 -3
- data/lib/facter/util/memory.rb +13 -13
- data/lib/facter/util/monkey_patches.rb +0 -31
- data/lib/facter/util/netmask.rb +3 -3
- data/lib/facter/util/normalization.rb +94 -0
- data/lib/facter/util/nothing_loader.rb +3 -6
- data/lib/facter/util/parser.rb +3 -5
- data/lib/facter/util/plist/generator.rb +1 -1
- data/lib/facter/util/processor.rb +15 -15
- data/lib/facter/util/resolution.rb +112 -289
- data/lib/facter/util/solaris_zones.rb +4 -4
- data/lib/facter/util/uptime.rb +8 -3
- data/lib/facter/util/values.rb +67 -1
- data/lib/facter/util/virtual.rb +10 -10
- data/lib/facter/util/xendomains.rb +1 -1
- data/lib/facter/version.rb +42 -39
- data/lib/facter/virtual.rb +6 -7
- data/lib/facter/zfs_version.rb +3 -3
- data/lib/facter/zpool_version.rb +3 -3
- data/spec/fixtures/unit/netmask/darwin_10_8_5.txt +30 -0
- data/spec/unit/application_spec.rb +46 -1
- data/spec/unit/core/aggregate_spec.rb +125 -0
- data/spec/unit/core/directed_graph_spec.rb +79 -0
- data/spec/unit/core/execution/base_spec.rb +119 -0
- data/spec/unit/core/execution/posix_spec.rb +86 -0
- data/spec/unit/core/execution/windows_spec.rb +106 -0
- data/spec/unit/core/execution_spec.rb +37 -0
- data/spec/unit/core/logging_spec.rb +104 -0
- data/spec/unit/core/resolvable_spec.rb +81 -0
- data/spec/unit/core/suitable_spec.rb +96 -0
- data/spec/unit/domain_spec.rb +5 -5
- data/spec/unit/facter_spec.rb +61 -222
- data/spec/unit/filesystems_spec.rb +2 -2
- data/spec/unit/hardwareisa_spec.rb +5 -5
- data/spec/unit/hardwaremodel_spec.rb +1 -1
- data/spec/unit/hostname_spec.rb +4 -4
- data/spec/unit/id_spec.rb +3 -3
- data/spec/unit/interfaces_spec.rb +10 -0
- data/spec/unit/ipaddress6_spec.rb +4 -4
- data/spec/unit/ipaddress_spec.rb +1 -1
- data/spec/unit/kernel_spec.rb +2 -2
- data/spec/unit/kernelmajversion_spec.rb +1 -1
- data/spec/unit/kernelrelease_spec.rb +4 -4
- data/spec/unit/kernelversion_spec.rb +2 -2
- data/spec/unit/ldom_spec.rb +2 -2
- data/spec/unit/lsbdistcodename_spec.rb +2 -2
- data/spec/unit/lsbdistdescription_spec.rb +2 -2
- data/spec/unit/lsbdistid_spec.rb +2 -2
- data/spec/unit/lsbdistrelease_spec.rb +2 -2
- data/spec/unit/lsbrelease_spec.rb +2 -2
- data/spec/unit/manufacturer_spec.rb +1 -1
- data/spec/unit/memory_spec.rb +24 -31
- data/spec/unit/netmask_spec.rb +9 -0
- data/spec/unit/operatingsystem_spec.rb +1 -1
- data/spec/unit/operatingsystemrelease_spec.rb +62 -4
- data/spec/unit/physicalprocessorcount_spec.rb +10 -10
- data/spec/unit/processor_spec.rb +11 -11
- data/spec/unit/selinux_spec.rb +2 -8
- data/spec/unit/ssh_spec.rb +3 -2
- data/spec/unit/uniqueid_spec.rb +3 -3
- data/spec/unit/util/collection_spec.rb +37 -35
- data/spec/unit/util/config_spec.rb +20 -0
- data/spec/unit/util/confine_spec.rb +21 -0
- data/spec/unit/util/directory_loader_spec.rb +1 -0
- data/spec/unit/util/ec2_spec.rb +6 -6
- data/spec/unit/util/fact_spec.rb +92 -90
- data/spec/unit/util/ip_spec.rb +2 -2
- data/spec/unit/util/loader_spec.rb +127 -186
- data/spec/unit/util/macaddress_spec.rb +2 -2
- data/spec/unit/util/macosx_spec.rb +8 -8
- data/spec/unit/util/manufacturer_spec.rb +3 -3
- data/spec/unit/util/normalization_spec.rb +113 -0
- data/spec/unit/util/parser_spec.rb +25 -3
- data/spec/unit/util/processor_spec.rb +2 -2
- data/spec/unit/util/resolution_spec.rb +60 -631
- data/spec/unit/util/solaris_zones_spec.rb +5 -5
- data/spec/unit/util/uptime_spec.rb +1 -1
- data/spec/unit/util/values_spec.rb +131 -0
- data/spec/unit/util/virtual_spec.rb +16 -16
- data/spec/unit/util/xendomains_spec.rb +2 -2
- data/spec/unit/virtual_spec.rb +39 -39
- data/spec/unit/zfs_version_spec.rb +11 -11
- data/spec/unit/zonename_spec.rb +2 -2
- data/spec/unit/zones_spec.rb +1 -1
- data/spec/unit/zpool_version_spec.rb +11 -11
- metadata +466 -447
- data/lib/facter/util/cfpropertylist.rb +0 -6
- data/lib/facter/util/cfpropertylist/LICENSE +0 -19
- data/lib/facter/util/cfpropertylist/README +0 -44
- data/lib/facter/util/cfpropertylist/Rakefile +0 -44
- data/lib/facter/util/cfpropertylist/THANKS +0 -7
- data/lib/facter/util/cfpropertylist/lib/cfpropertylist.rb +0 -6
- data/lib/facter/util/cfpropertylist/lib/rbBinaryCFPropertyList.rb +0 -562
- data/lib/facter/util/cfpropertylist/lib/rbCFPlistError.rb +0 -26
- data/lib/facter/util/cfpropertylist/lib/rbCFPropertyList.rb +0 -407
- data/lib/facter/util/cfpropertylist/lib/rbCFTypes.rb +0 -244
- data/lib/facter/util/cfpropertylist/lib/rbLibXMLParser.rb +0 -135
- data/lib/facter/util/cfpropertylist/lib/rbNokogiriParser.rb +0 -140
- data/lib/facter/util/cfpropertylist/lib/rbREXMLParser.rb +0 -136
- data/spec/unit/util/monkey_patches_spec.rb +0 -42
data/lib/facter/util/macosx.rb
CHANGED
@@ -6,8 +6,7 @@
|
|
6
6
|
##
|
7
7
|
|
8
8
|
module Facter::Util::Macosx
|
9
|
-
require '
|
10
|
-
require 'facter/util/cfpropertylist'
|
9
|
+
require 'cfpropertylist'
|
11
10
|
require 'facter/util/resolution'
|
12
11
|
|
13
12
|
Plist_Xml_Doctype = '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
|
@@ -16,7 +15,7 @@ module Facter::Util::Macosx
|
|
16
15
|
# by looking at the _name key of the _items dict for each _dataType
|
17
16
|
|
18
17
|
def self.profiler_xml(data_field)
|
19
|
-
Facter::
|
18
|
+
Facter::Core::Execution.exec("/usr/sbin/system_profiler -xml #{data_field}")
|
20
19
|
end
|
21
20
|
|
22
21
|
def self.intern_xml(xml)
|
@@ -26,13 +25,13 @@ module Facter::Util::Macosx
|
|
26
25
|
xml.gsub!( bad_xml_doctype, Plist_Xml_Doctype )
|
27
26
|
Facter.debug("Had to fix plist with incorrect DOCTYPE declaration")
|
28
27
|
end
|
29
|
-
plist =
|
28
|
+
plist = CFPropertyList::List.new
|
30
29
|
begin
|
31
30
|
plist.load_str(xml)
|
32
|
-
rescue => e
|
33
|
-
|
31
|
+
rescue CFFormatError => e
|
32
|
+
raise RuntimeError, "A plist file could not be properly read by CFPropertyList: #{e.message}", e.backtrace
|
34
33
|
end
|
35
|
-
|
34
|
+
CFPropertyList.native_types(plist.value)
|
36
35
|
end
|
37
36
|
|
38
37
|
# Return an xml result, modified as we need it.
|
@@ -58,7 +57,7 @@ module Facter::Util::Macosx
|
|
58
57
|
def self.sw_vers
|
59
58
|
ver = Hash.new
|
60
59
|
[ "productName", "productVersion", "buildVersion" ].each do |option|
|
61
|
-
ver["macosx_#{option}"] = Facter::
|
60
|
+
ver["macosx_#{option}"] = Facter::Core::Execution.exec("/usr/bin/sw_vers -#{option}").strip
|
62
61
|
end
|
63
62
|
productversion = ver["macosx_productVersion"]
|
64
63
|
if not productversion.nil?
|
@@ -55,7 +55,7 @@ module Facter::Manufacturer
|
|
55
55
|
Facter.add(facterkey) do
|
56
56
|
confine :kernel => [:openbsd, :darwin]
|
57
57
|
setcode do
|
58
|
-
Facter::
|
58
|
+
Facter::Core::Execution.exec("sysctl -n #{sysctlkey} 2>/dev/null")
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
@@ -63,7 +63,7 @@ module Facter::Manufacturer
|
|
63
63
|
|
64
64
|
def self.prtdiag_sparc_find_system_info()
|
65
65
|
# Parses prtdiag for a SPARC architecture string, won't work with Solaris x86
|
66
|
-
output = Facter::
|
66
|
+
output = Facter::Core::Execution.exec('/usr/sbin/prtdiag 2>/dev/null')
|
67
67
|
|
68
68
|
# System Configuration: Sun Microsystems sun4u Sun SPARC Enterprise M3000 Server
|
69
69
|
if output and output =~ /^System Configuration:\s+(.+?)\s+(sun\d+\S+)\s+(.+)/
|
@@ -81,7 +81,7 @@ module Facter::Manufacturer
|
|
81
81
|
|
82
82
|
Facter.add('serialnumber') do
|
83
83
|
setcode do
|
84
|
-
Facter::
|
84
|
+
Facter::Core::Execution.exec("/usr/sbin/sneep")
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
data/lib/facter/util/memory.rb
CHANGED
@@ -35,7 +35,7 @@ module Facter::Memory
|
|
35
35
|
def self.vmstat_find_free_memory(args = [])
|
36
36
|
cmd = 'vmstat'
|
37
37
|
cmd += (' ' + args.join(' ')) unless args.empty?
|
38
|
-
row = Facter::
|
38
|
+
row = Facter::Core::Execution.exec(cmd).split("\n")[-1]
|
39
39
|
if row =~ /^\s*\d+\s*\d+\s*\d+\s*\d+\s*(\d+)/
|
40
40
|
memfree = $1
|
41
41
|
end
|
@@ -52,7 +52,7 @@ module Facter::Memory
|
|
52
52
|
pagesize = 0
|
53
53
|
memspecfree = 0
|
54
54
|
|
55
|
-
vmstats = Facter::
|
55
|
+
vmstats = Facter::Core::Execution.exec('vm_stat')
|
56
56
|
vmstats.each_line do |vmline|
|
57
57
|
case
|
58
58
|
when vmline =~ /page\ssize\sof\s(\d+)\sbytes/
|
@@ -71,7 +71,7 @@ module Facter::Memory
|
|
71
71
|
# it's the third value on the line starting with memory
|
72
72
|
# svmon can be run by non root users
|
73
73
|
def self.svmon_aix_find_free_memory()
|
74
|
-
Facter::
|
74
|
+
Facter::Core::Execution.exec("/usr/bin/svmon -O unit=KB") =~ /^memory\s+\d+\s+\d+\s+(\d+)\s+/
|
75
75
|
$1
|
76
76
|
end
|
77
77
|
|
@@ -112,15 +112,15 @@ module Facter::Memory
|
|
112
112
|
def self.mem_size_info(kernel = Facter.value(:kernel))
|
113
113
|
case kernel
|
114
114
|
when /OpenBSD/i
|
115
|
-
Facter::
|
115
|
+
Facter::Core::Execution.exec("sysctl hw.physmem | cut -d'=' -f2")
|
116
116
|
when /FreeBSD/i
|
117
|
-
Facter::
|
117
|
+
Facter::Core::Execution.exec("sysctl -n hw.physmem")
|
118
118
|
when /Darwin/i
|
119
|
-
Facter::
|
119
|
+
Facter::Core::Execution.exec("sysctl -n hw.memsize")
|
120
120
|
when /Dragonfly/i
|
121
|
-
Facter::
|
121
|
+
Facter::Core::Execution.exec("sysctl -n hw.physmem")
|
122
122
|
when /AIX/i
|
123
|
-
if Facter::
|
123
|
+
if Facter::Core::Execution.exec("/usr/bin/svmon -O unit=KB") =~ /^memory\s+(\d+)\s+/
|
124
124
|
$1
|
125
125
|
end
|
126
126
|
end
|
@@ -150,15 +150,15 @@ module Facter::Memory
|
|
150
150
|
def self.swap_info(kernel = Facter.value(:kernel))
|
151
151
|
case kernel
|
152
152
|
when /AIX/i
|
153
|
-
(Facter.value(:id) == "root") ? Facter::
|
153
|
+
(Facter.value(:id) == "root") ? Facter::Core::Execution.exec('swap -l 2>/dev/null') : nil
|
154
154
|
when /OpenBSD/i
|
155
|
-
Facter::
|
155
|
+
Facter::Core::Execution.exec('swapctl -s')
|
156
156
|
when /FreeBSD/i
|
157
|
-
Facter::
|
157
|
+
Facter::Core::Execution.exec('swapinfo -k')
|
158
158
|
when /Darwin/i
|
159
|
-
Facter::
|
159
|
+
Facter::Core::Execution.exec('sysctl vm.swapusage')
|
160
160
|
when /SunOS/i
|
161
|
-
Facter::
|
161
|
+
Facter::Core::Execution.exec('/usr/sbin/swap -l 2>/dev/null')
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
@@ -2,38 +2,7 @@
|
|
2
2
|
# version 1.8.5. This allows us to use RbConfig in place of the older Config in
|
3
3
|
# our code and still be compatible with at least Ruby 1.8.1.
|
4
4
|
require 'rbconfig'
|
5
|
-
require 'enumerator'
|
6
5
|
|
7
6
|
unless defined? ::RbConfig
|
8
7
|
::RbConfig = ::Config
|
9
8
|
end
|
10
|
-
|
11
|
-
module Facter
|
12
|
-
module Util
|
13
|
-
module MonkeyPatches
|
14
|
-
module Lines
|
15
|
-
def lines(separator = $/)
|
16
|
-
if block_given?
|
17
|
-
self.each_line(separator) {|line| yield line }
|
18
|
-
return self
|
19
|
-
else
|
20
|
-
return enum_for(:each_line, separator)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
public
|
29
|
-
class String
|
30
|
-
unless method_defined? :lines
|
31
|
-
include Facter::Util::MonkeyPatches::Lines
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class IO
|
36
|
-
unless method_defined? :lines
|
37
|
-
include Facter::Util::MonkeyPatches::Lines
|
38
|
-
end
|
39
|
-
end
|
data/lib/facter/util/netmask.rb
CHANGED
@@ -8,19 +8,19 @@ module Facter::NetMask
|
|
8
8
|
when 'Linux'
|
9
9
|
ops = {
|
10
10
|
:ifconfig_opts => ['2>/dev/null'],
|
11
|
-
:regex => %r{#{Facter.ipaddress}.*?(?:Mask:|netmask)\s*(#{ipregex})}x,
|
11
|
+
:regex => %r{#{Facter.value(:ipaddress)}.*?(?:Mask:|netmask)\s*(#{ipregex})}x,
|
12
12
|
:munge => nil,
|
13
13
|
}
|
14
14
|
when 'SunOS'
|
15
15
|
ops = {
|
16
16
|
:ifconfig_opts => ['-a'],
|
17
|
-
:regex => %r{\s+ inet \s #{Facter.ipaddress} \s netmask \s (\w{8})}x,
|
17
|
+
:regex => %r{\s+ inet \s #{Facter.value(:ipaddress)} \s netmask \s (\w{8})}x,
|
18
18
|
:munge => Proc.new { |mask| mask.scan(/../).collect do |byte| byte.to_i(16) end.join('.') }
|
19
19
|
}
|
20
20
|
when 'FreeBSD','NetBSD','OpenBSD', 'Darwin', 'GNU/kFreeBSD', 'DragonFly'
|
21
21
|
ops = {
|
22
22
|
:ifconfig_opts => ['-a'],
|
23
|
-
:regex => %r{\s+ inet \s #{Facter.ipaddress} \s netmask \s 0x(\w{8})}x,
|
23
|
+
:regex => %r{\s+ inet \s #{Facter.value(:ipaddress)} \s netmask \s 0x(\w{8})}x,
|
24
24
|
:munge => Proc.new { |mask| mask.scan(/../).collect do |byte| byte.to_i(16) end.join('.') }
|
25
25
|
}
|
26
26
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Facter
|
2
|
+
module Util
|
3
|
+
module Normalization
|
4
|
+
class NormalizationError < StandardError; end
|
5
|
+
|
6
|
+
VALID_TYPES = [Integer, Float, TrueClass, FalseClass, NilClass, String, Array, Hash]
|
7
|
+
|
8
|
+
module_function
|
9
|
+
|
10
|
+
# Recursively normalize the given data structure
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
# @raise [NormalizationError] If the data structure contained an invalid element.
|
14
|
+
# @return [void]
|
15
|
+
def normalize(value)
|
16
|
+
case value
|
17
|
+
when Integer, Float, TrueClass, FalseClass, NilClass
|
18
|
+
value
|
19
|
+
when String
|
20
|
+
normalize_string(value)
|
21
|
+
when Array
|
22
|
+
normalize_array(value)
|
23
|
+
when Hash
|
24
|
+
normalize_hash(value)
|
25
|
+
else
|
26
|
+
raise NormalizationError, "Expected #{value} to be one of #{VALID_TYPES.inspect}, but was #{value.class}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# @!method normalize_string(value)
|
31
|
+
#
|
32
|
+
# Attempt to normalize and validate the given string.
|
33
|
+
#
|
34
|
+
# On Ruby 1.8 the string is checked by stripping out all non UTF-8
|
35
|
+
# characters and comparing the converted string to the original. If they
|
36
|
+
# do not match then the string is considered invalid.
|
37
|
+
#
|
38
|
+
# On Ruby 1.9+, the string is validate by checking that the string encoding
|
39
|
+
# is UTF-8 and that the string content matches the encoding. If the string
|
40
|
+
# is not an expected encoding then it is converted to UTF-8.
|
41
|
+
#
|
42
|
+
# @api public
|
43
|
+
# @raise [NormalizationError] If the string used an unsupported encoding or did not match its encoding
|
44
|
+
# @param value [String]
|
45
|
+
# @return [void]
|
46
|
+
|
47
|
+
if RUBY_VERSION =~ /^1\.8/
|
48
|
+
require 'iconv'
|
49
|
+
|
50
|
+
def normalize_string(value)
|
51
|
+
converted = Iconv.conv('UTF-8//IGNORE', 'UTF-8', value)
|
52
|
+
if converted != value
|
53
|
+
raise NormalizationError, "String #{value.inspect} is not valid UTF-8"
|
54
|
+
end
|
55
|
+
value
|
56
|
+
end
|
57
|
+
else
|
58
|
+
def normalize_string(value)
|
59
|
+
value = value.encode(Encoding::UTF_8)
|
60
|
+
|
61
|
+
unless value.valid_encoding?
|
62
|
+
raise NormalizationError, "String #{value.inspect} doesn't match the reported encoding #{value.encoding}"
|
63
|
+
end
|
64
|
+
|
65
|
+
value
|
66
|
+
rescue EncodingError
|
67
|
+
raise NormalizationError, "String encoding #{value.encoding} is not UTF-8 and could not be converted to UTF-8"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Validate all elements of the array.
|
72
|
+
#
|
73
|
+
# @api public
|
74
|
+
# @raise [NormalizationError] If one of the elements failed validation
|
75
|
+
# @param value [Array]
|
76
|
+
# @return [void]
|
77
|
+
def normalize_array(value)
|
78
|
+
value.collect do |elem|
|
79
|
+
normalize(elem)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Validate all keys and values of the hash.
|
84
|
+
#
|
85
|
+
# @api public
|
86
|
+
# @raise [NormalizationError] If one of the keys or values failed normalization
|
87
|
+
# @param value [Hash]
|
88
|
+
# @return [void]
|
89
|
+
def normalize_hash(value)
|
90
|
+
Hash[value.collect { |k, v| [ normalize(k), normalize(v) ] } ]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -1,13 +1,10 @@
|
|
1
|
-
# An external fact loader that doesn't load anything
|
2
|
-
|
3
|
-
# This makes it possible to disable loading
|
4
|
-
# of external facts
|
5
|
-
|
6
1
|
module Facter
|
7
2
|
module Util
|
8
3
|
|
4
|
+
# An external fact loader that doesn't load anything
|
5
|
+
# This makes it possible to disable loading
|
6
|
+
# of external facts
|
9
7
|
class NothingLoader
|
10
|
-
|
11
8
|
def load(collection)
|
12
9
|
end
|
13
10
|
end
|
data/lib/facter/util/parser.rb
CHANGED
@@ -55,9 +55,7 @@ module Facter::Util::Parser
|
|
55
55
|
def results
|
56
56
|
parse_results
|
57
57
|
rescue Exception => detail
|
58
|
-
Facter.
|
59
|
-
Facter.warn("detail: #{detail.class}: #{detail.message}")
|
60
|
-
Facter.debug(detail.backtrace.join("\n\t"))
|
58
|
+
Facter.log_exception(detail, "Failed to handle #{filename} as #{self.class} facts: #{detail.message}")
|
61
59
|
nil
|
62
60
|
end
|
63
61
|
|
@@ -119,7 +117,7 @@ module Facter::Util::Parser
|
|
119
117
|
|
120
118
|
class ScriptParser < Base
|
121
119
|
def parse_results
|
122
|
-
KeyValuePairOutputFormat.parse Facter::
|
120
|
+
KeyValuePairOutputFormat.parse Facter::Core::Execution.exec(quote(filename))
|
123
121
|
end
|
124
122
|
|
125
123
|
private
|
@@ -142,7 +140,7 @@ module Facter::Util::Parser
|
|
142
140
|
# Returns a hash of facts from powershell output
|
143
141
|
def parse_results
|
144
142
|
shell_command = "powershell -NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass -File \"#{filename}\""
|
145
|
-
KeyValuePairOutputFormat.parse Facter::
|
143
|
+
KeyValuePairOutputFormat.parse Facter::Core::Execution.exec(shell_command)
|
146
144
|
end
|
147
145
|
end
|
148
146
|
|
@@ -47,19 +47,19 @@ module Processor
|
|
47
47
|
end
|
48
48
|
|
49
49
|
##
|
50
|
-
# lsdev is intended to directly delegate to Facter::
|
50
|
+
# lsdev is intended to directly delegate to Facter::Core::Execution.exec in an
|
51
51
|
# effort to make the processorX facts easier to test by stubbing only the
|
52
52
|
# behaviors we need to stub to get the output of the system command.
|
53
53
|
def self.lsdev(command="lsdev -Cc processor")
|
54
|
-
Facter::
|
54
|
+
Facter::Core::Execution.exec(command)
|
55
55
|
end
|
56
56
|
|
57
57
|
##
|
58
|
-
# lsattr is intended to directly delegate to Facter::
|
58
|
+
# lsattr is intended to directly delegate to Facter::Core::Execution.exec in
|
59
59
|
# an effort to make the processorX facts easier to test. See also the
|
60
60
|
# {lsdev} method.
|
61
61
|
def self.lsattr(command="lsattr -El proc0 -a type")
|
62
|
-
Facter::
|
62
|
+
Facter::Core::Execution.exec(command)
|
63
63
|
end
|
64
64
|
|
65
65
|
##
|
@@ -181,34 +181,34 @@ module Processor
|
|
181
181
|
private_class_method :read_unistd_h
|
182
182
|
|
183
183
|
##
|
184
|
-
# machinfo delegates directly to Facter::
|
184
|
+
# machinfo delegates directly to Facter::Core::Execution.exec, as with lsdev
|
185
185
|
# above.
|
186
186
|
def self.machinfo(command="/usr/contrib/bin/machinfo")
|
187
|
-
Facter::
|
187
|
+
Facter::Core::Execution.exec(command)
|
188
188
|
end
|
189
189
|
|
190
190
|
##
|
191
|
-
# model delegates directly to Facter::
|
191
|
+
# model delegates directly to Facter::Core::Execution.exec.
|
192
192
|
def self.model(command="model")
|
193
|
-
Facter::
|
193
|
+
Facter::Core::Execution.exec(command)
|
194
194
|
end
|
195
195
|
|
196
196
|
##
|
197
|
-
# ioscan delegates directly to Facter::
|
197
|
+
# ioscan delegates directly to Facter::Core::Execution.exec.
|
198
198
|
def self.ioscan(command="ioscan -fknCprocessor")
|
199
|
-
Facter::
|
199
|
+
Facter::Core::Execution.exec(command)
|
200
200
|
end
|
201
201
|
|
202
202
|
##
|
203
|
-
# getconf_cpu_version delegates directly to Facter::
|
203
|
+
# getconf_cpu_version delegates directly to Facter::Core::Execution.exec.
|
204
204
|
def self.getconf_cpu_version(command="getconf CPU_VERSION")
|
205
|
-
Facter::
|
205
|
+
Facter::Core::Execution.exec(command)
|
206
206
|
end
|
207
207
|
|
208
208
|
##
|
209
|
-
# getconf_cpu_chip_type delegates directly to Facter::
|
209
|
+
# getconf_cpu_chip_type delegates directly to Facter::Core::Execution.exec.
|
210
210
|
def self.getconf_cpu_chip_type(command="getconf CPU_CHIP_TYPE")
|
211
|
-
Facter::
|
211
|
+
Facter::Core::Execution.exec(command)
|
212
212
|
end
|
213
213
|
|
214
214
|
def self.enum_cpuinfo
|
@@ -272,7 +272,7 @@ module Processor
|
|
272
272
|
processor_num = -1
|
273
273
|
processor_list = []
|
274
274
|
Thread::exclusive do
|
275
|
-
kstat = Facter::
|
275
|
+
kstat = Facter::Core::Execution.exec('/usr/bin/kstat cpu_info')
|
276
276
|
if kstat
|
277
277
|
kstat.each_line do |l|
|
278
278
|
if l =~ /cpu_info(\d+)/
|
@@ -1,329 +1,152 @@
|
|
1
|
-
# An actual fact resolution mechanism. These are largely just chunks of
|
2
|
-
# code, with optional confinements restricting the mechanisms to only working on
|
3
|
-
# specific systems. Note that the confinements are always ANDed, so any
|
4
|
-
# confinements specified must all be true for the resolution to be
|
5
|
-
# suitable.
|
6
1
|
require 'facter/util/confine'
|
7
2
|
require 'facter/util/config'
|
8
|
-
|
9
|
-
require '
|
10
|
-
|
3
|
+
require 'facter/util/normalization'
|
4
|
+
require 'facter/core/execution'
|
5
|
+
require 'facter/core/resolvable'
|
6
|
+
require 'facter/core/suitable'
|
7
|
+
|
8
|
+
# This represents a fact resolution. A resolution is a concrete
|
9
|
+
# implementation of a fact. A single fact can have many resolutions and
|
10
|
+
# the correct resolution will be chosen at runtime. Each time
|
11
|
+
# {Facter.add} is called, a new resolution is created and added to the
|
12
|
+
# set of resolutions for the fact named in the call. Each resolution
|
13
|
+
# has a {#has_weight weight}, which defines its priority over other
|
14
|
+
# resolutions, and a set of {#confine _confinements_}, which defines the
|
15
|
+
# conditions under which it will be chosen. All confinements must be
|
16
|
+
# satisfied for a fact to be considered _suitable_.
|
17
|
+
#
|
18
|
+
# @api public
|
11
19
|
class Facter::Util::Resolution
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
INTERPRETER = Facter::Util::Config.is_windows? ? "cmd.exe" : "/bin/sh"
|
20
|
+
# @api private
|
21
|
+
attr_accessor :code
|
22
|
+
attr_writer :value
|
16
23
|
|
17
|
-
|
18
|
-
# is currently determined by the +PATH+ environment variable plus
|
19
|
-
# <tt>/sbin</tt> and <tt>/usr/sbin</tt> when run on unix
|
20
|
-
def self.search_paths
|
21
|
-
if Facter::Util::Config.is_windows?
|
22
|
-
ENV['PATH'].split(File::PATH_SEPARATOR)
|
23
|
-
else
|
24
|
-
# Make sure facter is usable even for non-root users. Most commands
|
25
|
-
# in /sbin (like ifconfig) can be run as non priviledged users as
|
26
|
-
# long as they do not modify anything - which we do not do with facter
|
27
|
-
ENV['PATH'].split(File::PATH_SEPARATOR) + [ '/sbin', '/usr/sbin' ]
|
28
|
-
end
|
29
|
-
end
|
24
|
+
extend Facter::Core::Execution
|
30
25
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
if absolute_path?(bin)
|
39
|
-
return bin if File.executable?(bin)
|
40
|
-
if Facter::Util::Config.is_windows? and File.extname(bin).empty?
|
41
|
-
exts = ENV['PATHEXT']
|
42
|
-
exts = exts ? exts.split(File::PATH_SEPARATOR) : %w[.COM .EXE .BAT .CMD]
|
43
|
-
exts.each do |ext|
|
44
|
-
destext = bin + ext
|
45
|
-
if File.executable?(destext)
|
46
|
-
Facter.warnonce("Using Facter::Util::Resolution.which with an absolute path like #{bin} but no fileextension is deprecated. Please add the correct extension (#{ext})")
|
47
|
-
return destext
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
else
|
52
|
-
search_paths.each do |dir|
|
53
|
-
dest = File.join(dir, bin)
|
54
|
-
if Facter::Util::Config.is_windows?
|
55
|
-
dest.gsub!(File::SEPARATOR, File::ALT_SEPARATOR)
|
56
|
-
if File.extname(dest).empty?
|
57
|
-
exts = ENV['PATHEXT']
|
58
|
-
exts = exts ? exts.split(File::PATH_SEPARATOR) : %w[.COM .EXE .BAT .CMD]
|
59
|
-
exts.each do |ext|
|
60
|
-
destext = dest + ext
|
61
|
-
return destext if File.executable?(destext)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
return dest if File.executable?(dest)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
nil
|
26
|
+
class << self
|
27
|
+
# Expose command execution methods that were extracted into
|
28
|
+
# Facter::Util::Execution from Facter::Util::Resolution in Facter 2.0.0 for
|
29
|
+
# compatibility.
|
30
|
+
#
|
31
|
+
# @deprecated
|
32
|
+
public :search_paths, :which, :absolute_path?, :expand_command, :with_env, :exec
|
69
33
|
end
|
70
34
|
|
71
|
-
|
72
|
-
|
73
|
-
def self.absolute_path?(path, platform=nil)
|
74
|
-
# Escape once for the string literal, and once for the regex.
|
75
|
-
slash = '[\\\\/]'
|
76
|
-
name = '[^\\\\/]+'
|
77
|
-
regexes = {
|
78
|
-
:windows => %r!^(([A-Z]:#{slash})|(#{slash}#{slash}#{name}#{slash}#{name})|(#{slash}#{slash}\?#{slash}#{name}))!i,
|
79
|
-
:posix => %r!^/!,
|
80
|
-
}
|
81
|
-
platform ||= Facter::Util::Config.is_windows? ? :windows : :posix
|
35
|
+
include Facter::Core::Resolvable
|
36
|
+
include Facter::Core::Suitable
|
82
37
|
|
83
|
-
|
84
|
-
|
38
|
+
# @!attribute [rw] name
|
39
|
+
# The name of this resolution. The resolution name should be unique with
|
40
|
+
# respect to the given fact.
|
41
|
+
# @return [String]
|
42
|
+
# @api public
|
43
|
+
attr_accessor :name
|
85
44
|
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
|
90
|
-
# Returns the commandline with the expanded binary or nil if the binary
|
91
|
-
# can't be found. If the path to the binary contains quotes, the whole binary
|
92
|
-
# is put in quotes.
|
93
|
-
def self.expand_command(command)
|
94
|
-
if match = /^"(.+?)"(?:\s+(.*))?/.match(command)
|
95
|
-
exe, arguments = match.captures
|
96
|
-
exe = which(exe) and [ "\"#{exe}\"", arguments ].compact.join(" ")
|
97
|
-
elsif match = /^'(.+?)'(?:\s+(.*))?/.match(command) and not Facter::Util::Config.is_windows?
|
98
|
-
exe, arguments = match.captures
|
99
|
-
exe = which(exe) and [ "'#{exe}'", arguments ].compact.join(" ")
|
100
|
-
else
|
101
|
-
exe, arguments = command.split(/ /,2)
|
102
|
-
if exe = which(exe)
|
103
|
-
# the binary was not quoted which means it contains no spaces. But the
|
104
|
-
# full path to the binary may do so.
|
105
|
-
exe = "\"#{exe}\"" if exe =~ /\s/ and Facter::Util::Config.is_windows?
|
106
|
-
exe = "'#{exe}'" if exe =~ /\s/ and not Facter::Util::Config.is_windows?
|
107
|
-
[ exe, arguments ].compact.join(" ")
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
45
|
+
# @!attribute [r] fact
|
46
|
+
# @return [Facter::Util::Fact]
|
47
|
+
# @api private
|
48
|
+
attr_reader :fact
|
111
49
|
|
50
|
+
# Create a new resolution mechanism.
|
112
51
|
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
# of your block, after which the original values (if any) will be restored.
|
52
|
+
# @param name [String] The name of the resolution.
|
53
|
+
# @return [void]
|
116
54
|
#
|
117
|
-
#
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
end
|
126
|
-
# set the new (temporary) value for the environment variable
|
127
|
-
ENV[var] = value
|
128
|
-
end
|
129
|
-
# execute the caller's block, capture the return value
|
130
|
-
rv = yield
|
131
|
-
# use an ensure block to make absolutely sure we restore the variables
|
132
|
-
ensure
|
133
|
-
# restore the old values
|
134
|
-
values.each do |var, value|
|
135
|
-
if old.include?(var)
|
136
|
-
ENV[var] = old[var]
|
137
|
-
else
|
138
|
-
# if there was no old value, delete the key from the current environment variables hash
|
139
|
-
ENV.delete(var)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
# return the captured return value
|
143
|
-
rv
|
55
|
+
# @api private
|
56
|
+
def initialize(name, fact)
|
57
|
+
@name = name
|
58
|
+
@fact = fact
|
59
|
+
@confines = []
|
60
|
+
@value = nil
|
61
|
+
@timeout = 0
|
62
|
+
@weight = nil
|
144
63
|
end
|
145
64
|
|
146
|
-
#
|
147
|
-
#
|
148
|
-
# Returns nil if the program can't be found, or if there is a problem
|
149
|
-
# executing the code.
|
65
|
+
# Evaluate the given block in the context of this resolution. If a block has
|
66
|
+
# already been evaluated emit a warning to that effect.
|
150
67
|
#
|
151
|
-
|
152
|
-
|
68
|
+
# @return [void]
|
69
|
+
def evaluate(&block)
|
70
|
+
if @last_evaluated
|
71
|
+
msg = "Already evaluated #{@name}"
|
72
|
+
msg << " at #{@last_evaluated}" if msg.is_a? String
|
73
|
+
msg << ", reevaluating anyways"
|
74
|
+
Facter.warn msg
|
75
|
+
end
|
153
76
|
|
154
|
-
|
155
|
-
## output of the command can expect it to be in a consistent / predictable format / locale
|
156
|
-
with_env "LANG" => "C" do
|
157
|
-
|
158
|
-
if expanded_code = expand_command(code)
|
159
|
-
# if we can find the binary, we'll run the command with the expanded path to the binary
|
160
|
-
code = expanded_code
|
161
|
-
else
|
162
|
-
# if we cannot find the binary return nil on posix. On windows we'll still try to run the
|
163
|
-
# command in case it is a shell-builtin. In case it is not, windows will raise Errno::ENOENT
|
164
|
-
return nil unless Facter::Util::Config.is_windows?
|
165
|
-
return nil if absolute_path?(code)
|
166
|
-
end
|
167
|
-
|
168
|
-
out = nil
|
77
|
+
instance_eval(&block)
|
169
78
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
Facter.warn(detail)
|
178
|
-
return nil
|
179
|
-
end
|
180
|
-
|
181
|
-
if out == ""
|
182
|
-
return nil
|
183
|
-
else
|
184
|
-
return out
|
185
|
-
end
|
79
|
+
# Ruby 1.9+ provides the source location of procs which can provide useful
|
80
|
+
# debugging information if a resolution is being evaluated twice. Since 1.8
|
81
|
+
# doesn't support this we opportunistically provide this information.
|
82
|
+
if block.respond_to? :source_location
|
83
|
+
@last_evaluated = block.source_location.join(':')
|
84
|
+
else
|
85
|
+
@last_evaluated = true
|
186
86
|
end
|
187
87
|
end
|
188
88
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
@confines.push Facter::Util::Confine.new(fact, *values)
|
89
|
+
def set_options(options)
|
90
|
+
if options[:name]
|
91
|
+
@name = options.delete(:name)
|
193
92
|
end
|
194
|
-
end
|
195
|
-
|
196
|
-
def has_weight(weight)
|
197
|
-
@weight = weight
|
198
|
-
end
|
199
93
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
@confines = []
|
204
|
-
@value = nil
|
205
|
-
@timeout = 0
|
206
|
-
@weight = nil
|
207
|
-
end
|
94
|
+
if options.has_key?(:value)
|
95
|
+
@value = options.delete(:value)
|
96
|
+
end
|
208
97
|
|
209
|
-
|
210
|
-
|
211
|
-
if @weight
|
212
|
-
@weight
|
213
|
-
else
|
214
|
-
@confines.length
|
98
|
+
if options.has_key?(:timeout)
|
99
|
+
@timeout = options.delete(:timeout)
|
215
100
|
end
|
216
|
-
end
|
217
101
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
def limit
|
222
|
-
@timeout
|
223
|
-
end
|
102
|
+
if options.has_key?(:weight)
|
103
|
+
@weight = options.delete(:weight)
|
104
|
+
end
|
224
105
|
|
225
|
-
|
226
|
-
|
227
|
-
Facter.warnonce "The interpreter parameter to 'setcode' is deprecated and will be removed in a future version." if interp
|
228
|
-
if string
|
229
|
-
@code = string
|
230
|
-
@interpreter = interp || INTERPRETER
|
231
|
-
else
|
232
|
-
unless block_given?
|
233
|
-
raise ArgumentError, "You must pass either code or a block"
|
234
|
-
end
|
235
|
-
@code = block
|
106
|
+
if not options.keys.empty?
|
107
|
+
raise ArgumentError, "Invalid resolution options #{options.keys.inspect}"
|
236
108
|
end
|
237
109
|
end
|
238
110
|
|
239
|
-
|
240
|
-
#
|
241
|
-
# is flushed. This makes it possible to model a single, expensive system
|
242
|
-
# call inside of a Ruby object and then define multiple dynamic facts which
|
243
|
-
# resolve by sending messages to the model instance. If one of the dynamic
|
244
|
-
# facts is flushed then it can, in turn, flush the data stored in the model
|
245
|
-
# instance to keep all of the dynamic facts in sync without making multiple,
|
246
|
-
# expensive, system calls.
|
247
|
-
#
|
248
|
-
# Please see the Solaris zones fact for an example of how this feature may be
|
249
|
-
# used.
|
111
|
+
# Sets the code block or external program that will be evaluated to
|
112
|
+
# get the value of the fact.
|
250
113
|
#
|
251
|
-
# @
|
252
|
-
# @see Facter::Util::Resolution#flush
|
114
|
+
# @return [void]
|
253
115
|
#
|
254
|
-
# @
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
##
|
260
|
-
# flush executes the block, if any, stored by the {on_flush} method
|
116
|
+
# @overload setcode(string)
|
117
|
+
# Sets an external program to call to get the value of the resolution
|
118
|
+
# @param [String] string the external program to run to get the
|
119
|
+
# value
|
261
120
|
#
|
262
|
-
# @
|
263
|
-
#
|
121
|
+
# @overload setcode(&block)
|
122
|
+
# Sets the resolution's value by evaluating a block at runtime
|
123
|
+
# @param [Proc] block The block to determine the resolution's value.
|
124
|
+
# This block is run when the fact is evaluated. Errors raised from
|
125
|
+
# inside the block are rescued and printed to stderr.
|
264
126
|
#
|
265
|
-
# @api
|
266
|
-
def
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
Facter.warnonce "The 'Facter::Util::Resolution.interpreter=' method is deprecated and will be removed in a future version."
|
277
|
-
@interpreter = interp
|
278
|
-
end
|
279
|
-
|
280
|
-
# Is this resolution mechanism suitable on the system in question?
|
281
|
-
def suitable?
|
282
|
-
unless defined? @suitable
|
283
|
-
@suitable = ! @confines.detect { |confine| ! confine.true? }
|
127
|
+
# @api public
|
128
|
+
def setcode(string = nil, &block)
|
129
|
+
if string
|
130
|
+
@code = Proc.new do
|
131
|
+
output = Facter::Core::Execution.exec(string)
|
132
|
+
output.empty? ? nil : output
|
133
|
+
end
|
134
|
+
elsif block_given?
|
135
|
+
@code = block
|
136
|
+
else
|
137
|
+
raise ArgumentError, "You must pass either code or a block"
|
284
138
|
end
|
285
|
-
|
286
|
-
return @suitable
|
287
|
-
end
|
288
|
-
|
289
|
-
def to_s
|
290
|
-
return self.value()
|
291
139
|
end
|
292
140
|
|
293
|
-
|
294
|
-
def value
|
295
|
-
return @value if @value
|
296
|
-
result = nil
|
297
|
-
return result if @code == nil
|
141
|
+
private
|
298
142
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
result = Facter::Util::Resolution.exec(@code)
|
307
|
-
end
|
308
|
-
end
|
309
|
-
rescue Timeout::Error => detail
|
310
|
-
Facter.warn "Timed out seeking value for %s" % self.name
|
311
|
-
|
312
|
-
# This call avoids zombies -- basically, create a thread that will
|
313
|
-
# dezombify all of the child processes that we're ignoring because
|
314
|
-
# of the timeout.
|
315
|
-
Thread.new { Process.waitall }
|
316
|
-
return nil
|
317
|
-
rescue => details
|
318
|
-
Facter.warn "Could not retrieve %s: %s" % [self.name, details]
|
319
|
-
return nil
|
143
|
+
def resolve_value
|
144
|
+
if @value
|
145
|
+
@value
|
146
|
+
elsif @code.nil?
|
147
|
+
nil
|
148
|
+
elsif @code
|
149
|
+
@code.call()
|
320
150
|
end
|
321
|
-
|
322
|
-
finishtime = Time.now.to_f
|
323
|
-
ms = (finishtime - starttime) * 1000
|
324
|
-
Facter.show_time "#{self.name}: #{"%.2f" % ms}ms"
|
325
|
-
|
326
|
-
return nil if result == ""
|
327
|
-
return result
|
328
151
|
end
|
329
152
|
end
|