require 'spec_helper' describe Puppet::Type.type(:package) do before do allow(Process).to receive(:euid).and_return(0) allow(Puppet::Util::Storage).to receive(:store) end it "should have a :reinstallable feature that requires the :reinstall method" do expect(Puppet::Type.type(:package).provider_feature(:reinstallable).methods).to eq([:reinstall]) end it "should have an :installable feature that requires the :install method" do expect(Puppet::Type.type(:package).provider_feature(:installable).methods).to eq([:install]) end it "should have an :uninstallable feature that requires the :uninstall method" do expect(Puppet::Type.type(:package).provider_feature(:uninstallable).methods).to eq([:uninstall]) end it "should have an :upgradeable feature that requires :update and :latest methods" do expect(Puppet::Type.type(:package).provider_feature(:upgradeable).methods).to eq([:update, :latest]) end it "should have a :purgeable feature that requires the :purge latest method" do expect(Puppet::Type.type(:package).provider_feature(:purgeable).methods).to eq([:purge]) end it "should have a :versionable feature" do expect(Puppet::Type.type(:package).provider_feature(:versionable)).not_to be_nil end it "should have a :supports_flavors feature" do expect(Puppet::Type.type(:package).provider_feature(:supports_flavors)).not_to be_nil end it "should have a :package_settings feature that requires :package_settings_insync?, :package_settings and :package_settings=" do expect(Puppet::Type.type(:package).provider_feature(:package_settings).methods).to eq([:package_settings_insync?, :package_settings, :package_settings=]) end it "should default to being installed" do pkg = Puppet::Type.type(:package).new(:name => "yay", :provider => :apt) expect(pkg.should(:ensure)).to eq(:present) end describe "when validating attributes" do [:name, :source, :instance, :status, :adminfile, :responsefile, :configfiles, :category, :platform, :root, :vendor, :description, :allowcdrom, :allow_virtual, :reinstall_on_refresh].each do |param| it "should have a #{param} parameter" do expect(Puppet::Type.type(:package).attrtype(param)).to eq(:param) end end it "should have an ensure property" do expect(Puppet::Type.type(:package).attrtype(:ensure)).to eq(:property) end it "should have a package_settings property" do expect(Puppet::Type.type(:package).attrtype(:package_settings)).to eq(:property) end it "should have a flavor property" do expect(Puppet::Type.type(:package).attrtype(:flavor)).to eq(:property) end end describe "when validating attribute values" do before :each do @provider = double( 'provider', :class => Puppet::Type.type(:package).defaultprovider, :clear => nil, :validate_source => nil ) allow(Puppet::Type.type(:package).defaultprovider).to receive(:new).and_return(@provider) end after :each do Puppet::Type.type(:package).defaultprovider = nil end it "should support :present as a value to :ensure" do Puppet::Type.type(:package).new(:name => "yay", :ensure => :present) end it "should alias :installed to :present as a value to :ensure" do pkg = Puppet::Type.type(:package).new(:name => "yay", :ensure => :installed) expect(pkg.should(:ensure)).to eq(:present) end it "should support :absent as a value to :ensure" do Puppet::Type.type(:package).new(:name => "yay", :ensure => :absent) end it "should support :purged as a value to :ensure if the provider has the :purgeable feature" do expect(@provider).to receive(:satisfies?).with([:purgeable]).and_return(true) Puppet::Type.type(:package).new(:name => "yay", :ensure => :purged) end it "should not support :purged as a value to :ensure if the provider does not have the :purgeable feature" do expect(@provider).to receive(:satisfies?).with([:purgeable]).and_return(false) expect { Puppet::Type.type(:package).new(:name => "yay", :ensure => :purged) }.to raise_error(Puppet::Error) end it "should support :latest as a value to :ensure if the provider has the :upgradeable feature" do expect(@provider).to receive(:satisfies?).with([:upgradeable]).and_return(true) Puppet::Type.type(:package).new(:name => "yay", :ensure => :latest) end it "should not support :latest as a value to :ensure if the provider does not have the :upgradeable feature" do expect(@provider).to receive(:satisfies?).with([:upgradeable]).and_return(false) expect { Puppet::Type.type(:package).new(:name => "yay", :ensure => :latest) }.to raise_error(Puppet::Error) end it "should support version numbers as a value to :ensure if the provider has the :versionable feature" do expect(@provider).to receive(:satisfies?).with([:versionable]).and_return(true) Puppet::Type.type(:package).new(:name => "yay", :ensure => "1.0") end it "should not support version numbers as a value to :ensure if the provider does not have the :versionable feature" do expect(@provider).to receive(:satisfies?).with([:versionable]).and_return(false) expect { Puppet::Type.type(:package).new(:name => "yay", :ensure => "1.0") }.to raise_error(Puppet::Error) end it "should accept any string as an argument to :source" do expect { Puppet::Type.type(:package).new(:name => "yay", :source => "stuff") }.to_not raise_error end it "should not accept a non-string name" do expect do Puppet::Type.type(:package).new(:name => ["error"]) end.to raise_error(Puppet::ResourceError, /Name must be a String/) end end module PackageEvaluationTesting def setprops(properties) allow(@provider).to receive(:properties).and_return(properties) end end describe Puppet::Type.type(:package) do before :each do @provider = double( 'provider', :class => Puppet::Type.type(:package).defaultprovider, :clear => nil, :satisfies? => true, :name => :mock, :validate_source => nil ) allow(Puppet::Type.type(:package).defaultprovider).to receive(:new).and_return(@provider) allow(Puppet::Type.type(:package).defaultprovider).to receive(:instances).and_return([]) @package = Puppet::Type.type(:package).new(:name => "yay") @catalog = Puppet::Resource::Catalog.new @catalog.add_resource(@package) end describe Puppet::Type.type(:package), "when it should be purged" do include PackageEvaluationTesting before { @package[:ensure] = :purged } it "should do nothing if it is :purged" do expect(@provider).to receive(:properties).and_return(:ensure => :purged).at_least(:once) @catalog.apply end [:absent, :installed, :present, :latest].each do |state| it "should purge if it is #{state.to_s}" do allow(@provider).to receive(:properties).and_return(:ensure => state) expect(@provider).to receive(:purge) @catalog.apply end end end describe Puppet::Type.type(:package), "when it should be absent" do include PackageEvaluationTesting before { @package[:ensure] = :absent } [:purged, :absent].each do |state| it "should do nothing if it is #{state.to_s}" do expect(@provider).to receive(:properties).and_return(:ensure => state).at_least(:once) @catalog.apply end end [:installed, :present, :latest].each do |state| it "should uninstall if it is #{state.to_s}" do allow(@provider).to receive(:properties).and_return(:ensure => state) expect(@provider).to receive(:uninstall) @catalog.apply end end end describe Puppet::Type.type(:package), "when it should be present" do include PackageEvaluationTesting before { @package[:ensure] = :present } [:present, :latest, "1.0"].each do |state| it "should do nothing if it is #{state.to_s}" do expect(@provider).to receive(:properties).and_return(:ensure => state).at_least(:once) @catalog.apply end end [:purged, :absent].each do |state| it "should install if it is #{state.to_s}" do allow(@provider).to receive(:properties).and_return(:ensure => state) expect(@provider).to receive(:install) @catalog.apply end end end describe Puppet::Type.type(:package), "when it should be latest" do include PackageEvaluationTesting before { @package[:ensure] = :latest } [:purged, :absent].each do |state| it "should upgrade if it is #{state.to_s}" do allow(@provider).to receive(:properties).and_return(:ensure => state) expect(@provider).to receive(:update) @catalog.apply end end it "should upgrade if the current version is not equal to the latest version" do allow(@provider).to receive(:properties).and_return(:ensure => "1.0") allow(@provider).to receive(:latest).and_return("2.0") expect(@provider).to receive(:update) @catalog.apply end it "should do nothing if it is equal to the latest version" do allow(@provider).to receive(:properties).and_return(:ensure => "1.0") allow(@provider).to receive(:latest).and_return("1.0") expect(@provider).not_to receive(:update) @catalog.apply end it "should do nothing if the provider returns :present as the latest version" do allow(@provider).to receive(:properties).and_return(:ensure => :present) allow(@provider).to receive(:latest).and_return("1.0") expect(@provider).not_to receive(:update) @catalog.apply end end describe Puppet::Type.type(:package), "when it should be a specific version" do include PackageEvaluationTesting before { @package[:ensure] = "1.0" } [:purged, :absent].each do |state| it "should install if it is #{state.to_s}" do allow(@provider).to receive(:properties).and_return(:ensure => state) expect(@package.property(:ensure).insync?(state)).to be_falsey expect(@provider).to receive(:install) @catalog.apply end end it "should do nothing if the current version is equal to the desired version" do allow(@provider).to receive(:properties).and_return(:ensure => "1.0") expect(@package.property(:ensure).insync?('1.0')).to be_truthy expect(@provider).not_to receive(:install) @catalog.apply end it "should install if the current version is not equal to the specified version" do allow(@provider).to receive(:properties).and_return(:ensure => "2.0") expect(@package.property(:ensure).insync?('2.0')).to be_falsey expect(@provider).to receive(:install) @catalog.apply end describe "when current value is an array" do let(:installed_versions) { ["1.0", "2.0", "3.0"] } before (:each) do allow(@provider).to receive(:properties).and_return(:ensure => installed_versions) end it "should install if value not in the array" do @package[:ensure] = "1.5" expect(@package.property(:ensure).insync?(installed_versions)).to be_falsey expect(@provider).to receive(:install) @catalog.apply end it "should not install if value is in the array" do @package[:ensure] = "2.0" expect(@package.property(:ensure).insync?(installed_versions)).to be_truthy expect(@provider).not_to receive(:install) @catalog.apply end describe "when ensure is set to 'latest'" do it "should not install if the value is in the array" do expect(@provider).to receive(:latest).and_return("3.0") @package[:ensure] = "latest" expect(@package.property(:ensure).insync?(installed_versions)).to be_truthy expect(@provider).not_to receive(:install) @catalog.apply end end end end describe Puppet::Type.type(:package), "when responding to refresh" do include PackageEvaluationTesting it "should support :true as a value to :reinstall_on_refresh" do srv = Puppet::Type.type(:package).new(:name => "yay", :reinstall_on_refresh => :true) expect(srv[:reinstall_on_refresh]).to eq(:true) end it "should support :false as a value to :reinstall_on_refresh" do srv = Puppet::Type.type(:package).new(:name => "yay", :reinstall_on_refresh => :false) expect(srv[:reinstall_on_refresh]).to eq(:false) end it "should specify :false as the default value of :reinstall_on_refresh" do srv = Puppet::Type.type(:package).new(:name => "yay") expect(srv[:reinstall_on_refresh]).to eq(:false) end [:latest, :present, :installed].each do |state| it "should reinstall if it should be #{state.to_s} and reinstall_on_refresh is true" do @package[:ensure] = state @package[:reinstall_on_refresh] = :true allow(@provider).to receive(:reinstallable?).and_return(true) expect(@provider).to receive(:reinstall).once @package.refresh end it "should reinstall if it should be #{state.to_s} and reinstall_on_refresh is false" do @package[:ensure] = state @package[:reinstall_on_refresh] = :false allow(@provider).to receive(:reinstallable?).and_return(true) expect(@provider).not_to receive(:reinstall) @package.refresh end end [:purged, :absent].each do |state| it "should not reinstall if it should be #{state.to_s} and reinstall_on_refresh is true" do @package[:ensure] = state allow(@provider).to receive(:reinstallable?).and_return(true) expect(@provider).not_to receive(:reinstall) @package.refresh end it "should not reinstall if it should be #{state.to_s} and reinstall_on_refresh is false" do @package[:ensure] = state allow(@provider).to receive(:reinstallable?).and_return(true) expect(@provider).not_to receive(:reinstall) @package.refresh end end end end it "should select dnf over yum for dnf supported fedora versions" do dnf = Puppet::Type.type(:package).provider(:dnf) yum = Puppet::Type.type(:package).provider(:yum) allow(Facter).to receive(:value).with('os.family').and_return(:redhat) allow(Facter).to receive(:value).with('os.name').and_return(:fedora) allow(Facter).to receive(:value).with('os.release.major').and_return("22") expect(dnf.specificity).to be > yum.specificity end describe "allow_virtual" do it "defaults to true on platforms that support virtual packages" do pkg = Puppet::Type.type(:package).new(:name => 'yay', :provider => :yum) expect(pkg[:allow_virtual]).to eq true end it "defaults to false on dpkg provider" do pkg = Puppet::Type.type(:package).new(:name => 'yay', :provider => :dpkg) expect(pkg[:allow_virtual]).to be_nil end it "defaults to false on platforms that do not support virtual packages" do pkg = Puppet::Type.type(:package).new(:name => 'yay', :provider => :apple) expect(pkg[:allow_virtual]).to be_nil end end end