diff options
author | Tim Smith <tsmith@chef.io> | 2018-11-22 14:51:40 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-22 14:51:40 -0800 |
commit | ea2092cc6ed146b82042d744c3ee718830d850d5 (patch) | |
tree | 2826cb39d5d96ac8897323a4581ca0ee3339c076 | |
parent | 7cccce14c33bb3556b384d93e97a766fcd25d21d (diff) | |
parent | 15381beafe5c1375154bb8ff4c7cf6b6a72ee6c5 (diff) | |
download | chef-ea2092cc6ed146b82042d744c3ee718830d850d5.tar.gz |
Merge pull request #7963 from chef/lcg/apt-get-allow-downgrades
Support apt-get --allow-downgrades
-rw-r--r-- | lib/chef/provider/package/apt.rb | 16 | ||||
-rw-r--r-- | spec/unit/provider/package/apt_spec.rb | 85 |
2 files changed, 95 insertions, 6 deletions
diff --git a/lib/chef/provider/package/apt.rb b/lib/chef/provider/package/apt.rb index bfb24e502d..de1b106d45 100644 --- a/lib/chef/provider/package/apt.rb +++ b/lib/chef/provider/package/apt.rb @@ -1,6 +1,6 @@ # # Author:: Adam Jacob (<adam@chef.io>) -# Copyright:: Copyright 2008-2017, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -92,7 +92,8 @@ class Chef package_name = name.zip(version).map do |n, v| package_data[n][:virtual] ? n : "#{n}=#{v}" end - run_noninteractive("apt-get", "-q", "-y", config_file_options, default_release_options, options, "install", package_name) + dgrade = "--allow-downgrades" if supports_allow_downgrade? && allow_downgrade + run_noninteractive("apt-get", "-q", "-y", dgrade, config_file_options, default_release_options, options, "install", package_name) end def upgrade_package(name, version) @@ -133,6 +134,17 @@ class Chef private + # @return [String] version of apt-get which is installed + def apt_version + @apt_version ||= shell_out("apt-get --version").stdout.match(/^apt (\S+)/)[1] + end + + # @return [Boolean] if apt-get supports --allow-downgrades + def supports_allow_downgrade? + return @supports_allow_downgrade unless @supports_allow_downgrade.nil? + @supports_allow_downgrade = ( version_compare(apt_version, "1.1.0") >= 0 ) + end + # compare 2 versions to each other to see which is newer. # this differs from the standard package method because we # need to be able to parse debian version strings which contain diff --git a/spec/unit/provider/package/apt_spec.rb b/spec/unit/provider/package/apt_spec.rb index 05be08f332..24bd642317 100644 --- a/spec/unit/provider/package/apt_spec.rb +++ b/spec/unit/provider/package/apt_spec.rb @@ -256,7 +256,78 @@ describe Chef::Provider::Package::Apt do }) end + def ubuntu1804downgrade_stubs + so = instance_double(Mixlib::ShellOut, stdout: "apt 1.6~beta1 (amd64)\notherstuff\n") + so2 = instance_double(Mixlib::ShellOut, error?: false) + allow(@provider).to receive(:shell_out).with("apt-get --version").and_return(so) + allow(@provider).to receive(:shell_out).with("dpkg", "--compare-versions", "1.6~beta1", "gt", "1.1.0").and_return(so2) + end + + def ubuntu1404downgrade_stubs + so = instance_double(Mixlib::ShellOut, stdout: "apt 1.0.1ubuntu2 for amd64 compiled on Dec 8 2016 16:23:38\notherstuff\n") + so2 = instance_double(Mixlib::ShellOut, error?: true) + allow(@provider).to receive(:shell_out).with("apt-get --version").and_return(so) + allow(@provider).to receive(:shell_out).with("dpkg", "--compare-versions", "1.0.1ubuntu2", "gt", "1.1.0").and_return(so2) + allow(@provider).to receive(:shell_out).with("dpkg", "--compare-versions", "1.0.1ubuntu2", "eq", "1.1.0").and_return(so2) + end + describe "install_package" do + before(:each) do + ubuntu1804downgrade_stubs + end + + it "should run apt-get install with the package name and version" do + expect(@provider).to receive(:shell_out_compacted!). with( + "apt-get", "-q", "-y", "--allow-downgrades", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "irssi=0.8.12-7", + env: { "DEBIAN_FRONTEND" => "noninteractive" }, + timeout: @timeout + ) + @provider.install_package(["irssi"], ["0.8.12-7"]) + end + + it "should run apt-get install with the package name and version and options if specified" do + expect(@provider).to receive(:shell_out_compacted!).with( + "apt-get", "-q", "-y", "--allow-downgrades", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "--force-yes", "install", "irssi=0.8.12-7", + env: { "DEBIAN_FRONTEND" => "noninteractive" }, + timeout: @timeout + ) + @new_resource.options("--force-yes") + @provider.install_package(["irssi"], ["0.8.12-7"]) + end + + it "should run apt-get install with the package name and version and default_release if there is one and provider is explicitly defined" do + @new_resource = nil + @new_resource = Chef::Resource::AptPackage.new("irssi", @run_context) + @new_resource.default_release("lenny-backports") + @new_resource.provider = nil + @provider.new_resource = @new_resource + + expect(@provider).to receive(:shell_out_compacted!).with( + "apt-get", "-q", "-y", "--allow-downgrades", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "-o", "APT::Default-Release=lenny-backports", "install", "irssi=0.8.12-7", + env: { "DEBIAN_FRONTEND" => "noninteractive" }, + timeout: @timeout + ) + + @provider.install_package(["irssi"], ["0.8.12-7"]) + end + + it "should run apt-get install with the package name and quotes options if specified" do + expect(@provider).to receive(:shell_out_compacted!).with( + "apt-get", "-q", "-y", "--allow-downgrades", "--force-yes", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confnew", "install", "irssi=0.8.12-7", + env: { "DEBIAN_FRONTEND" => "noninteractive" }, + timeout: @timeout + ) + @new_resource.options('--force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew"') + @provider.install_package(["irssi"], ["0.8.12-7"]) + end + end + + describe "install_package with old apt-get" do + # tests apt-get on 1404 that does not support --allow-downgrades + before(:each) do + ubuntu1404downgrade_stubs + end + it "should run apt-get install with the package name and version" do expect(@provider).to receive(:shell_out_compacted!). with( "apt-get", "-q", "-y", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "irssi=0.8.12-7", @@ -449,9 +520,10 @@ describe Chef::Provider::Package::Apt do describe "when installing a virtual package" do it "should install the package without specifying a version" do + ubuntu1804downgrade_stubs @provider.package_data["libmysqlclient15-dev"][:virtual] = true expect(@provider).to receive(:shell_out_compacted!).with( - "apt-get", "-q", "-y", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "libmysqlclient15-dev", + "apt-get", "-q", "-y", "--allow-downgrades", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "libmysqlclient15-dev", env: { "DEBIAN_FRONTEND" => "noninteractive" }, timeout: @timeout ) @@ -485,9 +557,10 @@ describe Chef::Provider::Package::Apt do describe "when installing multiple packages" do it "can install a virtual package followed by a non-virtual package" do + ubuntu1804downgrade_stubs # https://github.com/chef/chef/issues/2914 expect(@provider).to receive(:shell_out_compacted!).with( - "apt-get", "-q", "-y", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "libmysqlclient15-dev", "irssi=0.8.12-7", + "apt-get", "-q", "-y", "--allow-downgrades", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "libmysqlclient15-dev", "irssi=0.8.12-7", env: { "DEBIAN_FRONTEND" => "noninteractive" }, timeout: @timeout ) @@ -506,9 +579,11 @@ describe Chef::Provider::Package::Apt do end it "should install the package if the installed version is older" do + ubuntu1804downgrade_stubs + expect(@provider).to receive(:version_compare).with("1.6~beta1", "1.1.0").and_return(1) allow(@provider).to receive(:get_current_versions).and_return("0.4.0") allow(@new_resource).to receive(:allow_downgrade).and_return(false) - expect(@provider).to receive(:version_compare).and_return(-1) + expect(@provider).to receive(:version_compare).with("0.4.0", any_args).and_return(-1) expect(@provider).to receive(:shell_out_compacted!).with( "apt-get", "-q", "-y", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "irssi=0.8.12-7", env: { "DEBIAN_FRONTEND" => "noninteractive" }, @@ -518,9 +593,11 @@ describe Chef::Provider::Package::Apt do end it "should not compare versions if an existing version is not installed" do + ubuntu1804downgrade_stubs + expect(@provider).to receive(:version_compare).with("1.6~beta1", "1.1.0").and_return(1) allow(@provider).to receive(:get_current_versions).and_return(nil) allow(@new_resource).to receive(:allow_downgrade).and_return(false) - expect(@provider).not_to receive(:version_compare) + expect(@provider).not_to receive(:version_compare).with("0.4.0", any_args) expect(@provider).to receive(:shell_out_compacted!).with( "apt-get", "-q", "-y", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "irssi=0.8.12-7", env: { "DEBIAN_FRONTEND" => "noninteractive" }, |