class ForemanMaintain::Utils::CommandRunner
Wrapper around running a command
Attributes
command[R]
logger[R]
Public Class Methods
new(logger, command, options)
click to toggle source
# File lib/foreman_maintain/utils/command_runner.rb, line 10 def initialize(logger, command, options) options.validate_options!(:stdin, :hidden_patterns, :interactive, :valid_exit_statuses) options[:valid_exit_statuses] ||= [0] @logger = logger @command = command @stdin = options[:stdin] @hidden_patterns = Array(options[:hidden_patterns]).compact @interactive = options[:interactive] @options = options @valid_exit_statuses = options[:valid_exit_statuses] raise ArgumentError, 'Can not pass stdin for interactive command' if @interactive && @stdin end
Public Instance Methods
execution_error()
click to toggle source
# File lib/foreman_maintain/utils/command_runner.rb, line 51 def execution_error raise Error::ExecutionError.new(hide_strings(@command), exit_status, hide_strings(@stdin), @interactive ? nil : hide_strings(@output)) end
exit_status()
click to toggle source
# File lib/foreman_maintain/utils/command_runner.rb, line 42 def exit_status raise 'Command not yet executed' unless defined? @exit_status @exit_status end
interactive?()
click to toggle source
# File lib/foreman_maintain/utils/command_runner.rb, line 33 def interactive? @interactive end
output()
click to toggle source
# File lib/foreman_maintain/utils/command_runner.rb, line 37 def output raise 'Command not yet executed' unless defined? @output @output end
run()
click to toggle source
# File lib/foreman_maintain/utils/command_runner.rb, line 23 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
success?()
click to toggle source
# File lib/foreman_maintain/utils/command_runner.rb, line 47 def success? @valid_exit_statuses.include? exit_status end
Private Instance Methods
full_command()
click to toggle source
# File lib/foreman_maintain/utils/command_runner.rb, line 94 def full_command "#{@command} 2>&1" end
hide_strings(string)
click to toggle source
# File lib/foreman_maintain/utils/command_runner.rb, line 98 def hide_strings(string) return unless string @hidden_patterns.reduce(string) do |result, hidden_pattern| result.gsub(hidden_pattern, '[FILTERED]') end end
run_interactively()
click to toggle source
# File lib/foreman_maintain/utils/command_runner.rb, line 60 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( "stdbuf -oL -eL bash -c '#{full_command}; echo $? > #{exit_file.path}'"\ "| tee -i #{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
run_non_interactively()
click to toggle source
# File lib/foreman_maintain/utils/command_runner.rb, line 83 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