class Facter::Core::Aggregate

Attributes

confines[R]

@!attribute [r] confines

@return [Array<LegacyFacter::Core::Confine>] An array of confines restricting

this to a specific platform

@api private

deps[R]

@!attribute [r] deps

@return [LegacyFacter::Core::DirectedGraph]

@api private

fact[R]

@!attribute [r] fact

@return [Facter::Util::Fact]

@api private

fact_type[R]

@!attribute [r] fact_type

@return [Symbol] The fact type of the aggregate resolution

@api private

name[R]

@!attribute [r] name

@return [Symbol] The name of the aggregate resolution

@api public

Public Class Methods

new(name, fact) click to toggle source

Create a new aggregated resolution mechanism.

@param name [String] The name of the resolution. @param fact [Facter::Fact] The fact to which this

resolution will be added.

@return [Facter::Util::Resolution] The created resolution

@api private

# File lib/facter/custom_facts/core/aggregate.rb, line 65
def initialize(name, fact)
  @name = name
  @fact = fact

  @confines = []
  @chunks = {}

  @aggregate = nil
  @deps = LegacyFacter::Core::DirectedGraph.new
end

Public Instance Methods

<=>(other) click to toggle source

Compares the weight of two aggregate facts

@return [bool] Weight comparison result

@api private

# File lib/facter/custom_facts/core/aggregate.rb, line 81
def <=>(other)
  weight <=> other.weight
end
aggregate(&block) click to toggle source

Define how all chunks should be combined

@example Merge all chunks

aggregate.aggregate do |chunks|
  final_result = {}
  chunks.each_value do |chunk|
    final_result.deep_merge(chunk)
  end
  final_result
end

@example Sum all chunks

aggregate.aggregate do |chunks|
  total = 0
  chunks.each_value do |chunk|
    total += chunk
  end
  total
end

@yield [Hash<Symbol, Object>] A hash containing chunk names and

chunk values

@return [Facter::Core::Aggregate] The aggregate fact

@api public

# File lib/facter/custom_facts/core/aggregate.rb, line 167
def aggregate(&block)
  raise ArgumentError, "#{self.class.name}#aggregate requires a block" unless block_given?

  @aggregate = block
  self
end
chunk(name, opts = {}, &block) click to toggle source

Define a new chunk for the given aggregate

@example Defining a chunk with no dependencies

aggregate.chunk(:mountpoints) do
  # generate mountpoint information
end

@example Defining an chunk to add mount options

aggregate.chunk(:mount_options, :require => [:mountpoints]) do |mountpoints|
  # `mountpoints` is the result of the previous chunk
  # generate mount option information based on the mountpoints
end

@param name [Symbol] A name unique to this aggregate describing the chunk

@param opts [Hash] Hash with options for the aggregate fact

@return [Facter::Core::Aggregate] The aggregate object

@api public

# File lib/facter/custom_facts/core/aggregate.rb, line 127
def chunk(name, opts = {}, &block)
  evaluate_params(name, &block)

  deps = Array(opts.delete(:require))

  unless opts.empty?
    raise ArgumentError, "Unexpected options passed to #{self.class.name}#chunk: #{opts.keys.inspect}"
  end

  @deps[name] = deps
  @chunks[name] = block
  self
end
evaluate(&block) click to toggle source

Evaluates the given block

@return [String] Result of the block’s evaluation

@api private

# File lib/facter/custom_facts/core/aggregate.rb, line 103
def evaluate(&block)
  instance_eval(&block)
end
options(options) click to toggle source

Sets options for the aggregate fact

@return [nil]

@api private

# File lib/facter/custom_facts/core/aggregate.rb, line 90
def options(options)
  accepted_options = %i[name timeout weight fact_type]
  accepted_options.each do |option_name|
    instance_variable_set("@#{option_name}", options.delete(option_name)) if options.key?(option_name)
  end
  raise ArgumentError, "Invalid aggregate options #{options.keys.inspect}" unless options.keys.empty?
end
resolution_type() click to toggle source

Returns the fact’s resolution type

@return [Symbol] The fact’s type

@api private

# File lib/facter/custom_facts/core/aggregate.rb, line 179
def resolution_type
  :aggregate
end

Private Instance Methods

aggregate_results(results) click to toggle source

Process the results of all chunks with the aggregate block and return the results. If no aggregate block has been specified, fall back to deep merging the given data structure

@param results [Hash<Symbol, Object>] A hash of chunk names and the output

of that chunk.

@return [Object]

# File lib/facter/custom_facts/core/aggregate.rb, line 223
def aggregate_results(results)
  if @aggregate
    @aggregate.call(results)
  else
    default_aggregate(results)
  end
end
default_aggregate(results) click to toggle source
# File lib/facter/custom_facts/core/aggregate.rb, line 231
def default_aggregate(results)
  results.values.inject do |result, current|
    LegacyFacter::Util::Values.deep_merge(result, current)
  end
rescue LegacyFacter::Util::Values::DeepMergeError => e
  raise ArgumentError, 'Could not deep merge all chunks (Original error: ' \
                   "#{e.message}), ensure that chunks return either an Array or Hash or " \
                   'override the aggregate block', e.backtrace
end
evaluate_params(name) click to toggle source
# File lib/facter/custom_facts/core/aggregate.rb, line 185
def evaluate_params(name)
  raise ArgumentError, "#{self.class.name}#chunk requires a block" unless block_given?
  raise ArgumentError, "#{self.class.name}#expected chunk name to be a Symbol" unless name.is_a? Symbol
end
order_chunks() click to toggle source

Order chunks based on their dependencies

@return [Array<Symbol, Proc>] A list of chunk names and blocks in evaluation order.

# File lib/facter/custom_facts/core/aggregate.rb, line 244
def order_chunks
  unless @deps.acyclic?
    raise DependencyError,
          "Could not order chunks; found the following dependency cycles: #{@deps.cycles.inspect}"
  end

  sorted_names = @deps.tsort

  sorted_names.map do |name|
    [name, @chunks[name]]
  end
end
resolve_value() click to toggle source

Evaluate the results of this aggregate.

@see Facter::Core::Resolvable#value @return [Object]

# File lib/facter/custom_facts/core/aggregate.rb, line 194
def resolve_value
  chunk_results = run_chunks
  aggregate_results(chunk_results)
end
run_chunks() click to toggle source

Order all chunks based on their dependencies and evaluate each one, passing dependent chunks as needed.

@return [Hash<Symbol, Object>] A hash containing the chunk that

generated value and the related value.
# File lib/facter/custom_facts/core/aggregate.rb, line 204
def run_chunks
  results = {}
  order_chunks.each do |(name, block)|
    input = @deps[name].map { |dep_name| results[dep_name] }

    output = block.call(*input)
    results[name] = LegacyFacter::Util::Values.deep_freeze(output)
  end

  results
end