diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2017-02-06 11:46:20 -0800 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2017-02-07 11:27:09 -0800 |
commit | e1f1ba4c9c5a802c0f50b4d5e53b26a5da982c20 (patch) | |
tree | 9360411b39daf533c8f49e28b197b0705b24ae1c /lib/chef/provider | |
parent | b1d3d41697b99ea8d4615c6cca5776c9276bc0be (diff) | |
download | chef-e1f1ba4c9c5a802c0f50b4d5e53b26a5da982c20.tar.gz |
rhel7 / dnf 2.0 fixes / improved errors
- fixes for dnf 2.0 / rhel7
- improved error messages from python helper (gives python stack
traces instead of just EPIPE all the time)
- improved which/where interface in the which mixin.
Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
Diffstat (limited to 'lib/chef/provider')
-rw-r--r-- | lib/chef/provider/package/dnf/dnf_helper.py | 2 | ||||
-rw-r--r-- | lib/chef/provider/package/dnf/python_helper.rb | 81 |
2 files changed, 59 insertions, 24 deletions
diff --git a/lib/chef/provider/package/dnf/dnf_helper.py b/lib/chef/provider/package/dnf/dnf_helper.py index 236b967710..ef08bb54c2 100644 --- a/lib/chef/provider/package/dnf/dnf_helper.py +++ b/lib/chef/provider/package/dnf/dnf_helper.py @@ -53,7 +53,7 @@ def query(command): if len(archq.run()) > 0: q = archq - pkgs = dnf.query.latest_limit_pkgs(q, 1) + pkgs = q.latest(1).run() if not pkgs: sys.stdout.write('{} nil nil\n'.format(command['provides'].split().pop(0))) diff --git a/lib/chef/provider/package/dnf/python_helper.rb b/lib/chef/provider/package/dnf/python_helper.rb index 466114b339..a4d91ea4b6 100644 --- a/lib/chef/provider/package/dnf/python_helper.rb +++ b/lib/chef/provider/package/dnf/python_helper.rb @@ -15,6 +15,8 @@ # limitations under the License. # +require "chef/mixin/which" +require "chef/mixin/shell_out" require "chef/provider/package/dnf/version" require "timeout" @@ -24,7 +26,8 @@ class Chef class Dnf < Chef::Provider::Package class PythonHelper include Singleton - extend Chef::Mixin::Which + include Chef::Mixin::Which + include Chef::Mixin::ShellOut attr_accessor :stdin attr_accessor :stdout @@ -32,11 +35,16 @@ class Chef attr_accessor :wait_thr DNF_HELPER = ::File.expand_path(::File.join(::File.dirname(__FILE__), "dnf_helper.py")).freeze - DNF_COMMAND = "#{which("python3")} #{DNF_HELPER}" + + def dnf_command + @dnf_command ||= which("python", "python3", "python2", "python2.7") do |f| + shell_out("#{f} -c 'import dnf'").exitstatus == 0 + end + " #{DNF_HELPER}" + end def start ENV["PYTHONUNBUFFERED"] = "1" - @stdin, @stdout, @stderr, @wait_thr = Open3.popen3(DNF_COMMAND) + @stdin, @stdout, @stderr, @wait_thr = Open3.popen3(dnf_command) end def reap @@ -53,6 +61,27 @@ class Chef start if stdin.nil? end + # @returns Array<Version> + def query(action, provides, version = nil, arch = nil) + with_helper do + json = build_query(action, provides, version, arch) + Chef::Log.debug "sending '#{json}' to python helper" + stdin.syswrite json + "\n" + output = stdout.sysread(4096).chomp + Chef::Log.debug "got '#{output}' from python helper" + version = parse_response(output) + Chef::Log.debug "parsed #{version} from python helper" + version + end + end + + def restart + reap + start + end + + private + # i couldn't figure out how to decompose an evr on the python side, it seems reasonably # painless to do it in ruby (generally massaging nevras in the ruby side is HIGHLY # discouraged -- this is an "every rule has an exception" exception -- any additional @@ -83,35 +112,41 @@ class Chef array.each_slice(3).map { |x| Version.new(*x) }.first end - # @returns Array<Version> - def query(action, provides, version = nil, arch = nil) - with_helper do - json = build_query(action, provides, version, arch) - Chef::Log.debug "sending '#{json}' to python helper" - stdin.syswrite json + "\n" - output = stdout.sysread(4096).chomp - Chef::Log.debug "got '#{output}' from python helper" - version = parse_response(output) - Chef::Log.debug "parsed #{version} from python helper" - version + def drain_stderr + output = "" + until IO.select([stderr], nil, nil, 0).nil? + output += stderr.sysread(4096).chomp end - end - - def restart - reap - start + output + rescue + # we must rescue EOFError, and we don't much care about errors on stderr anyway + output end def with_helper max_retries ||= 5 + ret = nil Timeout.timeout(600) do check - yield + ret = yield end + output = drain_stderr + unless output.empty? + Chef::Log.debug "discarding output on stderr from python helper: #{output}" + end + ret rescue EOFError, Errno::EPIPE, Timeout::Error, Errno::ESRCH => e - raise e unless ( max_retries -= 1 ) > 0 - restart - retry + output = drain_stderr + if ( max_retries -= 1 ) > 0 + unless output.empty? + Chef::Log.debug "discarding output on stderr from python helper: #{output}" + end + restart + retry + else + raise e if output.empty? + raise "dnf-helper.py had stderr output:\n\n#{output}" + end end end end |