summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/chef/provider/package/yum.rb30
-rw-r--r--spec/unit/provider/package/yum_spec.rb36
2 files changed, 64 insertions, 2 deletions
diff --git a/lib/chef/provider/package/yum.rb b/lib/chef/provider/package/yum.rb
index 49c6f6beb5..b3d3d72844 100644
--- a/lib/chef/provider/package/yum.rb
+++ b/lib/chef/provider/package/yum.rb
@@ -19,6 +19,7 @@
require 'chef/config'
require 'chef/provider/package'
require 'chef/mixin/shell_out'
+require 'chef/mixin/which'
require 'chef/resource/package'
require 'singleton'
require 'chef/mixin/get_source_from_package'
@@ -647,6 +648,7 @@ class Chef
# Cache for our installed and available packages, pulled in from yum-dump.py
class YumCache
include Chef::Mixin::Command
+ include Chef::Mixin::Which
include Chef::Mixin::ShellOut
include Singleton
@@ -713,7 +715,7 @@ class Chef
status = nil
begin
- status = shell_out!("/usr/bin/python #{helper}#{opts}", :timeout => Chef::Config[:yum_timeout])
+ status = shell_out!("#{python_bin} #{helper}#{opts}", :timeout => Chef::Config[:yum_timeout])
status.stdout.each_line do |line|
one_line = true
@@ -779,6 +781,32 @@ class Chef
@next_refresh = :none
end
+ def python_bin
+ yum_executable = which("yum")
+ if yum_executable && shabang?(yum_executable)
+ extract_interpreter(yum_executable)
+ else
+ Chef::Log.warn("Yum executable not found or doesn't start with #!. Using default python.")
+ "/usr/bin/python"
+ end
+ rescue StandardError => e
+ Chef::Log.warn("An error occured attempting to determine correct python executable. Using default.")
+ Chef::Log.debug(e)
+ "/usr/bin/python"
+ end
+
+ def extract_interpreter(file)
+ ::File.open(file, 'r', &:readline)[2..-1].chomp
+ end
+
+ def shabang?(file)
+ ::File.open(file, 'r') do |f|
+ f.read(2) == '#!'
+ end
+ rescue Errno::ENOENT
+ false
+ end
+
def reload
@next_refresh = :all
end
diff --git a/spec/unit/provider/package/yum_spec.rb b/spec/unit/provider/package/yum_spec.rb
index 865dce23fa..8f4bde7f62 100644
--- a/spec/unit/provider/package/yum_spec.rb
+++ b/spec/unit/provider/package/yum_spec.rb
@@ -17,6 +17,7 @@
#
require 'spec_helper'
+require 'securerandom'
describe Chef::Provider::Package::Yum do
before(:each) do
@@ -1659,6 +1660,14 @@ describe Chef::Provider::Package::Yum::YumCache do
end
end
+ let(:yum_exe) {
+ StringIO.new("#!/usr/bin/python\n\naldsjfa\ldsajflkdsjf\lajsdfj")
+ }
+
+ let(:bin_exe) {
+ StringIO.new(SecureRandom.random_bytes)
+ }
+
before(:each) do
@stdin = double("STDIN", :nil_object => true)
@stdout = double("STDOUT", :nil_object => true)
@@ -1704,12 +1713,19 @@ file: file://///etc/yum.repos.d/CentOS-Base.repo, line: 12
'qeqwewe\n'
EOF
@status = double("Status", :exitstatus => 0, :stdin => @stdin, :stdout => @stdout_good, :stderr => @stderr)
-
# new singleton each time
Chef::Provider::Package::Yum::YumCache.reset_instance
@yc = Chef::Provider::Package::Yum::YumCache.instance
# load valid data
allow(@yc).to receive(:shell_out!).and_return(@status)
+ allow_any_instance_of(described_class).to receive(:which).with("yum").and_return("/usr/bin/yum")
+ allow(::File).to receive(:open).with("/usr/bin/yum", "r") do |&block|
+ res = block.call(yum_exe)
+ # a bit of a hack. rewind this since it seem that no matter what
+ # I do, we get the same StringIO objects on multiple calls to
+ # ::File.open
+ yum_exe.rewind; res
+ end
end
describe "initialize" do
@@ -1726,6 +1742,24 @@ EOF
end
end
+ describe "python_bin" do
+ it "should return the default python if an error occurs" do
+ allow(::File).to receive(:open).with("/usr/bin/yum", "r").and_raise(StandardError)
+ expect(@yc.python_bin).to eq("/usr/bin/python")
+ end
+
+ it "should return the default python if the yum-executable doesn't start with #!" do
+ allow(::File).to receive(:open).with("/usr/bin/yum", "r") { |&b| r = b.call(bin_exe); bin_exe.rewind; r}
+ expect(@yc.python_bin).to eq("/usr/bin/python")
+ end
+
+ it "should return the interpreter for yum" do
+ other = StringIO.new("#!/usr/bin/super_python\n\nlasjdfdsaljf\nlasdjfs")
+ allow(::File).to receive(:open).with("/usr/bin/yum", "r") { |&b| r = b.call(other); other.rewind; r}
+ expect(@yc.python_bin).to eq("/usr/bin/super_python")
+ end
+ end
+
describe "refresh" do
it "should implicitly call yum-dump.py only once by default after being instantiated" do
expect(@yc).to receive(:shell_out!).once