Skip to content
This repository has been archived by the owner on Jun 19, 2020. It is now read-only.

(FACT-2515) Define custom fact groups in facter.conf #491

Merged
merged 1 commit into from
May 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions facter.conf
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@ cli : {
verbose : false,
log-level : "warn"
}

fact-groups : {
cached-custom-facts : ["my_custom_fact"],
}
3 changes: 1 addition & 2 deletions lib/facter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ def to_user_output(cli_options, *args)
init_cli_options(cli_options, args)
logger.info("executed with command line: #{ARGV.drop(1).join(' ')}")
log_blocked_facts

resolved_facts = Facter::FactManager.instance.resolve_facts(args)
SessionCache.invalidate_all_caches
fact_formatter = Facter::FormatterFactory.build(Facter::Options.get)
Expand Down Expand Up @@ -331,7 +330,7 @@ def error_check(args, resolved_facts)
#
# @api private
def log_blocked_facts
block_list = Facter::FactGroups.new(Facter::Options[:config]).block_list
block_list = Options[:block_list]
return unless block_list.any? && Facter::Options[:block]

logger.debug("blocking collection of #{block_list.join("\s")} facts")
Expand Down
4 changes: 4 additions & 0 deletions lib/framework/config/config_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ def cli
@conf['cli']
end

def fact_groups
@conf['fact-groups']
end

def refresh_config(config_path)
@conf = File.readable?(config_path) ? Hocon.load(config_path) : {}
end
Expand Down
3 changes: 2 additions & 1 deletion lib/framework/config/fact_groups.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ def get_group_ttls(group_name)
def load_groups
config = ConfigReader.init(Options[:config])
@block_list = config.block_list || {}
@groups_ttls = ConfigReader.init(Options[:config]).ttls || {}
@groups_ttls = config.ttls || {}
@groups.merge!(config.fact_groups) if config.fact_groups
end

def ttls_to_seconds(ttls)
Expand Down
40 changes: 19 additions & 21 deletions lib/framework/core/cache_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@ def initialize
@groups = {}
@log = Log.new(self)
@fact_groups = Facter::FactGroups.new
end

def cache_dir
LegacyFacter::Util::Config.facts_cache_dir
@cache_dir = LegacyFacter::Util::Config.facts_cache_dir
end

def resolve_facts(searched_facts)
return searched_facts, [] if !File.directory?(cache_dir) || !Options[:cache]
return searched_facts, [] if !File.directory?(@cache_dir) || !Options[:cache]

facts = []
searched_facts.each do |fact|
Expand Down Expand Up @@ -48,7 +45,7 @@ def resolve_fact(searched_fact)

return unless group_cached?(group_name)

return if check_ttls(group_name).zero?
return unless check_ttls?(group_name)

data = read_group_json(group_name)
return unless data
Expand All @@ -73,24 +70,24 @@ def cache_fact(fact)
end

def write_cache
unless File.directory?(cache_dir)
unless File.directory?(@cache_dir)
require 'fileutils'
FileUtils.mkdir_p(cache_dir)
FileUtils.mkdir_p(@cache_dir)
end

@groups.each do |group_name, data|
next if check_ttls(group_name).zero?
next unless check_ttls?(group_name)

@log.debug("caching values for #{group_name} facts")
cache_file_name = File.join(cache_dir, group_name)
cache_file_name = File.join(@cache_dir, group_name)
File.write(cache_file_name, JSON.pretty_generate(data))
end
end

def read_group_json(group_name)
return @groups[group_name] if @groups.key?(group_name)

cache_file_name = File.join(cache_dir, group_name)
cache_file_name = File.join(@cache_dir, group_name)
data = nil
file = Util::FileHelper.safe_read(cache_file_name)
begin
Expand All @@ -107,24 +104,25 @@ def group_cached?(group_name)
cached
end

def check_ttls(group_name)
def check_ttls?(group_name)
ttls = @fact_groups.get_group_ttls(group_name)
return 0 unless ttls
return false unless ttls

