From 1ec10ee5e6d331b47a7b0023a75020ced3f349dd Mon Sep 17 00:00:00 2001 From: BogdanIrimie Date: Thu, 23 Jul 2020 16:38:50 +0300 Subject: [PATCH 1/2] (FACT-2699) Detect augeas from gem if augparse is not available. --- lib/facter/resolvers/augeas_resolver.rb | 23 +++++- spec/facter/resolvers/augeas_resolver_spec.rb | 80 +++++++++++++++++-- spec/mocks/augeas.rb | 7 ++ spec/mocks/kernel_mock.rb | 2 +- 4 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 spec/mocks/augeas.rb diff --git a/lib/facter/resolvers/augeas_resolver.rb b/lib/facter/resolvers/augeas_resolver.rb index 2e1ee7bc11..80321521bb 100644 --- a/lib/facter/resolvers/augeas_resolver.rb +++ b/lib/facter/resolvers/augeas_resolver.rb @@ -14,10 +14,29 @@ def post_resolve(fact_name) end def read_augeas_version(fact_name) - output = Facter::Core::Execution.execute('augparse --version 2>&1', logger: log) - @fact_list[:augeas_version] = Regexp.last_match(1) if output =~ /^augparse (\d+\.\d+\.\d+)/ + @fact_list[:augeas_version] = read_augeas_from_cli + @fact_list[:augeas_version] ||= read_augeas_from_gem + @fact_list[fact_name] end + + def read_augeas_from_cli + output = Facter::Core::Execution.execute('augparse --version 2>&1', logger: log) + Regexp.last_match(1) if output =~ /^augparse (\d+\.\d+\.\d+)/ + end + + def read_augeas_from_gem + require 'augeas' + + return ::Augeas.create { |aug| aug.get('/augeas/version') } if ::Augeas.respond_to?(:create) + + # it is used for legacy augeas <= 0.5.0 + return ::Augeas.open { |aug| aug.get('/augeas/version') } if ::Augeas.respond_to?(:open) + rescue StandardError => e + log.debug('ruby-augeas not available') + log.log_exception(e) + nil + end end end end diff --git a/spec/facter/resolvers/augeas_resolver_spec.rb b/spec/facter/resolvers/augeas_resolver_spec.rb index feefda5046..afc9fb74bf 100644 --- a/spec/facter/resolvers/augeas_resolver_spec.rb +++ b/spec/facter/resolvers/augeas_resolver_spec.rb @@ -7,12 +7,82 @@ before do augeas.instance_variable_set(:@log, log_spy) - allow(Facter::Core::Execution).to receive(:execute) - .with('augparse --version 2>&1', logger: log_spy) - .and_return('augparse 1.12.0 ') end - it 'returns build' do - expect(augeas.resolve(:augeas_version)).to eq('1.12.0') + after do + augeas.invalidate_cache + end + + context 'when augparse is installed' do + before do + allow(Facter::Core::Execution).to receive(:execute) + .with('augparse --version 2>&1', logger: log_spy) + .and_return('augparse 1.12.0 ') + end + + it 'returns build' do + expect(augeas.resolve(:augeas_version)).to eq('1.12.0') + end + end + + context 'when augparse is not installed' do + before do + allow(Facter::Core::Execution).to receive(:execute) + .with('augparse --version 2>&1', logger: log_spy) + .and_return('sh: augparse: command not found') + end + + context 'when augeas gem > 0.5.0 is installed' do + let(:augeas_mock) { instance_spy(Augeas) } + + before do + allow(Augeas).to receive(:respond_to?).with(:create).and_return(true) + allow(Augeas).to receive(:respond_to?).with(:create, true).and_return(true) + allow(Augeas).to receive(:create).and_return('1.12.0') + end + + it 'returns build' do + expect(augeas.resolve(:augeas_version)).to eq('1.12.0') + end + end + + context 'when augeas gem <= 0.5.0 is installed' do + let(:augeas_mock) { instance_spy(Augeas) } + + before do + allow(Augeas).to receive(:respond_to?).with(:create).and_return(false) + allow(Augeas).to receive(:respond_to?).with(:open).and_return(true) + allow(Augeas).to receive(:respond_to?).with(:open, true).and_return(true) + allow(Augeas).to receive(:open).and_return('1.12.0') + end + + it 'returns build' do + expect(augeas.resolve(:augeas_version)).to eq('1.12.0') + end + end + + context 'when augeas gem is not installed' do + let(:exception) { StandardError.new('error_message') } + + before do + allow(Facter::Resolvers::Augeas).to receive(:require).with('augeas').and_raise(exception) + end + + it 'returns nil' do + expect(augeas.resolve(:augeas_version)).to be_nil + end + + it 'logs a debug message' do + augeas.resolve(:augeas_version) + + expect(log_spy).to have_received(:debug).with('ruby-augeas not available') + end + + it 'logs an exception' do + augeas.resolve(:augeas_version) + + expect(log_spy).to have_received(:log_exception).with(exception) + end + end end end diff --git a/spec/mocks/augeas.rb b/spec/mocks/augeas.rb new file mode 100644 index 0000000000..d6b61af045 --- /dev/null +++ b/spec/mocks/augeas.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class Augeas + def self.create(opts = {}, &block); end + + def self.open(root = nil, loadpath = nil, flags = NONE, &block); end +end diff --git a/spec/mocks/kernel_mock.rb b/spec/mocks/kernel_mock.rb index 245f2ac90e..9df9cef4b6 100644 --- a/spec/mocks/kernel_mock.rb +++ b/spec/mocks/kernel_mock.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -LIBS_TO_SKIP = %w[win32ole ffi win32/registry sys/filesystem].freeze +LIBS_TO_SKIP = %w[win32ole ffi win32/registry sys/filesystem augeas].freeze module Kernel alias old_require require def require(path) From 458f69e43c0eb4f136841124342b3dad6c3d84a4 Mon Sep 17 00:00:00 2001 From: BogdanIrimie Date: Fri, 24 Jul 2020 15:33:20 +0300 Subject: [PATCH 2/2] (FACT-2699) Detect augeas from gem if augparse is not available. --- lib/facter/resolvers/augeas_resolver.rb | 14 +++++----- spec/facter/resolvers/augeas_resolver_spec.rb | 27 ++++--------------- 2 files changed, 11 insertions(+), 30 deletions(-) diff --git a/lib/facter/resolvers/augeas_resolver.rb b/lib/facter/resolvers/augeas_resolver.rb index 80321521bb..0e21e61e5e 100644 --- a/lib/facter/resolvers/augeas_resolver.rb +++ b/lib/facter/resolvers/augeas_resolver.rb @@ -28,14 +28,12 @@ def read_augeas_from_cli def read_augeas_from_gem require 'augeas' - return ::Augeas.create { |aug| aug.get('/augeas/version') } if ::Augeas.respond_to?(:create) - - # it is used for legacy augeas <= 0.5.0 - return ::Augeas.open { |aug| aug.get('/augeas/version') } if ::Augeas.respond_to?(:open) - rescue StandardError => e - log.debug('ruby-augeas not available') - log.log_exception(e) - nil + if Gem.loaded_specs['augeas'] + ::Augeas.create { |aug| aug.get('/augeas/version') } + else + # it is used for legacy augeas <= 0.5.0 (ruby-augeas gem) + ::Augeas.open { |aug| aug.get('/augeas/version') } + end end end end diff --git a/spec/facter/resolvers/augeas_resolver_spec.rb b/spec/facter/resolvers/augeas_resolver_spec.rb index afc9fb74bf..eec11b108b 100644 --- a/spec/facter/resolvers/augeas_resolver_spec.rb +++ b/spec/facter/resolvers/augeas_resolver_spec.rb @@ -33,11 +33,8 @@ end context 'when augeas gem > 0.5.0 is installed' do - let(:augeas_mock) { instance_spy(Augeas) } - before do - allow(Augeas).to receive(:respond_to?).with(:create).and_return(true) - allow(Augeas).to receive(:respond_to?).with(:create, true).and_return(true) + allow(Gem).to receive(:loaded_specs).and_return({ 'augeas' => true }) allow(Augeas).to receive(:create).and_return('1.12.0') end @@ -47,12 +44,8 @@ end context 'when augeas gem <= 0.5.0 is installed' do - let(:augeas_mock) { instance_spy(Augeas) } - before do - allow(Augeas).to receive(:respond_to?).with(:create).and_return(false) - allow(Augeas).to receive(:respond_to?).with(:open).and_return(true) - allow(Augeas).to receive(:respond_to?).with(:open, true).and_return(true) + allow(Gem).to receive(:loaded_specs).and_return({}) allow(Augeas).to receive(:open).and_return('1.12.0') end @@ -62,26 +55,16 @@ end context 'when augeas gem is not installed' do - let(:exception) { StandardError.new('error_message') } + let(:exception) { LoadError.new('load_error_message') } before do allow(Facter::Resolvers::Augeas).to receive(:require).with('augeas').and_raise(exception) end - it 'returns nil' do - expect(augeas.resolve(:augeas_version)).to be_nil - end - - it 'logs a debug message' do - augeas.resolve(:augeas_version) - - expect(log_spy).to have_received(:debug).with('ruby-augeas not available') - end - - it 'logs an exception' do + it 'raises a LoadError error' do augeas.resolve(:augeas_version) - expect(log_spy).to have_received(:log_exception).with(exception) + expect(log_spy).to have_received(:debug).with('resolving fact augeas_version, but load_error_message') end end end