diff --git a/lib/custom_facts/core/execution/base.rb b/lib/custom_facts/core/execution/base.rb index 6b6e2b356..ddd336a6e 100644 --- a/lib/custom_facts/core/execution/base.rb +++ b/lib/custom_facts/core/execution/base.rb @@ -33,12 +33,17 @@ def with_env(values) def execute(command, options = {}) on_fail = options.fetch(:on_fail, :raise) + expand = options.fetch(:expand, true) # Set LC_ALL and LANG to force i18n to C for the duration of this exec; # this ensures that any code that parses the # output of the command can expect it to be in a consistent / predictable format / locale with_env 'LC_ALL' => 'C', 'LANG' => 'C' do - expanded_command = expand_command(command) + expanded_command = if !expand && builtin_command?(command) + command + else + expand_command(command) + end if expanded_command.nil? if on_fail == :raise @@ -49,17 +54,7 @@ def execute(command, options = {}) return on_fail end - begin - out, stderr, _status_ = Open3.capture3(expanded_command.to_s) - log_stderr_from_file(stderr, expanded_command) - rescue StandardError => e - return on_fail unless on_fail == :raise - - raise Facter::Core::Execution::ExecutionFailure.new, - "Failed while executing '#{expanded_command}': #{e.message}" - end - - out.strip + execute_command(expanded_command, on_fail) end end @@ -72,6 +67,24 @@ def log_stderr_from_file(msg, command) logger = Facter::Log.new(file_name) logger.warn(msg.strip) end + + def builtin_command?(command) + `type #{command}`.chomp =~ /builtin/ ? true : false + end + + def execute_command(command, on_fail) + begin + out, stderr, _status_ = Open3.capture3(command.to_s) + log_stderr_from_file(stderr, command) + rescue StandardError => e + return on_fail unless on_fail == :raise + + raise Facter::Core::Execution::ExecutionFailure.new, + "Failed while executing '#{command}': #{e.message}" + end + + out.strip + end end end end diff --git a/lib/custom_facts/core/execution/windows.rb b/lib/custom_facts/core/execution/windows.rb index 1ff0c2798..2693aaac0 100644 --- a/lib/custom_facts/core/execution/windows.rb +++ b/lib/custom_facts/core/execution/windows.rb @@ -57,6 +57,13 @@ def expand_command(command) expanded end + + def execute(command, options = {}) + expand = options.fetch(:expand, true) + raise ArgumentError.new, 'Unsupported argument on Windows expand with value false' unless expand + + super(command, options) + end end end end diff --git a/spec/custom_facts/core/execution/fact_manager_spec.rb b/spec/custom_facts/core/execution/fact_manager_spec.rb index b1278edfd..91f816b4a 100644 --- a/spec/custom_facts/core/execution/fact_manager_spec.rb +++ b/spec/custom_facts/core/execution/fact_manager_spec.rb @@ -73,6 +73,46 @@ def handy_method subject.execute('foo') end + context 'with expand on posix' do + subject(:execution_base) { LegacyFacter::Core::Execution::Posix.new } + + let(:test_env) { { 'LANG' => 'C', 'LC_ALL' => 'C', 'PATH' => '/sbin' } } + + before do + test_env.each do |key, value| + allow(ENV).to receive(:[]).with(key).and_return(value) + allow(File).to receive(:executable?).with('/bin/foo').and_return(true) + allow(FileTest).to receive(:file?).with('/bin/foo').and_return(true) + end + end + + it 'does not expant builtin command' do + allow(Open3).to receive(:capture3).with('/bin/foo').and_return('') + allow(Kernel).to receive(:'`').with('type /bin/foo').and_return 'builtin' + execution_base.execute('/bin/foo', expand: false) + end + end + + context 'with expand on windows' do + subject(:execution_base) { LegacyFacter::Core::Execution::Windows.new } + + let(:test_env) { { 'LANG' => 'C', 'LC_ALL' => 'C', 'PATH' => '/sbin' } } + + before do + test_env.each do |key, value| + allow(ENV).to receive(:[]).with(key).and_return(value) + end + end + + it 'throws exception' do + allow(Open3).to receive(:capture3).with('foo').and_return('') + allow(Kernel).to receive(:'`').with('type foo').and_return 'builtin' + expect { execution_base.execute('foo', expand: false) } + .to raise_error(ArgumentError, + 'Unsupported argument on Windows expand with value false') + end + end + context 'when there are stderr messages from file' do subject(:executor) { LegacyFacter::Core::Execution::Posix.new } diff --git a/spec/custom_facts/core/execution/windows_spec.rb b/spec/custom_facts/core/execution/windows_spec.rb index 0c0bdbd48..ff3d6e2f2 100644 --- a/spec/custom_facts/core/execution/windows_spec.rb +++ b/spec/custom_facts/core/execution/windows_spec.rb @@ -8,6 +8,18 @@ end end + describe '#execute' do + context 'with expand false' do + subject(:executor) { LegacyFacter::Core::Execution::Windows.new } + + it 'raises exception' do + expect { subject.execute('c:\foo.exe', expand: false) } + .to raise_error(ArgumentError, + 'Unsupported argument on Windows expand with value false') + end + end + end + describe '#which' do before do allow(subject)