Parent

Facter::Util::Resolution

Constants

INTERPRETER

Attributes

interpreter[RW]
code[RW]
name[RW]
timeout[RW]

Public Class Methods

absolute_path?(path, platform=nil) click to toggle source

Determine in a platform-specific way whether a path is absolute. This defaults to the local platform if none is specified.

    # File lib/facter/util/resolution.rb, line 72
72:   def self.absolute_path?(path, platform=nil)
73:     # Escape once for the string literal, and once for the regex.
74:     slash = '[\\/]'
75:     name = '[^\\/]+'
76:     regexes = {
77:       :windows => %^(([A-Z]:#{slash})|(#{slash}#{slash}#{name}#{slash}#{name})|(#{slash}#{slash}\?#{slash}#{name}))!,
78:       :posix   => %^/!,
79:     }
80:     platform ||= Facter::Util::Config.is_windows? ? :windows : :posix
81: 
82:     !! (path =~ regexes[platform])
83:   end
exec(code, interpreter = nil) click to toggle source

Execute a program and return the output of that program.

Returns nil if the program can’t be found, or if there is a problem executing the code.

     # File lib/facter/util/resolution.rb, line 117
117:   def self.exec(code, interpreter = nil)
118:     Facter.warnonce "The interpreter parameter to 'exec' is deprecated and will be removed in a future version." if interpreter
119: 
120:     if expanded_code = expand_command(code)
121:       # if we can find the binary, we'll run the command with the expanded path to the binary
122:       code = expanded_code
123:     else
124:       # if we cannot find the binary return nil on posix. On windows we'll still try to run the
125:       # command in case it is a shell-builtin. In case it is not, windows will raise Errno::ENOENT
126:       return nil unless Facter::Util::Config.is_windows?
127:       return nil if absolute_path?(code)
128:     end
129: 
130:     out = nil
131: 
132:     begin
133:       out = %{#{code}}.chomp
134:       Facter.warnonce 'Using Facter::Util::Resolution.exec with a shell built-in is deprecated. Most built-ins can be replaced with native ruby commands. If you really have to run a built-in, pass "cmd /c your_builtin" as a command' unless expanded_code
135:     rescue Errno::ENOENT => detail
136:       # command not found on Windows
137:       return nil
138:     rescue => detail
139:       $stderr.puts detail
140:       return nil
141:     end
142: 
143:     if out == ""
144:       return nil
145:     else
146:       return out
147:     end
148:   end
expand_command(command) click to toggle source

Expand the executable of a commandline to an absolute path. The executable is the first word of the commandline. If the executable contains spaces, it has be but in double quotes to be properly recognized.

Returns the commandline with the expanded binary or nil if the binary can’t be found. If the path to the binary contains quotes, the whole binary is put in quotes.

     # File lib/facter/util/resolution.rb, line 92
 92:   def self.expand_command(command)
 93:     if match = /^"(.+?)"(?:\s+(.*))?/.match(command)
 94:       exe, arguments = match.captures
 95:       exe = which(exe) and [ "\"#{exe}\"", arguments ].compact.join(" ")
 96:     elsif match = /^'(.+?)'(?:\s+(.*))?/.match(command) and not Facter::Util::Config.is_windows?
 97:       exe, arguments = match.captures
 98:       exe = which(exe) and [ "'#{exe}'", arguments ].compact.join(" ")
 99:     else
100:       exe, arguments = command.split(/ /,2)
101:       if exe = which(exe)
102:         # the binary was not quoted which means it contains no spaces. But the
103:         # full path to the binary may do so.
104:         exe = "\"#{exe}\"" if exe =~ /\s/ and Facter::Util::Config.is_windows?
105:         exe = "'#{exe}'" if exe =~ /\s/ and not Facter::Util::Config.is_windows?
106:         [ exe, arguments ].compact.join(" ")
107:       end
108:     end
109:   end
new(name) click to toggle source

Create a new resolution mechanism.

     # File lib/facter/util/resolution.rb, line 162
162:   def initialize(name)
163:     @name = name
164:     @confines = []
165:     @value = nil
166:     @timeout = 0
167:     @weight = nil
168:   end
search_paths() click to toggle source

Returns the locations to be searched when looking for a binary. This is currently determined by the PATH environment variable plus /sbin and /usr/sbin when run on unix

    # File lib/facter/util/resolution.rb, line 19
19:   def self.search_paths
20:     if Facter::Util::Config.is_windows?
21:       ENV['PATH'].split(File::PATH_SEPARATOR)
22:     else
23:       # Make sure facter is usable even for non-root users. Most commands
24:       # in /sbin (like ifconfig) can be run as non priviledged users as
25:       # long as they do not modify anything - which we do not do with facter
26:       ENV['PATH'].split(File::PATH_SEPARATOR) + [ '/sbin', '/usr/sbin' ]
27:     end
28:   end
which(bin) click to toggle source

Determine the full path to a binary. If the supplied filename does not already describe an absolute path then different locations (determined by self.search_paths) will be searched for a match.

Returns nil if no matching executable can be found otherwise returns the expanded pathname.

    # File lib/facter/util/resolution.rb, line 36
36:   def self.which(bin)
37:     if absolute_path?(bin)
38:       return bin if File.executable?(bin)
39:       if Facter::Util::Config.is_windows? and File.extname(bin).empty?
40:         exts = ENV['PATHEXT']
41:         exts = exts ? exts.split(File::PATH_SEPARATOR) : ].COM .EXE .BAT .CMD]
42:         exts.each do |ext|
43:           destext = bin + ext
44:           if File.executable?(destext)
45:             Facter.warnonce("Using Facter::Util::Resolution.which with an absolute path like #{bin} but no fileextension is deprecated. Please add the correct extension (#{ext})")
46:             return destext
47:           end
48:         end
49:       end
50:     else
51:       search_paths.each do |dir|
52:         dest = File.join(dir, bin)
53:         if Facter::Util::Config.is_windows?
54:           dest.gsub!(File::SEPARATOR, File::ALT_SEPARATOR)
55:           if File.extname(dest).empty?
56:             exts = ENV['PATHEXT']
57:             exts = exts ? exts.split(File::PATH_SEPARATOR) : ].COM .EXE .BAT .CMD]
58:             exts.each do |ext|
59:               destext = dest + ext
60:               return destext if File.executable?(destext)
61:             end
62:           end
63:         end
64:         return dest if File.executable?(dest)
65:       end
66:     end
67:     nil
68:   end

