\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7 \8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh \00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€ \00 $\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95 59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9 C/// File Manager

File Manager

Path: /opt/chef/embedded/lib/ruby/gems/2.7.0/gems/chef-16.3.45/spec/unit/provider/package/

Viewing File: dpkg_spec.rb

# Author:: Bryan McLellan (btm@loftninjas.org)
# Copyright:: Copyright 2009-2016, Bryan McLellan
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require "spec_helper"

describe Chef::Provider::Package::Dpkg do
  let(:node) { Chef::Node.new }
  let(:events) { Chef::EventDispatch::Dispatcher.new }
  let(:run_context) { Chef::RunContext.new(node, {}, events) }
  let(:package) { "wget" }
  let(:source) { "/tmp/wget_1.11.4-1ubuntu1_amd64.deb" }
  let(:new_resource) do
    new_resource = Chef::Resource::DpkgPackage.new(package)
    new_resource.source source
    new_resource
  end
  let(:provider) { Chef::Provider::Package::Dpkg.new(new_resource, run_context) }

  let(:dpkg_deb_version) { "1.11.4" }
  let(:dpkg_deb_status) { status = double(stdout: "#{package}\t#{dpkg_deb_version}", exitstatus: 0) }
  let(:dpkg_s_version) { "1.11.4-1ubuntu1" }
  let(:dpkg_s_status) do
    stdout = <<~DPKG_S
      Package: #{package}
      Status: install ok installed
      Priority: important
      Section: web
      Installed-Size: 1944
      Maintainer: Ubuntu Core developers <ubuntu-devel-discuss@lists.ubuntu.com>
      Architecture: amd64
      Version: #{dpkg_s_version}
      Config-Version: #{dpkg_s_version}
      Depends: libc6 (>= 2.8~20080505), libssl0.9.8 (>= 0.9.8f-5)
      Conflicts: wget-ssl
    DPKG_S
    status = double(stdout: stdout, exitstatus: 1)
  end

  before(:each) do
    allow(provider).to receive(:shell_out_compacted!).with("dpkg-deb", "-W", source, timeout: 900).and_return(dpkg_deb_status)
    allow(provider).to receive(:shell_out_compacted!).with("dpkg", "-s", package, timeout: 900, returns: [0, 1]).and_return(double(stdout: "", exitstatus: 1))
  end

  describe "#define_resource_requirements" do
    it "should raise an exception if a source is supplied but not found when :install" do
      allow(::File).to receive(:exist?).with(source).and_return(false)
      expect { provider.run_action(:install) }.to raise_error(Chef::Exceptions::Package)
    end

    it "should raise an exception if a source is supplied but not found when :upgrade" do
      allow(::File).to receive(:exist?).with(source).and_return(false)
      expect { provider.run_action(:upgrade) }.to raise_error(Chef::Exceptions::Package)
    end

    # FIXME?  we're saying we ignore source, but should supplying source on :remove or :purge be an actual error?
    it "should not raise an exception if a source is supplied but not found when :remove" do
      allow(::File).to receive(:exist?).with(source).and_return(false)
      expect(provider).to receive(:action_remove)
      expect { provider.run_action(:remove) }.not_to raise_error
    end

    it "should not raise an exception if a source is supplied but not found when :purge" do
      allow(::File).to receive(:exist?).with(source).and_return(false)
      expect(provider).to receive(:action_purge)
      expect { provider.run_action(:purge) }.not_to raise_error
    end

    context "when source is nil" do
      let(:source) { nil }

      it "should raise an exception if a source is nil when :install" do
        expect { provider.run_action(:install) }.to raise_error(Chef::Exceptions::Package)
      end

      it "should raise an exception if a source is nil when :upgrade" do
        expect { provider.run_action(:upgrade) }.to raise_error(Chef::Exceptions::Package)
      end

      it "should not raise an exception if a source is nil when :remove" do
        expect(provider).to receive(:action_remove)
        expect { provider.run_action(:remove) }.not_to raise_error
      end

      it "should not raise an exception if a source is nil when :purge" do
        expect(provider).to receive(:action_purge)
        expect { provider.run_action(:purge) }.not_to raise_error
      end
    end
  end

  describe "when loading the current resource state" do
    before(:each) do
      allow(::File).to receive(:exist?).with(source).and_return(true)
    end

    it "should create a current resource with the name of the new_resource" do
      provider.load_current_resource
      expect(provider.current_resource.package_name).to eq(["wget"])
    end

    describe "gets the source package version from dpkg-deb" do
      def check_version(version)
        status = double(stdout: "wget\t#{version}", exitstatus: 0)
        expect(provider).to receive(:shell_out_compacted!).with("dpkg-deb", "-W", source, timeout: 900).and_return(status)
        provider.load_current_resource
        expect(provider.current_resource.package_name).to eq(["wget"])
        expect(provider.candidate_version).to eq([version])
      end

      it "if short version provided" do
        check_version("1.11.4")
      end

      it "if extended version provided" do
        check_version("1.11.4-1ubuntu1")
      end

      it "if distro-specific version provided" do
        check_version("1.11.4-1ubuntu1~lucid")
      end

      it "returns the version if an epoch is used" do
        check_version("1:1.8.3-2")
      end
    end

    describe "when the package name has `-', `+' or `.' characters" do
      let(:package) { "f.o.o-pkg++2" }

      it "gets the source package name from dpkg-deb correctly" do
        provider.load_current_resource
        expect(provider.current_resource.package_name).to eq(["f.o.o-pkg++2"])
      end
    end

    describe "when the package version has `~', `-', `+' or `.' characters" do
      let(:package) { "b.a.r-pkg++1" }
      let(:dpkg_deb_version) { "1.2.3+3141592-1ubuntu1~lucid" }
      let(:dpkg_s_version) { "1.2.3+3141592-1ubuntu1~lucid" }

      it "gets the source package version from dpkg-deb correctly when the package version has `~', `-', `+' or `.' characters" do
        provider.load_current_resource
        expect(provider.candidate_version).to eq(["1.2.3+3141592-1ubuntu1~lucid"])
      end
    end

    describe "when the source is not set" do
      let(:source) { nil }

      it "should raise an exception if the source is not set but we are installing" do
        expect { provider.run_action(:install) }.to raise_error(Chef::Exceptions::Package)
      end
    end

    it "should return the current version installed if found by dpkg" do
      allow(provider).to receive(:shell_out_compacted!).with("dpkg", "-s", package, timeout: 900, returns: [0, 1]).and_return(dpkg_s_status)
      provider.load_current_resource
      expect(provider.current_resource.version).to eq(["1.11.4-1ubuntu1"])
    end

    it "on new debian/ubuntu we get an exit(1) and no stdout from dpkg -s for uninstalled" do
      dpkg_s_status = double(
        exitstatus: 1, stdout: "", stderr: <<~EOF
          dpkg-query: package '#{package}' is not installed and no information is available
          Use dpkg --info (= dpkg-deb --info) to examine archive files,
          and dpkg --contents (= dpkg-deb --contents) to list their contents.
        EOF
      )
      expect(provider).to receive(:shell_out_compacted!).with("dpkg", "-s", package, returns: [0, 1], timeout: 900).and_return(dpkg_s_status)
      provider.load_current_resource
      expect(provider.current_resource.version).to eq([nil])
    end

    it "on old debian/ubuntu we get an exit(0) and we get info on stdout from dpkg -s for uninstalled" do
      dpkg_s_status = double(
        exitstatus: 0, stderr: "", stdout: <<~EOF
          Package: #{package}
          Status: unknown ok not-installed
          Priority: extra
          Section: ruby
        EOF
      )
      expect(provider).to receive(:shell_out_compacted!).with("dpkg", "-s", package, returns: [0, 1], timeout: 900).and_return(dpkg_s_status)
      provider.load_current_resource
      expect(provider.current_resource.version).to eq([nil])
    end

    it "and we should raise if we get any other exit codes from dpkg -s" do
      dpkg_s_status = double(
        exitstatus: 3, stderr: "i am very, very angry with you.  i'm very, very cross.  go to your room.", stdout: ""
      )
      expect(provider).to receive(:shell_out_compacted!).with("dpkg", "-s", package, returns: [0, 1], timeout: 900).and_raise(Mixlib::ShellOut::ShellCommandFailed)
      expect { provider.load_current_resource }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
    end

    it "should raise an exception if dpkg-deb -W fails to run" do
      status = double(stdout: "", exitstatus: -1)
      expect(provider).to receive(:shell_out_compacted!).with("dpkg-deb", "-W", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb", timeout: 900).and_raise(Mixlib::ShellOut::ShellCommandFailed)
      expect { provider.load_current_resource }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
    end
  end

  describe Chef::Provider::Package::Dpkg, "install and upgrade" do
    before(:each) do
      allow(::File).to receive(:exist?).with(source).and_return(true)
    end

    it "should run dpkg -i with the package source" do
      expect(provider).to receive(:run_noninteractive).with(
        "dpkg", "-i", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
      )
      provider.load_current_resource
      provider.run_action(:install)
    end

    it "should run dpkg -i if the package is a path and the source is nil" do
      new_resource.name "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
      expect(provider).to receive(:run_noninteractive).with(
        "dpkg", "-i", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
      )
      provider.run_action(:install)
    end

    it "should run dpkg -i if the package is a path and the source is nil for an upgrade" do
      new_resource.name "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
      expect(provider).to receive(:run_noninteractive).with(
        "dpkg", "-i", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
      )
      provider.run_action(:upgrade)
    end

    it "should run dpkg -i with the package source and options if specified" do
      new_resource.options "--force-yes"
      expect(provider).to receive(:run_noninteractive).with(
        "dpkg", "-i", "--force-yes", "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
      )
      provider.run_action(:install)
    end

    it "should upgrade by running install_package" do
      expect(provider).to receive(:install_package).with(["wget"], ["1.11.4-1ubuntu1"])
      provider.upgrade_package(["wget"], ["1.11.4-1ubuntu1"])
    end
  end

  describe Chef::Provider::Package::Dpkg, "remove and purge" do
    it "should run dpkg -r to remove the package" do
      expect(provider).to receive(:run_noninteractive).with(
        "dpkg", "-r", "wget"
      )
      provider.remove_package(["wget"], ["1.11.4-1ubuntu1"])
    end

    it "should run dpkg -r to remove the package with options if specified" do
      expect(provider).to receive(:run_noninteractive).with(
        "dpkg", "-r", "--force-yes", "wget"
      )
      allow(new_resource).to receive(:options).and_return("--force-yes")

      provider.remove_package(["wget"], ["1.11.4-1ubuntu1"])
    end

    it "should run dpkg -P to purge the package" do
      expect(provider).to receive(:run_noninteractive).with(
        "dpkg", "-P", "wget"
      )
      provider.purge_package(["wget"], ["1.11.4-1ubuntu1"])
    end

    it "should run dpkg -P to purge the package with options if specified" do
      expect(provider).to receive(:run_noninteractive).with(
        "dpkg", "-P", "--force-yes", "wget"
      )
      allow(new_resource).to receive(:options).and_return("--force-yes")

      provider.purge_package(["wget"], ["1.11.4-1ubuntu1"])
    end
  end

  describe "when given a response file" do
    it_behaves_like "given a response file" do
      before do
        @provider = Chef::Provider::Package::Dpkg.new(new_resource, run_context)
      end
      let(:new_resource) do
        new_resource = Chef::Resource::DpkgPackage.new("wget", run_context)
        new_resource.response_file("wget.response")
        new_resource.cookbook_name = "wget"
        new_resource
      end
      let(:path) { "preseed/wget" }
      let(:tmp_path) { "/tmp/preseed/wget" }
      let(:package_name) { "wget" }
      let(:package_version) { "1.11.4" }
      let(:response) { "wget.response" }
      let(:tmp_preseed_path) { "/tmp/preseed/wget/wget-1.11.4.seed" }
      let(:preseed_path) { "/preseed--wget--wget-1.11.4.seed" }
    end
  end
end