class Facter::Util::Resolution

Constants

INTERPRETER

Attributes

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

Public Instance Methods

confine(confines) click to toggle source

Add a new confine to the resolution mechanism.

# File lib/facter/util/resolution.rb, line 80
def confine(confines)
  confines.each do |fact, values|
    @confines.push Facter::Util::Confine.new(fact, *values)
  end
end
has_weight(weight) click to toggle source
# File lib/facter/util/resolution.rb, line 86
def has_weight(weight)
  @weight = weight
end
interpreter=(interp) click to toggle source
# File lib/facter/util/resolution.rb, line 134
def interpreter=(interp)
  Facter.warnonce "The 'Facter::Util::Resolution.interpreter=' method is deprecated and will be removed in a future version."
  @interpreter = interp
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 111
def limit
  @timeout
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 116
def setcode(string = nil, interp = nil, &block)
  Facter.warnonce "The interpreter parameter to 'setcode' is deprecated and will be removed in a future version." if interp
  if string
    @code = string
    @interpreter = interp || INTERPRETER
  else
    unless block_given?
      raise ArgumentError, "You must pass either code or a block"
    end
    @code = block
  end
end
suitable?() click to toggle source

Is this resolution mechanism suitable on the system in question?

# File lib/facter/util/resolution.rb, line 140
def suitable?
  unless defined? @suitable
    @suitable = ! @confines.detect { |confine| ! confine.true? }
  end

  return @suitable
end
to_s() click to toggle source
# File lib/facter/util/resolution.rb, line 148
def to_s
  return self.value()
end
value() click to toggle source

How we get a value for our resolution mechanism.

# File lib/facter/util/resolution.rb, line 153
def value
  result = nil
  return result if @code == nil

  starttime = Time.now.to_f

  begin
    Timeout.timeout(limit) do
      if @code.is_a?(Proc)
        result = @code.call()
      else
        result = Facter::Util::Resolution.exec(@code)
      end
    end
  rescue Timeout::Error => detail
    warn "Timed out seeking value for %s" % self.name

    # This call avoids zombies -- basically, create a thread that will
    # dezombify all of the child processes that we're ignoring because
    # of the timeout.
    Thread.new { Process.waitall }
    return nil
  rescue => details
    warn "Could not retrieve %s: %s" % [self.name, details]
    return nil
  end

  finishtime = Time.now.to_f
  ms = (finishtime - starttime) * 1000
  Facter.show_time "#{self.name}: #{"%.2f" % ms}ms"

  return nil if result == ""
  return result
end
weight() click to toggle source

Return the importance of this resolution.

# File lib/facter/util/resolution.rb, line 100
def weight
  if @weight
    @weight
  else
    @confines.length
  end
end

Public Class Methods

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 33
def self.exec(code, interpreter = nil)
  Facter.warnonce "The interpreter parameter to 'exec' is deprecated and will be removed in a future version." if interpreter

  # Try to guess whether the specified code can be executed by looking at the
  # first word. If it cannot be found on the PATH defer on resolving the fact
  # by returning nil.
  # This only fails on shell built-ins, most of which are masked by stuff in
  # /bin or of dubious value anyways. In the worst case, "sh -c 'builtin'" can
  # be used to work around this limitation
  #
  # Windows' %x{} throws Errno::ENOENT when the command is not found, so we
  # can skip the check there. This is good, since builtins cannot be found
  # elsewhere.
  if have_which and !Facter::Util::Config.is_windows?
    path = nil
    binary = code.split.first
    if code =~ %r^\//
      path = binary
    else
      path = %x{which #{binary} 2>/dev/null}.chomp
      # we don't have the binary necessary
      return nil if path == "" or path.match(%rCommand not found\./)
    end

    return nil unless FileTest.exists?(path)
  end

  out = nil

  begin
    out = %x{#{code}}.chomp
  rescue Errno::ENOENT => detail
    # command not found on Windows
    return nil
  rescue => detail
    $stderr.puts detail
    return nil
  end

  if out == ""
    return nil
  else
    return out
  end
end
have_which() click to toggle source
# File lib/facter/util/resolution.rb, line 16
def self.have_which
  if ! defined?(@have_which) or @have_which.nil?
    if Facter.value(:kernel) == 'windows'
      @have_which = false
    else
      %x{which which >/dev/null 2>&1}
      @have_which = ($? == 0)
    end
  end
  @have_which
end
new(name) click to toggle source

Create a new resolution mechanism.

# File lib/facter/util/resolution.rb, line 91
def initialize(name)
  @name = name
  @confines = []
  @value = nil
  @timeout = 0
  @weight = nil
end