Public Instance Methods

confine(confines) click to toggle source

Add a new confine to the resolution mechanism.

     # File lib/facter/util/resolution.rb, line 151
151:   def confine(confines)
152:     confines.each do |fact, values|
153:       @confines.push Facter::Util::Confine.new(fact, *values)
154:     end
155:   end
has_weight(weight) click to toggle source
     # File lib/facter/util/resolution.rb, line 157
157:   def has_weight(weight)
158:     @weight = weight
159:   end
interpreter() click to toggle source
     # File lib/facter/util/resolution.rb, line 200
200:   def interpreter
201:     Facter.warnonce "The 'Facter::Util::Resolution.interpreter' method is deprecated and will be removed in a future version."
202:     @interpreter
203:   end
interpreter=(interp) click to toggle source
     # File lib/facter/util/resolution.rb, line 205
205:   def interpreter=(interp)
206:     Facter.warnonce "The 'Facter::Util::Resolution.interpreter=' method is deprecated and will be removed in a future version."
207:     @interpreter = interp
208:   end
limit() click to toggle source

We need this as a getter for ‘timeout’, because some versions of ruby seem to already have a ‘timeout’ method and we can’t seem to override the instance methods, somehow.

     # File lib/facter/util/resolution.rb, line 182
182:   def limit
183:     @timeout
184:   end
setcode(string = nil, interp = nil, &block) click to toggle source

Set our code for returning a value.

     # File lib/facter/util/resolution.rb, line 187
187:   def setcode(string = nil, interp = nil, &block)
188:     Facter.warnonce "The interpreter parameter to 'setcode' is deprecated and will be removed in a future version." if interp
189:     if string
190:       @code = string
191:       @interpreter = interp || INTERPRETER
192:     else
193:       unless block_given?
194:         raise ArgumentError, "You must pass either code or a block"
195:       end
196:       @code = block
197:     end
198:   end
suitable?() click to toggle source

Is this resolution mechanism suitable on the system in question?

     # File lib/facter/util/resolution.rb, line 211
211:   def suitable?
212:     unless defined? @suitable
213:       @suitable = ! @confines.detect { |confine| ! confine.true? }
214:     end
215: 
216:     return @suitable
217:   end
to_s() click to toggle source
     # File lib/facter/util/resolution.rb, line 219
219:   def to_s
220:     return self.value()
221:   end
value() click to toggle source

How we get a value for our resolution mechanism.

     # File lib/facter/util/resolution.rb, line 224
224:   def value
225:     result = nil
226:     return result if @code == nil
227: 
228:     starttime = Time.now.to_f
229: 
230:     begin
231:       Timeout.timeout(limit) do
232:         if @code.is_a?(Proc)
233:           result = @code.call()
234:         else
235:           result = Facter::Util::Resolution.exec(@code)
236:         end
237:       end
238:     rescue Timeout::Error => detail
239:       warn "Timed out seeking value for %s" % self.name
240: 
241:       # This call avoids zombies -- basically, create a thread that will
242:       # dezombify all of the child processes that we're ignoring because
243:       # of the timeout.
244:       Thread.new { Process.waitall }
245:       return nil
246:     rescue => details
247:       warn "Could not retrieve %s: %s" % [self.name, details]
248:       return nil
249:     end
250: 
251:     finishtime = Time.now.to_f
252:     ms = (finishtime - starttime) * 1000
253:     Facter.show_time "#{self.name}: #{"%.2f" % ms}ms"
254: 
255:     return nil if result == ""
256:     return result
257:   end
weight() click to toggle source

Return the importance of this resolution.

     # File lib/facter/util/resolution.rb, line 171
171:   def weight
172:     if @weight
173:       @weight
174:     else
175:       @confines.length
176:     end
177:   end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.