cache_file_name = File.join(cache_dir, group_name)
return ttls unless File.readable?(cache_file_name)
cache_file_name = File.join(@cache_dir, group_name)
if File.readable?(cache_file_name)
file_time = File.mtime(cache_file_name)
expire_date = file_time + ttls
return true if expire_date > Time.now

file_time = File.mtime(cache_file_name)
expire_date = file_time + ttls
if expire_date < Time.now
File.delete(cache_file_name)
return ttls
end
expire_date.to_i

@log.debug("#{group_name} facts cache file expired/missing")
true
end

def delete_cache(group_name)
cache_file_name = File.join(cache_dir, group_name)
cache_file_name = File.join(@cache_dir, group_name)
File.delete(cache_file_name) if File.readable?(cache_file_name)
end
end
Expand Down
29 changes: 19 additions & 10 deletions lib/framework/core/options/config_file_options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,26 @@ def init(config_path = nil)

augment_config_path(config_path)

augment_all
end

def get
@options || {}
end

private

def augment_all
if Options.cli?
augment_cli(Facter::ConfigReader.cli)
augment_ruby(Facter::ConfigReader.global)
end
augment_custom(Facter::ConfigReader.global)
augment_external(Facter::ConfigReader.global)
augment_show_legacy(Facter::ConfigReader.global)
augment_facts(Facter::ConfigReader.ttls)
augment_facts(Facter::ConfigReader.ttls, Facter::ConfigReader.fact_groups)
end

def get
@options || {}
end

private

def augment_config_path(config_path)
@options[:config] = config_path
end
Expand Down Expand Up @@ -72,11 +76,16 @@ def augment_show_legacy(global_conf)
@options[:show_legacy] = global_conf['show-legacy'] unless global_conf['show-legacy'].nil?
end

def augment_facts(ttls)
blocked_facts = Facter::FactGroups.new.blocked_facts
@options[:blocked_facts] = blocked_facts unless blocked_facts.nil?
def augment_facts(ttls, groups)
fact_groups = Facter::FactGroups.new

@options[:blocked_facts] = fact_groups.blocked_facts unless fact_groups.blocked_facts.nil?
@options[:block_list] = fact_groups.block_list
@options[:ttls] = ttls unless ttls.nil?

f_groups = fact_groups.groups || {}
f_groups = groups.merge(f_groups) unless groups.nil?
@options[:fact_groups] = f_groups
end
end
end
Expand Down
19 changes: 14 additions & 5 deletions lib/framework/core/options/option_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@ class OptionStore
@cache = true
@blocked_facts = []
@user_query = []
@block_list = {}
@fact_groups = {}

class << self
attr_reader :debug, :verbose, :log_level, :show_legacy, :trace, :ruby,
:custom_facts, :blocked_facts

attr_accessor :config, :user_query, :strict, :json, :haml, :external_facts,
:cache, :yaml, :puppet, :ttls, :block, :cli, :config_file_custom_dir,
:config_file_external_dir, :default_external_dir
:config_file_external_dir, :default_external_dir, :fact_groups,
:block_list

attr_writer :external_dir

Expand Down Expand Up @@ -152,16 +155,22 @@ def reset
@log_level = :warn
@show_legacy = true
@block = true
@ruby = true
@user_query = []
@cli = nil
@cache = true
reset_config
end

def reset_config
@custom_dir = []
@custom_facts = true
@external_dir = []
@default_external_dir = []
@external_facts = true
@ruby = true
@blocked_facts = []
@user_query = []
@cli = nil
@cache = true
@fact_groups = {}
@block_list = {}
end

def fallback_external_dir
Expand Down
10 changes: 5 additions & 5 deletions spec/facter/facter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@
let(:fact_collection_spy) { instance_spy(Facter::FactCollection) }
let(:key_error) { KeyError.new('key error') }
let(:config_reader_double) { double(Facter::ConfigReader) }
let(:block_list_double) { instance_spy(Facter::FactGroups) }

before do
allow(Facter::ConfigReader).to receive(:init).and_return(config_reader_double)
allow(config_reader_double).to receive(:cli).and_return(nil)
allow(config_reader_double).to receive(:global).and_return(nil)
allow(config_reader_double).to receive(:ttls).and_return([])
allow(config_reader_double).to receive(:block_list).and_return([])
allow(config_reader_double).to receive(:fact_groups).and_return({})

