class OctofactsUpdater::FactIndex
Constants
- TOP_LEVEL_NODES_KEY
We will create a pseudo-fact that simply lists all of the nodes that were considered in the index. Define the name of that pseudo-fact here.
Attributes
Public Class Methods
Load an index from the YAML file.
filename - A String with the file to be loaded.
Returns a OctofactsUpdater::FactIndex
object.
# File lib/octofacts_updater/fact_index.rb, line 33 def self.load_file(filename) unless File.file?(filename) raise Errno::ENOENT, "load_index cannot load #{filename.inspect}" end data = YAML.safe_load(File.read(filename)) new(data, filename: filename) end
Constructor.
data - A Hash of existing index data. filename - Optionally, a String with a file name to write the index to
# File lib/octofacts_updater/fact_index.rb, line 46 def initialize(data = {}, filename: nil) @index_data = data @filename = filename end
Public Instance Methods
Add a fact to the index. If the fact already exists in the index, this will overwrite it.
fact_name - A String with the name of the fact fixtures - An Array with fact fixtures (must respond to .facts and .hostname)
# File lib/octofacts_updater/fact_index.rb, line 55 def add(fact_name, fixtures) @index_data[fact_name] ||= {} fixtures.each do |fixture| fact_value = get_fact(fixture, fact_name) next if fact_value.nil? @index_data[fact_name][fact_value] ||= [] @index_data[fact_name][fact_value] << fixture.hostname end end
Get a list of all of the nodes in the index. This supports a quick mode (default) where the TOP_LEVEL_NODES_KEY
key is used, and a more detailed mode where this digs through each indexed fact and value to build a list of nodes.
quick_mode - Boolean whether to use quick mode (default=true)
Returns an Array of nodes whose facts are indexed.
# File lib/octofacts_updater/fact_index.rb, line 72 def nodes(quick_mode = true) if quick_mode && @index_data.key?(TOP_LEVEL_NODES_KEY) return @index_data[TOP_LEVEL_NODES_KEY] end seen_hosts = Set.new @index_data.each do |fact_name, fact_values| next if fact_name == TOP_LEVEL_NODES_KEY fact_values.each do |_fact_value, nodes| seen_hosts.merge(nodes) end end seen_hosts.to_a.sort end
# File lib/octofacts_updater/fact_index.rb, line 111 def recursive_sort(object_in) if object_in.is_a?(Hash) object_out = {} object_in.keys.sort.each { |k| object_out[k] = recursive_sort(object_in[k]) } object_out elsif object_in.is_a?(Array) object_in.sort.map { |v| recursive_sort(v) } else object_in end end
Rebuild an index with a specified list of facts. This will remove any indexed facts that are not on the list of facts to use.
facts_to_index - An Array of Strings with facts to index fixtures - An Array with fact fixtures (must respond to .facts and .hostname)
# File lib/octofacts_updater/fact_index.rb, line 92 def reindex(facts_to_index, fixtures) @index_data = {} facts_to_index.each { |fact| add(fact, fixtures) } set_top_level_nodes_fact(fixtures) end
Create the top level nodes pseudo-fact.
fixtures - An Array with fact fixtures (must respond to .hostname)
# File lib/octofacts_updater/fact_index.rb, line 101 def set_top_level_nodes_fact(fixtures) @index_data[TOP_LEVEL_NODES_KEY] = fixtures.map { |f| f.hostname }.sort end
Get YAML representation of the index. This sorts the hash and any arrays without modifying the object.
# File lib/octofacts_updater/fact_index.rb, line 107 def to_yaml YAML.dump(recursive_sort(index_data)) end
Write the fact index out to a YAML file.
filename - A String with the file to write (defaults to filename from constructor if available)
# File lib/octofacts_updater/fact_index.rb, line 126 def write_file(filename = nil) filename ||= @filename unless filename.is_a?(String) raise ArgumentError, "Called write_file() for fact_index without a filename" end File.open(filename, "w") { |f| f.write(to_yaml) } end
Private Instance Methods
Extract a (possibly) structured fact.
fixture - Fact
fixture, must respond to .facts fact_name - A String with the name of the fact
Returns the value of the fact, or nil if fact or structure does not exist.
# File lib/octofacts_updater/fact_index.rb, line 142 def get_fact(fixture, fact_name) pointer = fixture.facts # Get the fact of interest from the fixture, whether structured or not. components = fact_name.split(".") first_component = components.shift return unless pointer.key?(first_component) # For simple non-structured facts, just return the value. return pointer[first_component].value if components.empty? # Structured facts: dig into the structure. pointer = pointer[first_component].value last_component = components.pop components.each do |part| return unless pointer.key?(part) return unless pointer[part].is_a?(Hash) pointer = pointer[part] end pointer[last_component] end