1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
require 'facter'
require 'facter/util/resolution'
class Facter::Util::Fact
TIMEOUT = 5
attr_accessor :name, :ldapname
# Create a new fact, with no resolution mechanisms.
def initialize(name, options = {})
@name = name.to_s.downcase.intern
# LAK:NOTE: This is slow for many options, but generally we won't have any and at
# worst we'll have one. If we add more, this should be made more efficient.
options.each do |name, value|
case name
when :ldapname; self.ldapname = value
else
raise ArgumentError, "Invalid fact option '%s'" % name
end
end
@ldapname ||= @name.to_s
@resolves = []
@searching = false
@value = nil
end
# Add a new resolution mechanism. This requires a block, which will then
# be evaluated in the context of the new mechanism.
def add(&block)
raise ArgumentError, "You must pass a block to Fact<instance>.add" unless block_given?
resolve = Facter::Util::Resolution.new(@name)
resolve.instance_eval(&block)
@resolves << resolve
# Immediately sort the resolutions, so that we always have
# a sorted list for looking up values.
@resolves.sort! { |a, b| b.weight <=> a.weight }
return resolve
end
# Flush any cached values.
def flush
@value = nil
@suitable = nil
end
# Return the value for a given fact. Searches through all of the mechanisms
# and returns either the first value or nil.
def value
return @value if @value
if @resolves.length == 0
Facter.debug "No resolves for %s" % @name
return nil
end
searching do
@value = nil
foundsuits = false
@value = @resolves.inject(nil) { |result, resolve|
next unless resolve.suitable?
foundsuits = true
tmp = resolve.value
break tmp unless tmp.nil? or tmp == ""
}
unless foundsuits
Facter.debug "Found no suitable resolves of %s for %s" % [@resolves.length, @name]
end
end
if @value.nil?
# nothing
Facter.debug("value for %s is still nil" % @name)
return nil
else
return @value
end
end
private
# Are we in the midst of a search?
def searching?
@searching
end
# Lock our searching process, so we never ge stuck in recursion.
def searching
if searching?
Facter.debug "Caught recursion on %s" % @name
# return a cached value if we've got it
if @value
return @value
else
return nil
end
end
# If we've gotten this far, we're not already searching, so go ahead and do so.
@searching = true
begin
yield
ensure
@searching = false
end
end
end
|