Writing facts with aggregate resolutions
Aggregate resolutions allow you to split up the resolution of a fact into separate chunks.
By default, Facter merges hashes with hashes or arrays with arrays, resulting in a structured fact, but you can also aggregate the chunks into a flat fact using concatenation, addition, or any other function that you can express in Ruby code.
On this page:
Main components of aggregate resolutions
Aggregate resolutions have two key differences compared to simple resolutions: the presence
of chunk statements and the lack of
a setcode statement. The aggregate block is optional, and without it Facter merges hashes with hashes or arrays with arrays.
-
A call to
Facter.add(:fact_name, :type => :aggregate):-
Introduces a new fact or a new resolution for an existing fact with the same name.
-
The name can be either a symbol or a string.
-
The
:type => :aggregateparameter is required for aggregate resolutions. -
The rest of the fact is wrapped in the
addcall’sdo ... endblock.
-
-
Zero or more
confinestatements:-
Determine whether the resolution is suitable and (therefore is evaluated).
-
They can either match against the value of another fact or evaluate a Ruby block.
-
If given a symbol or string representing a fact name, a block is required and the block receives the fact’s value as an argument.
-
If given a hash, the keys are expected to be fact names. The values of the hash are either the expected fact values or an array of values to compare against.
-
If given a block, the confine is suitable if the block returns a value other than
nilorfalse.
-
-
An optional
has_weightstatement:-
Evaluates multiple resolutions for a fact from highest weight value to lowest.
-
Must be an integer greater than 0.
-
Defaults to the number of
confinestatements for the resolution.
-
-
One or more calls to
chunk, each containing:-
A name (as the argument to
chunk). -
A block of code, which is responsible for resolving the chunk to a value. The block’s return value is the value of the chunk; it can be any type, but is typically a hash or array.
-
-
An optional
aggregateblock:-
If absent, Facter automatically merges hashes with hashes or arrays with arrays.
-
To merge the chunks in any other way, you need to make a call to
aggregate, which takes a block of code. -
The block is passed one argument (
chunks, in the example), which is a hash of chunk name to chunk value for all the chunks in the resolution.
-
Example: Building a structured fact progressively
This example builds a new fact, networking_primary_sha, by progressively merging two chunks. One chunk encodes
each networking interface’s MAC address as an encoded base64 value, and the other determines
if each interface is the system’s primary interface.
require 'digest'
require 'base64'
Facter.add(:networking_primary_sha, :type => :aggregate) do
chunk(:sha256) do
interfaces = {}
Facter.value(:networking)['interfaces'].each do |interface, values|
if values['mac']
hash = Digest::SHA256.digest(values['mac'])
encoded = Base64.encode64(hash)
interfaces[interface] = {:mac_sha256 => encoded.strip}
end
end
interfaces
end
chunk(:primary?) do
interfaces = {}
Facter.value(:networking)['interfaces'].each do |interface, values|
interfaces[interface] = {:primary? => (interface == Facter.value(:networking)['primary'])}
end
interfaces
end
# Facter merges the return values for the two chunks
# automatically, so there's no aggregate statement.
end
The fact’s output is organized by network interface into hashes, each containing the two chunks:
{
bridge0 => {
mac_sha256 => "bfgEFV7m1V04HYU6UqzoNoVmnPIEKWRSUOU650j0Wkk=",
primary? => false
},
en0 => {
mac_sha256 => "6Fd3Ws2z+aIl8vNmClCbzxiO2TddyFBChMlIU+QB28c=",
primary? => true
},
...
}
Example: Building a flat fact progressively with addition
Facter.add(:total_free_memory_mb, :type => :aggregate) do
chunk(:physical_memory) do
Facter.value(:memoryfree_mb)
end
chunk(:virtual_memory) do
Facter.value(:swapfree_mb)
end
aggregate do |chunks|
# The return value for this block determines the value of the fact.
sum = 0
chunks.each_value do |i|
sum += i
end
sum
end
end
Related information