allow(Facter::FactGroups).to receive(:new).and_return(block_list_double)
allow(block_list_double).to receive(:blocked_facts).and_return([])
allow(block_list_double).to receive(:block_list).and_return([])
allow(Facter::Options).to receive(:[]).and_call_original
allow(Facter::Options).to receive(:[]).with(:blocked_facts).and_return([])
allow(Facter::Options).to receive(:[]).with(:block_list).and_return([])

allow(Facter::Log).to receive(:new).and_return(logger)
Facter.clear
Expand Down Expand Up @@ -99,7 +99,6 @@ def mock_collection(method, os_name = nil, error = nil)
it 'returns no fact and status 1', resolved_fact: false do
user_query = ['os.name', 'missing_fact']
expected_json_output = '{}'
allow(Facter::Options).to receive(:[]).and_call_original
allow(Facter::Options).to receive(:[]).with(:strict).and_return(true)

formatted_facts = Facter.to_user_output({}, *user_query)
Expand All @@ -111,6 +110,7 @@ def mock_collection(method, os_name = nil, error = nil)
user_query = 'os.name'
expected_json_output = '{"os" : {"name": "ubuntu"}'
allow(Facter::Options).to receive(:[]).with(anything)
allow(Facter::Options).to receive(:[]).with(:block_list).and_return([])
allow(Facter::Options).to receive(:[]).with(:strict).and_return(true)

formated_facts = Facter.to_user_output({}, user_query)
Expand Down
29 changes: 29 additions & 0 deletions spec/framework/config/config_reader_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,33 @@
end
end
end

describe '#fact-groups' do
let(:os) { :linux }

before do
allow(File).to receive(:readable?).and_return(true)
allow(Hocon).to receive(:load).and_return(config)
end

context 'with empty config file' do
let(:config) { {} }

it 'returns nil' do
config_reader.init

expect(config_reader.fact_groups).to eq(nil)
end
end

context 'with fact-groups in config file' do
let(:config) { { 'fact-groups' => { 'cached-custom-facts' => ['my_custom_fact'] } } }

it 'returns fact-groups' do
config_reader.init

expect(config_reader.fact_groups).to eq('cached-custom-facts' => ['my_custom_fact'])
end
end
end
end
17 changes: 17 additions & 0 deletions spec/framework/config/fact_groups_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
allow(Facter::ConfigReader).to receive(:init).and_return(config_reader)
allow(config_reader).to receive(:block_list).and_return([])
allow(config_reader).to receive(:ttls).and_return([])
allow(config_reader).to receive(:fact_groups).and_return({})
end

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add tests for merging of default groups with user defined groups.

describe '#initialize' do
Expand All @@ -24,6 +25,22 @@

expect(blk_list.instance_variable_get(:@groups_file_path)).to eq(File.join(ROOT_DIR, 'fact_groups.conf'))
end

it 'merges groups from facter.conf' do
allow(config_reader).to receive(:fact_groups).and_return('foo' => 'bar')
fct_grp = fact_groups.new

expect(fct_grp.instance_variable_get(:@groups)).to include('foo' => 'bar')
end

it 'merges groups from facter.conf with default group override' do
allow(Hocon).to receive(:load).with(File.join(ROOT_DIR, 'fact_groups.conf'))
.and_return('kernel' => %w[kernel kernelversion])
allow(config_reader).to receive(:fact_groups).and_return('kernel' => 'foo')
fct_grp = fact_groups.new

expect(fct_grp.instance_variable_get(:@groups)).to eq('kernel' => 'foo')
end
end

describe '#blocked_facts' do
Expand Down
2 changes: 2 additions & 0 deletions spec/framework/core/options/option_store_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
it 'returns default values' do
expect(option_store.all).to eq(
block: true,
block_list: {},
blocked_facts: [],
cli: nil,
custom_dir: [],
Expand All @@ -25,6 +26,7 @@
config_file_external_dir: [],
default_external_dir: [],
external_facts: true,
fact_groups: {},
log_level: :warn,
ruby: true,
show_legacy: true,
Expand Down