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

Commit

Permalink
(FACT-2517) Open3 wrapper for executing system calls
Browse files Browse the repository at this point in the history
  • Loading branch information
Oana Tanasoiu committed Apr 23, 2020
1 parent b4917e6 commit 50018b8
Show file tree
Hide file tree
Showing 71 changed files with 539 additions and 553 deletions.
11 changes: 3 additions & 8 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config --exclude-limit 1000`
# on 2020-04-15 10:09:42 +0300 using RuboCop version 0.74.0.
# on 2020-04-23 16:01:57 +0300 using RuboCop version 0.74.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
Expand Down Expand Up @@ -49,8 +49,8 @@ RSpec/FilePath:
- 'spec/facter/resolvers/processors_resolver_spec.rb'
- 'spec/facter/resolvers/redhat_release_resolver_spec.rb'
- 'spec/facter/resolvers/selinux_resolver_spec.rb'
- 'spec/facter/resolvers/solaris/current_zone_resolver_spec.rb'
- 'spec/facter/resolvers/solaris/solaris_release_resolver_spec.rb'
- 'spec/facter/resolvers/solaris/solaris_zone_name_spec.rb'
- 'spec/facter/resolvers/solaris/zone_resolver_spec.rb'
- 'spec/facter/resolvers/solaris/zpool_resolver_spec.rb'
- 'spec/facter/resolvers/suse_relese_resolver_spec.rb'
Expand Down Expand Up @@ -190,7 +190,7 @@ RSpec/SubjectStub:
- 'spec/custom_facts/util/fact_spec.rb'
- 'spec/custom_facts/util/resolution_spec.rb'

# Offense count: 179
# Offense count: 174
# Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
RSpec/VerifiedDoubles:
Exclude:
Expand Down Expand Up @@ -228,11 +228,6 @@ RSpec/VerifiedDoubles:
- 'spec/facter/resolvers/aix/hardware_resolver_spec.rb'
- 'spec/facter/resolvers/macosx/mountpoints_resolver_spec.rb'
- 'spec/facter/resolvers/mountpoints_resolver_spec.rb'
- 'spec/facter/resolvers/solaris/current_zone_resolver_spec.rb'
- 'spec/facter/resolvers/solaris/solaris_release_resolver_spec.rb'
- 'spec/facter/resolvers/solaris/zfs_resolver_spec.rb'
- 'spec/facter/resolvers/solaris/zone_resolver_spec.rb'
- 'spec/facter/resolvers/solaris/zpool_resolver_spec.rb'
- 'spec/facter/resolvers/utils/windows/network_utils_spec.rb'
- 'spec/facter/resolvers/utils/windows/win32ole_spec.rb'
- 'spec/facter/resolvers/windows/dmi_bios_resolver_spec.rb'
Expand Down
24 changes: 16 additions & 8 deletions lib/custom_facts/core/execution/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ module Facter
module Core
module Execution
class Base
STDERR_MESSAGE = 'Command %s resulted with the following stderr message: %s'

def with_env(values)
old = {}
values.each do |var, value|
Expand Down Expand Up @@ -34,12 +36,13 @@ def with_env(values)
def execute(command, options = {})
on_fail = options.fetch(:on_fail, :raise)
expand = options.fetch(:expand, true)
logger = options[:logger]

# 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 = if !expand && builtin_command?(command)
expanded_command = if !expand && builtin_command?(command) || logger
command
else
expand_command(command)
Expand All @@ -54,30 +57,35 @@ def execute(command, options = {})
return on_fail
end

execute_command(expanded_command, on_fail)
execute_command(expanded_command, on_fail, logger)
end
end

private

def log_stderr_from_file(msg, command)
def log_stderr(msg, command, logger)
return if !msg || msg.empty?

file_name = command.split('/').last
logger = Facter::Log.new(file_name)
logger.warn(msg.strip)
if logger
logger.debug(format(STDERR_MESSAGE, command, msg.strip))
else
file_name = command.split('/').last
logger = Facter::Log.new(file_name)
logger.warn(format(STDERR_MESSAGE, command, msg.strip))
end
end

def builtin_command?(command)
output, _status = Open3.capture2("type #{command}")
output.chomp =~ /builtin/ ? true : false
end

def execute_command(command, on_fail)
def execute_command(command, on_fail, logger = nil)
begin
out, stderr, _status_ = Open3.capture3(command.to_s)
log_stderr_from_file(stderr, command)
log_stderr(stderr, command, logger)
rescue StandardError => e
return '' if logger
return on_fail unless on_fail == :raise

raise Facter::Core::Execution::ExecutionFailure.new,
Expand Down
9 changes: 6 additions & 3 deletions lib/facts_utils/uptime_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class UptimeParser
SECS_IN_AN_HOUR = 3_600
SECS_IN_A_MINUTE = 60

@log = Facter::Log.new(self)

class << self
def uptime_seconds_unix
uptime_proc_uptime || uptime_sysctl || uptime_executable
Expand All @@ -16,19 +18,20 @@ def uptime_seconds_unix
private

def uptime_proc_uptime
output, _stderr, _status = Open3.capture3("/bin/cat #{uptime_file} 2>/dev/null")
output = Facter::Core::Execution.execute("/bin/cat #{uptime_file}", logger: @log)

output.chomp.split(' ').first.to_i unless output.empty?
end

def uptime_sysctl
output, _stderr, _status = Open3.capture3("sysctl -n #{uptime_sysctl_variable} 2>/dev/null")
output = Facter::Core::Execution.execute("sysctl -n #{uptime_sysctl_variable}", logger: @log)

compute_uptime(Time.at(output.match(/\d+/)[0].to_i)) unless output.empty?
end

def uptime_executable
output, _stderr, _status = Open3.capture3(uptime_executable_cmd + ' 2>/dev/null')
output = Facter::Core::Execution.execute(uptime_executable_cmd, logger: @log)

return unless output

up = 0
Expand Down
5 changes: 3 additions & 2 deletions lib/resolvers/aix/mountpoints.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Resolvers
module Aix
class Mountpoints < BaseResolver
@semaphore = Mutex.new
@log = Facter::Log.new(self)
@fact_list ||= {}
BLOCK_SIZE = 512

Expand All @@ -17,7 +18,7 @@ def post_resolve(fact_name)

def read_mount(fact_name)
@fact_list[:mountpoints] = {}
output, _status = Open3.capture2('mount 2>/dev/null')
output = Facter::Core::Execution.execute('mount', logger: @log)
output.split("\n").map do |line|
next if line =~ /\snode\s|---|procfs|ahafs/

Expand All @@ -32,7 +33,7 @@ def read_mount(fact_name)
end

def retrieve_sizes_for_mounts
output, _status = Open3.capture2('df -P 2>/dev/null')
output = Facter::Core::Execution.execute('df -P', logger: @log)
output.split("\n").map do |line|
next if line =~ /Filesystem|-\s+-\s+-/

Expand Down
3 changes: 2 additions & 1 deletion lib/resolvers/aix/networking_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Resolvers
module Aix
class Networking < BaseResolver
@semaphore = Mutex.new
@log = Facter::Log.new(self)
@fact_list ||= {}

class << self
Expand All @@ -15,7 +16,7 @@ def post_resolve(fact_name)
end

def read_netstat(fact_name)
output, _status = Open3.capture2('netstat -rn')
output = Facter::Core::Execution.execute('netstat -rn', logger: @log)
output = output.split("\n").select { |line| (line =~ /\s\s[0-9]+.[0-9]+.[0-9]+.[0-9]+|\s\s.*:[0-9a-f]+/) }
get_primary_interface_info(output)

Expand Down
3 changes: 2 additions & 1 deletion lib/resolvers/aix/os_level_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Resolvers
class OsLevel < BaseResolver
@semaphore = Mutex.new
@fact_list ||= {}
@log = Facter::Log.new(self)

class << self
private
Expand All @@ -14,7 +15,7 @@ def post_resolve(fact_name)
end

def read_oslevel(fact_name)
output, _status = Open3.capture2('/usr/bin/oslevel -s 2>/dev/null')
output = Facter::Core::Execution.execute('/usr/bin/oslevel -s', logger: @log)
@fact_list[:build] = output
@fact_list[:kernel] = 'AIX'

Expand Down
8 changes: 3 additions & 5 deletions lib/resolvers/aix/partitions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,9 @@ def query_cudv(fact_name)
end

def populate_from_lslv(name)
stdout, stderr, _status = Open3.capture3("lslv -L #{name}")
if stdout.empty?
@log.debug(stderr)
return
end
stdout = Facter::Core::Execution.execute("lslv -L #{name}", logger: @log)

return if stdout.empty?

info_hash = extract_info(stdout)
size_bytes = compute_size(info_hash)
Expand Down
3 changes: 2 additions & 1 deletion lib/resolvers/aix/utils/odm_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
module Facter
class ODMQuery
REPOS = %w[CuAt CuDv PdAt PdDv].freeze
@log = Facter::Log.new(self)

def initialize
@query = ''
Expand All @@ -29,7 +30,7 @@ def execute
REPOS.each do |repo|
break if result && !result.empty?

result, _stderr, _s = Open3.capture3("#{query} #{repo}")
result = Facter::Core::Execution.execute("#{query} #{repo}", logger: @log)
end
result
end
Expand Down
3 changes: 2 additions & 1 deletion lib/resolvers/augeas_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Resolvers
class Augeas < BaseResolver
@semaphore = Mutex.new
@fact_list ||= {}
@log = Facter::Log.new(self)

class << self
private
Expand All @@ -14,7 +15,7 @@ def post_resolve(fact_name)
end

def read_augeas_version(fact_name)
output, _status = Open3.capture2('augparse --version 2>&1')
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[fact_name]
end
Expand Down
3 changes: 2 additions & 1 deletion lib/resolvers/eos_release_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class EosRelease < BaseResolver

@semaphore = Mutex.new
@fact_list ||= {}
@log = Facter::Log.new(self)

class << self
private
Expand All @@ -18,7 +19,7 @@ def post_resolve(fact_name)
end

def read_eos_release(fact_name)
output, _status = Open3.capture2('cat /etc/Eos-release')
output = Facter::Core::Execution.execute('cat /etc/Eos-release', logger: @log)
output_strings = output.split(' ')

@fact_list[:name] = output_strings[0]
Expand Down
2 changes: 1 addition & 1 deletion lib/resolvers/hostname_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def post_resolve(fact_name)
end

def retrieve_hostname(fact_name)
output, _status = Open3.capture2('hostname')
output = Facter::Core::Execution.execute('hostname', logger: @log)

# get domain
domain = read_domain(output)
Expand Down
4 changes: 2 additions & 2 deletions lib/resolvers/lpar_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Resolvers
class Lpar < BaseResolver
@semaphore = Mutex.new
@fact_list ||= {}
@log = Facter::Log.new(self)

class << self
private
Expand All @@ -14,8 +15,7 @@ def post_resolve(fact_name)
end

def read_lpar(fact_name)
lpar_cmd = '/usr/bin/lparstat -i'
output, _status = Open3.capture2(lpar_cmd)
output = Facter::Core::Execution.execute('/usr/bin/lparstat -i', logger: @log)
output.each_line do |line|
populate_lpar_data(line.split(':').map(&:strip))
end
Expand Down
6 changes: 2 additions & 4 deletions lib/resolvers/lsb_release_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,12 @@ def retrieve_facts(fact_name)
end

def lsb_release_installed?
output, stderr, _status = Open3.capture3('which lsb_release')
@log.debug(stderr) unless stderr.empty?
output = Facter::Core::Execution.execute('which lsb_release', logger: @log)
@fact_list[:lsb_release_installed] = !output.empty?
end

def read_lsb_release_file
output, stderr, _status = Open3.capture3('lsb_release -a')
@log.debug(stderr) unless stderr.empty?
output = Facter::Core::Execution.execute('lsb_release -a', logger: @log)
build_fact_list(output)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/resolvers/macosx/dmi_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def post_resolve(fact_name)

def read_facts
# OSX only supports the product name
output, _status = Open3.capture2('sysctl -n hw.model')
output = Facter::Core::Execution.execute('sysctl -n hw.model', logger: @log)
@fact_list[:macosx_model] = output&.strip
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/resolvers/macosx/filesystems_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def post_resolve(fact_name)
end

def read_filesystems(fact_name)
output, _status = Open3.capture2('mount')
output = Facter::Core::Execution.execute('mount', logger: @log)
filesystems = []
output.each_line do |line|
filesystem = line.match(/\(([a-z]+)\,*/).to_s
Expand Down
6 changes: 3 additions & 3 deletions lib/resolvers/macosx/ipaddress_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def read_ipaddress(fact_name)
primary_interface = read_primary_interface
unless primary_interface.nil?
@fact_list[:primary] = primary_interface
output, _status = Open3.capture2("ipconfig getifaddr #{primary_interface}")
output = Facter::Core::Execution.execute("ipconfig getifaddr #{primary_interface}", logger: @log)
ip = output.strip
end
find_all_interfaces
Expand All @@ -29,15 +29,15 @@ def read_ipaddress(fact_name)

def read_primary_interface
iface = nil
output, _status = Open3.capture2('route -n get default')
output = Facter::Core::Execution.execute('route -n get default', logger: @log)
output.split(/^\S/).each do |str|
iface = Regexp.last_match(1) if str.strip =~ /interface: (\S+)/
end
iface
end

def find_all_interfaces
output, _status = Open3.capture2('ifconfig -a 2>/dev/null')
output = Facter::Core::Execution.execute('ifconfig -a', logger: @log)

data_hash = Hash[*output.split(/^([A-Za-z0-9_]+): /)[1..-1]]

Expand Down
2 changes: 1 addition & 1 deletion lib/resolvers/macosx/load_averages_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def post_resolve(fact_name)
end

def read_load_averages_file(fact_name)
output, _status = Open3.capture2('sysctl -n vm.loadavg')
output = Facter::Core::Execution.execute('sysctl -n vm.loadavg', logger: @log)
@fact_list[:load_averages] = {}.tap { |h| _, h['1m'], h['5m'], h['15m'], = output.split.map(&:to_f) }

@fact_list[fact_name]
Expand Down
2 changes: 1 addition & 1 deletion lib/resolvers/macosx/processor_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def post_resolve(fact_name)
end

def read_processor_data(fact_name)
output, _status = Open3.capture2("sysctl #{ITEMS.values.join(' ')}")
output = Facter::Core::Execution.execute("sysctl #{ITEMS.values.join(' ')}", logger: @log)
build_fact_list(output.split("\n"))
@fact_list[fact_name]
end
Expand Down
2 changes: 1 addition & 1 deletion lib/resolvers/macosx/swap_memory_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def post_resolve(fact_name)
end

def read_swap_memory(fact_name) # rubocop:disable Metrics/AbcSize
output = Open3.capture2('sysctl -n vm.swapusage').first
output = Facter::Core::Execution.execute('sysctl -n vm.swapusage', logger: @log)
data = output.match(/^total = ([\d.]+)M used = ([\d.]+)M free = ([\d.]+)M (\(encrypted\))$/)

if data[1].to_f.positive?
Expand Down
4 changes: 2 additions & 2 deletions lib/resolvers/macosx/system_memory_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ def calculate_system_memory(fact_name)
end

def read_available_memory_in_bytes
output, _status = Open3.capture2('vm_stat')
output = Facter::Core::Execution.execute('vm_stat', logger: @log)
page_size = output.match(/page size of (\d+) bytes/)[1].to_i
pages_free = output.match(/Pages free:\s+(\d+)/)[1].to_i

@fact_list[:available_bytes] = page_size * pages_free
end

def read_total_memory_in_bytes
@fact_list[:total_bytes] = Open3.capture2('sysctl -n hw.memsize').first.to_i
@fact_list[:total_bytes] = Facter::Core::Execution.execute('sysctl -n hw.memsize', logger: @log).to_i
end

def compute_capacity(used, total)
Expand Down

0 comments on commit 50018b8

Please sign in to comment.