Wrapper around running a command
# File lib/foreman_maintain/utils/command_runner.rb, line 10 def initialize(logger, command, options) options.validate_options!(:stdin, :hidden_patterns, :interactive) @logger = logger @command = command @stdin = options[:stdin] @hidden_patterns = Array(options[:hidden_patterns]) @interactive = options[:interactive] @options = options raise ArgumentError, 'Can not pass stdin for interactive command' if @interactive && @stdin end
# File lib/foreman_maintain/utils/command_runner.rb, line 49 def execution_error raise Error::ExecutionError.new(hide_strings(@command), exit_status, hide_strings(@stdin), @interactive ? nil : hide_strings(@output)) end
# File lib/foreman_maintain/utils/command_runner.rb, line 40 def exit_status raise 'Command not yet executed' unless defined? @exit_status @exit_status end
# File lib/foreman_maintain/utils/command_runner.rb, line 31 def interactive? @interactive end
# File lib/foreman_maintain/utils/command_runner.rb, line 35 def output raise 'Command not yet executed' unless defined? @output @output end
# File lib/foreman_maintain/utils/command_runner.rb, line 21 def run logger.debug(hide_strings("Running command #{@command} with stdin #{@stdin.inspect}")) if @interactive run_interactively else run_non_interactively end logger.debug("output of the command:\n #{hide_strings(output)}") end
# File lib/foreman_maintain/utils/command_runner.rb, line 45 def success? exit_status == 0 end
# File lib/foreman_maintain/utils/command_runner.rb, line 91 def full_command "#{@command} 2>&1" end
# File lib/foreman_maintain/utils/command_runner.rb, line 95 def hide_strings(string) @hidden_patterns.reduce(string) do |result, hidden_pattern| result.gsub(hidden_pattern, '[FILTERED]') end end
rubocop:disable Metrics/AbcSize
# File lib/foreman_maintain/utils/command_runner.rb, line 59 def run_interactively # use tmp files to capture output and exit status of the command when # running interactively log_file = Tempfile.open('captured-output') exit_file = Tempfile.open('captured-exit-code') Kernel.system("script -qc '#{full_command}; echo $? > #{exit_file.path}' #{log_file.path}") File.open(log_file.path) { |f| @output = f.read } File.open(exit_file.path) do |f| exit_status = f.read.strip @exit_status = if exit_status.empty? 256 else exit_status.to_i end end ensure log_file.close exit_file.close end
rubocop:enable Metrics/AbcSize
# File lib/foreman_maintain/utils/command_runner.rb, line 80 def run_non_interactively IO.popen(full_command, 'r+') do |f| if @stdin f.puts(@stdin) f.close_write end @output = f.read.strip end @exit_status = $CHILD_STATUS.exitstatus end