summaryrefslogtreecommitdiff
path: root/chef
diff options
context:
space:
mode:
authorMatthew Kent <mkent@magoazul.com>2012-10-28 00:23:16 -0700
committerBryan McLellan <btm@opscode.com>2012-12-14 08:33:06 -0800
commitcfbba7b061039be4f8290a9c368ffb04c17e6022 (patch)
tree42012519ab24e1d717f1825bdaa4769302712520 /chef
parent0c0f9fa8c636a1c65cfb37e5fc20f66c72b91e86 (diff)
downloadchef-cfbba7b061039be4f8290a9c368ffb04c17e6022.tar.gz
CHEF-2427: Teach the yum provider how to handle --(enable|disable)repo passed
as options. We collect these options while preserving their order, dump the cache, then pass them along to yum-dump.py during the refresh. yum-dump can now parse these options and enable/disable repos in exactly the same manner yum itself does, thus preserving our cache sanity. The next yum package resource that loads and doesn't have the same options set will blow away the cache. Under the current caching implementation passing these options will add client run time as the cache is rebuilt to account for the differences in package availability. As such I strongly suggest globally enabling/disabling the repo whenever possible.
Diffstat (limited to 'chef')
-rw-r--r--chef/lib/chef/provider/package/yum-dump.py20
-rw-r--r--chef/lib/chef/provider/package/yum.rb41
-rw-r--r--chef/spec/unit/provider/package/yum_spec.rb90
3 files changed, 140 insertions, 11 deletions
diff --git a/chef/lib/chef/provider/package/yum-dump.py b/chef/lib/chef/provider/package/yum-dump.py
index 99136eceec..407eb8f408 100644
--- a/chef/lib/chef/provider/package/yum-dump.py
+++ b/chef/lib/chef/provider/package/yum-dump.py
@@ -107,6 +107,14 @@ def setup(yb, options):
elif YUM_MAJOR == 2:
yb.conf.setConfigOption('cache', options.cache)
+ # Handle repo toggle via id or glob exactly like yum
+ for opt, repos in options.repo_control:
+ for repo in repos:
+ if opt == '--enablerepo':
+ yb.repos.enableRepo(repo)
+ elif opt == '--disablerepo':
+ yb.repos.disableRepo(repo)
+
return 0
def dump_packages(yb, list, output_provides):
@@ -239,6 +247,12 @@ def yum_dump(options):
print >> sys.stderr, "yum-dump Unlock Error: %s" % e
return 200
+# Preserve order of enable/disable repo args like yum does
+def gather_repo_opts(option, opt, value, parser):
+ if getattr(parser.values, option.dest, None) is None:
+ setattr(parser.values, option.dest, [])
+ getattr(parser.values, option.dest).append((opt, value.split(',')))
+
def main():
usage = "Usage: %prog [options]\n" + \
"Output a list of installed, available and re-installable packages via yum"
@@ -261,6 +275,12 @@ def main():
parser.add_option("-a", "--available",
action="store_const", const="available", dest="package_list", default="all",
help="output only available and re-installable packages")
+ parser.add_option("--enablerepo",
+ action="callback", callback=gather_repo_opts, type="string", dest="repo_control", default=[],
+ help="enable disabled repositories by id or glob")
+ parser.add_option("--disablerepo",
+ action="callback", callback=gather_repo_opts, type="string", dest="repo_control", default=[],
+ help="disable repositories by id or glob")
(options, args) = parser.parse_args()
diff --git a/chef/lib/chef/provider/package/yum.rb b/chef/lib/chef/provider/package/yum.rb
index 9048048b83..f67262ef6f 100644
--- a/chef/lib/chef/provider/package/yum.rb
+++ b/chef/lib/chef/provider/package/yum.rb
@@ -664,12 +664,16 @@ class Chef
@allow_multi_install = []
+ @extra_repo_control = nil
+
# these are for subsequent runs if we are on an interval
Chef::Client.when_run_starts do
YumCache.instance.reload
end
end
+ attr_reader :extra_repo_control
+
# Cache management
#
@@ -693,6 +697,10 @@ class Chef
raise ArgumentError, "Unexpected value in next_refresh: #{@next_refresh}"
end
+ if @extra_repo_control
+ opts << " #{@extra_repo_control}"
+ end
+
one_line = false
error = nil
@@ -848,6 +856,22 @@ class Chef
@allow_multi_install
end
+ def enable_extra_repo_control(arg)
+ # Don't touch cache if it's the same repos as the last load
+ unless @extra_repo_control == arg
+ @extra_repo_control = arg
+ reload
+ end
+ end
+
+ def disable_extra_repo_control
+ # Only force reload when set
+ if @extra_repo_control
+ @extra_repo_control = nil
+ reload
+ end
+ end
+
private
def version(package_name, arch=nil, is_available=false, is_installed=false)
@@ -995,6 +1019,23 @@ class Chef
@yum.reload
end
+ if @new_resource.options
+ repo_control = []
+ @new_resource.options.split.each do |opt|
+ if opt =~ %r{--(enable|disable)repo=.+}
+ repo_control << opt
+ end
+ end
+
+ if repo_control.size > 0
+ @yum.enable_extra_repo_control(repo_control.join(" "))
+ else
+ @yum.disable_extra_repo_control
+ end
+ else
+ @yum.disable_extra_repo_control
+ end
+
# At this point package_name could be:
#
# 1) a package name, eg: "foo"
diff --git a/chef/spec/unit/provider/package/yum_spec.rb b/chef/spec/unit/provider/package/yum_spec.rb
index 4b890b1549..375ae0966b 100644
--- a/chef/spec/unit/provider/package/yum_spec.rb
+++ b/chef/spec/unit/provider/package/yum_spec.rb
@@ -34,7 +34,8 @@ describe Chef::Provider::Package::Yum do
:package_available? => true,
:version_available? => true,
:allow_multi_install => [ "kernel" ],
- :package_repository => "base"
+ :package_repository => "base",
+ :disable_extra_repo_control => true
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@@ -92,6 +93,7 @@ describe Chef::Provider::Package::Yum do
end
end
@yum_cache.stub!(:package_available?).and_return(true)
+ @yum_cache.stub!(:disable_extra_repo_control).and_return(true)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@provider.load_current_resource
@@ -125,6 +127,7 @@ describe Chef::Provider::Package::Yum do
nil
end
@yum_cache.stub!(:package_available?).and_return(true)
+ @yum_cache.stub!(:disable_extra_repo_control).and_return(true)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
# annoying side effect of the fun stub'ing above
@@ -155,6 +158,7 @@ describe Chef::Provider::Package::Yum do
nil
end
@yum_cache.stub!(:package_available?).and_return(true)
+ @yum_cache.stub!(:disable_extra_repo_control).and_return(true)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@provider.load_current_resource
@@ -189,6 +193,7 @@ describe Chef::Provider::Package::Yum do
end
end.and_return("something")
@yum_cache.stub!(:package_available?).and_return(true)
+ @yum_cache.stub!(:disable_extra_repo_control).and_return(true)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@provider.load_current_resource
@@ -209,6 +214,24 @@ describe Chef::Provider::Package::Yum do
@provider.load_current_resource
end
+ it "should detect --enablerepo or --disablerepo when passed among options, collect them preserving order and notify the yum cache" do
+ @new_resource.stub!(:options).and_return("--stuff --enablerepo=foo --otherthings --disablerepo=a,b,c --enablerepo=bar")
+ @yum_cache.should_receive(:enable_extra_repo_control).with("--enablerepo=foo --disablerepo=a,b,c --enablerepo=bar")
+ @provider.load_current_resource
+ end
+
+ it "should let the yum cache know extra repos are disabled if --enablerepo or --disablerepo aren't among options" do
+ @new_resource.stub!(:options).and_return("--stuff --otherthings")
+ @yum_cache.should_receive(:disable_extra_repo_control)
+ @provider.load_current_resource
+ end
+
+ it "should let the yum cache know extra repos are disabled if options aren't set" do
+ @new_resource.stub!(:options).and_return(nil)
+ @yum_cache.should_receive(:disable_extra_repo_control)
+ @provider.load_current_resource
+ end
+
it "should search provides if package name can't be found then set package_name to match" do
@yum_cache = mock(
'Chef::Provider::Yum::YumCache',
@@ -217,7 +240,8 @@ describe Chef::Provider::Package::Yum do
:installed_version => "1.2.4-11.18.el5",
:candidate_version => "1.2.4-11.18.el5",
:package_available? => false,
- :version_available? => true
+ :version_available? => true,
+ :disable_extra_repo_control => true
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
pkg = Chef::Provider::Package::Yum::RPMPackage.new("test-package", "1.2.4-11.18.el5", "x86_64", [])
@@ -235,7 +259,8 @@ describe Chef::Provider::Package::Yum do
:installed_version => "1.2.4-11.18.el5",
:candidate_version => "1.2.4-11.18.el5",
:package_available? => false,
- :version_available? => true
+ :version_available? => true,
+ :disable_extra_repo_control => true
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
pkg_x = Chef::Provider::Package::Yum::RPMPackage.new("test-package-x", "1.2.4-11.18.el5", "x86_64", [])
@@ -255,7 +280,8 @@ describe Chef::Provider::Package::Yum do
:installed_version => "1.2.4-11.18.el5",
:candidate_version => "1.2.4-11.18.el5",
:package_available? => false,
- :version_available? => true
+ :version_available? => true,
+ :disable_extra_repo_control => true
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@yum_cache.should_receive(:packages_from_require).twice.and_return([])
@@ -272,7 +298,8 @@ describe Chef::Provider::Package::Yum do
:installed_version => "1.2.4-11.18.el5",
:candidate_version => "1.2.4-11.18.el5",
:package_available? => false,
- :version_available? => true
+ :version_available? => true,
+ :disable_extra_repo_control => true
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@@ -295,7 +322,8 @@ describe Chef::Provider::Package::Yum do
:installed_version => "1.2.4-11.18.el5",
:candidate_version => "1.2.4-11.18.el5",
:package_available? => false,
- :version_available? => true
+ :version_available? => true,
+ :disable_extra_repo_control => true
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@yum_cache.should_receive(:packages_from_require).twice.and_return([])
@@ -363,7 +391,8 @@ describe Chef::Provider::Package::Yum do
:installed_version => "1.2.4-11.18.el5",
:candidate_version => "1.2.4-11.18.el5_2.3",
:package_available? => true,
- :version_available? => nil
+ :version_available? => nil,
+ :disable_extra_repo_control => true
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@@ -380,7 +409,8 @@ describe Chef::Provider::Package::Yum do
:candidate_version => "1.2.4-11.15.el5",
:package_available? => true,
:version_available? => true,
- :allow_multi_install => [ "kernel" ]
+ :allow_multi_install => [ "kernel" ],
+ :disable_extra_repo_control => true
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@@ -398,7 +428,8 @@ describe Chef::Provider::Package::Yum do
:package_available? => true,
:version_available? => true,
:allow_multi_install => [ "cups" ],
- :package_repository => "base"
+ :package_repository => "base",
+ :disable_extra_repo_control => true
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@@ -420,7 +451,8 @@ describe Chef::Provider::Package::Yum do
:package_available? => true,
:version_available? => true,
:allow_multi_install => [],
- :package_repository => "base"
+ :package_repository => "base",
+ :disable_extra_repo_control => true
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@@ -485,7 +517,8 @@ describe Chef::Provider::Package::Yum do
:candidate_version => "1.2.4-11.15.el5",
:package_available? => true,
:version_available? => true,
- :allow_multi_install => [ "kernel" ]
+ :allow_multi_install => [ "kernel" ],
+ :disable_extra_repo_control => true
)
Chef::Provider::Package::Yum::YumCache.stub!(:instance).and_return(@yum_cache)
@provider = Chef::Provider::Package::Yum.new(@new_resource, @run_context)
@@ -1609,6 +1642,12 @@ EOF
@yc.refresh
end
+ it "should pass extra_repo_control args to yum-dump.py" do
+ @yc.enable_extra_repo_control("--enablerepo=foo --disablerepo=bar")
+ @yc.should_receive(:popen4).with(%r{^/usr/bin/python .*/yum-dump.py --options --installed-provides --enablerepo=foo --disablerepo=bar$}, :waitlast=>true)
+ @yc.refresh
+ end
+
it "should warn about invalid data with too many separators" do
@yc.stub!(:popen4).and_yield(@pid, @stdin, @stdout_bad_separators, @stderr).and_return(@status)
Chef::Log.should_receive(:warn).exactly(3).times.with(%r{Problem parsing})
@@ -1788,4 +1827,33 @@ EOF
end
end
+ describe "enable_extra_repo_control" do
+ it "should set @extra_repo_control to arg" do
+ @yc.enable_extra_repo_control("--enablerepo=test")
+ @yc.extra_repo_control.should be == "--enablerepo=test"
+ end
+
+ it "should call reload once when set to flag cache for update" do
+ @yc.should_receive(:reload).once
+ @yc.enable_extra_repo_control("--enablerepo=test")
+ @yc.enable_extra_repo_control("--enablerepo=test")
+ end
+ end
+
+ describe "disable_extra_repo_control" do
+ it "should set @extra_repo_control to nil" do
+ @yc.enable_extra_repo_control("--enablerepo=test")
+ @yc.disable_extra_repo_control
+ @yc.extra_repo_control.should be == nil
+ end
+
+ it "should call reload once when cleared to flag cache for update" do
+ @yc.should_receive(:reload).once
+ @yc.enable_extra_repo_control("--enablerepo=test")
+ @yc.should_receive(:reload).once
+ @yc.disable_extra_repo_control
+ @yc.disable_extra_repo_control
+ end
+ end
+
end