class Facter::QueryParser

Public Class Methods

construct_loaded_fact(query_tokens, loaded_fact) click to toggle source
# File lib/facter/framework/parsers/query_parser.rb, line 98
def construct_loaded_fact(query_tokens, loaded_fact)
  user_query = @query_list.any? ? query_tokens.join('.') : ''
  fact_name = loaded_fact.name.to_s
  klass_name = loaded_fact.klass
  type = loaded_fact.type
  sf = SearchedFact.new(fact_name, klass_name, user_query, type)
  sf.file = loaded_fact.file

  sf
end
found_fact?(fact_name, query_fact) click to toggle source
# File lib/facter/framework/parsers/query_parser.rb, line 81
def found_fact?(fact_name, query_fact)
  # This is the case where the fact_name contains a wildcard like
  # blockdevice_.*_model and we're querying for the legacy fact
  # specifically using 'blockdevice_sba_model' and we don't want the query
  # 'blockdevice.sba.model' to match
  fact_with_wildcard = fact_name.include?('.*') && !query_fact.include?('.')

  if fact_with_wildcard
    # fact_name contains wildcard, so we're intentially not escaping.
    query_fact.match("^#{fact_name}$")
  else
    processed_equery_fact = query_fact.gsub('\\', '\\\\\\\\')
    # Must escape metacharacters (like dots) to ensure the correct fact is found
    fact_name.match("^#{Regexp.escape(processed_equery_fact)}($|\\.)")
  end
end
get_facts_matching_tokens(query_tokens, query_fact, loaded_facts) click to toggle source
# File lib/facter/framework/parsers/query_parser.rb, line 67
def get_facts_matching_tokens(query_tokens, query_fact, loaded_facts)
  resolvable_fact_list = []

  loaded_facts.each do |loaded_fact|
    next unless found_fact?(loaded_fact.name, query_fact)

    searched_fact = construct_loaded_fact(query_tokens, loaded_fact)
    resolvable_fact_list << searched_fact
  end

  @log.debug "List of resolvable facts: #{resolvable_fact_list.inspect}" if resolvable_fact_list.any?
  resolvable_fact_list
end
no_user_query(loaded_facts) click to toggle source
# File lib/facter/framework/parsers/query_parser.rb, line 39
def no_user_query(loaded_facts)
  searched_facts = []
  loaded_facts.each do |loaded_fact|
    searched_facts << SearchedFact.new(loaded_fact.name, loaded_fact.klass, '', loaded_fact.type)
  end
  searched_facts
end
parse(query_list, loaded_facts) click to toggle source

Searches for facts that could resolve a user query. There are 4 types of facts:

root facts
  e.g. networking
child facts
  e.g. networking.dhcp
composite facts
  e.g. networking.interfaces.en0.bindings.address
regex facts (legacy)
  e.g. impaddress_end160

Because a root fact will always be resolved by a collection of child facts, we can return one or more child facts for each parent.

@param query_list [Array] The list of facts to search for @param loaded_facts [Array] All of the fact definitions for the current operating system

@return [Array<SearchedFact>] a list of searchable facts that resolve the user’s query

# File lib/facter/framework/parsers/query_parser.rb, line 25
def parse(query_list, loaded_facts)
  matched_facts = []
  @query_list = query_list

  return no_user_query(loaded_facts) unless query_list.any?

  query_list.each do |query|
    found_facts = search_for_facts(query, loaded_facts)
    matched_facts << found_facts
  end

  matched_facts.flatten(1)
end
search_for_facts(query, loaded_facts) click to toggle source
# File lib/facter/framework/parsers/query_parser.rb, line 47
def search_for_facts(query, loaded_facts)
  resolvable_fact_list = []
  query = query.to_s
  query_tokens = query.end_with?('.*') ? [query] : query.split('.')
  size = query_tokens.size

  # Try to match the most specific query_tokens to the least, returning the first match
  size.times do |i|
    query_token_range = 0..size - i - 1
    query_fact = query_tokens[query_token_range].join('.')
    resolvable_fact_list = get_facts_matching_tokens(query_tokens, query_fact, loaded_facts)

    return resolvable_fact_list if resolvable_fact_list.any?
  end

  resolvable_fact_list << SearchedFact.new(query, nil, query, :nil) if resolvable_fact_list.empty?

  resolvable_fact_list
end