From 97aaf5bbcdfd0810722b123bdc67e883a7ca8077 Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Fri, 24 Oct 2014 10:45:43 -0700 Subject: Chef-12 RC Provider Resolver makes resource and provider class resolution more dynamic. begins deprecation of Chef::Platform static mapping. --- spec/support/lib/chef/provider/snakeoil.rb | 1 + spec/support/lib/chef/resource/zen_follower.rb | 2 +- .../unit/resource/static_provider_resolution.rb | 71 +++ spec/unit/node_map_spec.rb | 155 +++++++ spec/unit/provider/log_spec.rb | 4 - spec/unit/provider/package/apt_spec.rb | 2 +- spec/unit/provider_resolver_spec.rb | 384 ++++++++++++++-- spec/unit/recipe_spec.rb | 17 +- spec/unit/resource/apt_package_spec.rb | 21 +- spec/unit/resource/breakpoint_spec.rb | 12 +- spec/unit/resource/chef_gem_spec.rb | 21 +- spec/unit/resource/deploy_revision_spec.rb | 31 +- spec/unit/resource/deploy_spec.rb | 13 +- spec/unit/resource/dpkg_package_spec.rb | 22 +- spec/unit/resource/easy_install_package_spec.rb | 25 +- spec/unit/resource/gem_package_spec.rb | 21 +- spec/unit/resource/git_spec.rb | 12 +- spec/unit/resource/homebrew_package_spec.rb | 25 +- spec/unit/resource/ips_package_spec.rb | 21 +- spec/unit/resource/macports_package_spec.rb | 21 +- spec/unit/resource/pacman_package_spec.rb | 22 +- spec/unit/resource/rpm_package_spec.rb | 22 +- spec/unit/resource/service_spec.rb | 12 +- spec/unit/resource/smartos_package_spec.rb | 25 +- spec/unit/resource/solaris_package_spec.rb | 39 +- spec/unit/resource/subversion_spec.rb | 12 +- spec/unit/resource/timestamped_deploy_spec.rb | 34 +- spec/unit/resource/yum_package_spec.rb | 23 +- spec/unit/resource_platform_map_spec.rb | 164 ------- spec/unit/resource_spec.rb | 49 ++- spec/unit/runner_spec.rb | 483 +++++++++++---------- 31 files changed, 1037 insertions(+), 729 deletions(-) create mode 100644 spec/support/shared/unit/resource/static_provider_resolution.rb create mode 100644 spec/unit/node_map_spec.rb delete mode 100644 spec/unit/resource_platform_map_spec.rb (limited to 'spec') diff --git a/spec/support/lib/chef/provider/snakeoil.rb b/spec/support/lib/chef/provider/snakeoil.rb index e9d01f654f..485d37329f 100644 --- a/spec/support/lib/chef/provider/snakeoil.rb +++ b/spec/support/lib/chef/provider/snakeoil.rb @@ -19,6 +19,7 @@ class Chef class Provider class SnakeOil < Chef::Provider + def load_current_resource true end diff --git a/spec/support/lib/chef/resource/zen_follower.rb b/spec/support/lib/chef/resource/zen_follower.rb index 713f122f06..ddc289e48d 100644 --- a/spec/support/lib/chef/resource/zen_follower.rb +++ b/spec/support/lib/chef/resource/zen_follower.rb @@ -22,7 +22,7 @@ class Chef class Resource class ZenFollower < Chef::Resource - provides :follower, :on_platforms => ["zen"] + provides :follower, platform: "zen" def initialize(name, run_context=nil) @resource_name = :zen_follower diff --git a/spec/support/shared/unit/resource/static_provider_resolution.rb b/spec/support/shared/unit/resource/static_provider_resolution.rb new file mode 100644 index 0000000000..147852598a --- /dev/null +++ b/spec/support/shared/unit/resource/static_provider_resolution.rb @@ -0,0 +1,71 @@ +# +# Author:: Lamont Granquist () +# Copyright:: Copyright (c) 2014 Chef Software, Inc. +# 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. +# + + + +# +# This is for typical "static" provider resolution which maps resources onto +# providers based only on the node data. Its not really 'static' because it +# all goes through the Chef::ProviderResolver, but the effective result is +# a static mapping for the node (unlike the service resource which is +# complicated). +# +def static_provider_resolution(opts={}) + action = opts[:action] + provider_class = opts[:provider] + resource_class = opts[:resource] + name = opts[:name] + os = opts[:os] + platform_family = opts[:platform_family] + platform_version = opts[:platform_version] + + describe resource_class, "static provider initialization" do + let(:node) { + node = Chef::Node.new + node.automatic_attrs[:os] = os + node.automatic_attrs[:platform_family] = platform_family + node.automatic_attrs[:platform_version] = platform_version + node + } + let(:events) { Chef::EventDispatch::Dispatcher.new } + let(:provider_resolver) { Chef::ProviderResolver.new(node) } + let(:run_context) { + run_context = Chef::RunContext.new(node, {}, events) + run_context.provider_resolver = provider_resolver + run_context + } + let(:resource) { resource_class.new("foo", run_context) } + + it "should return a #{resource_class}" do + expect(resource).to be_a_kind_of(resource_class) + end + + it "should set the resource_name to #{name}" do + expect(resource.resource_name).to eql(name) + end + + it "should leave the provider nil" do + expect(resource.provider).to eql(nil) + end + + it "should resolve to a #{provider_class}" do + expect(resource.provider_for_action(action)).to be_a(provider_class) + end + end +end + diff --git a/spec/unit/node_map_spec.rb b/spec/unit/node_map_spec.rb new file mode 100644 index 0000000000..fe7372961b --- /dev/null +++ b/spec/unit/node_map_spec.rb @@ -0,0 +1,155 @@ +# +# Author:: Lamont Granquist () +# Copyright:: Copyright (c) 2014 Chef Software, Inc. +# 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' +require 'chef/node_map' + +describe Chef::NodeMap do + + let(:node_map) { Chef::NodeMap.new } + + let(:node) { Chef::Node.new } + + describe "with a bad filter name" do + it "should raise an error" do + expect{ node_map.set(node, :thing, on_platform_family: 'rhel') }.to raise_error + end + end + + describe "when no matchers are set at all" do + before do + node_map.set(:thing, :foo) + end + + it "returns the value" do + expect(node_map.get(node, :thing)).to eql(:foo) + end + + it "returns nil for keys that do not exist" do + expect(node_map.get(node, :other_thing)).to eql(nil) + end + end + + describe "filtering by os" do + before do + node_map.set(:thing, :foo, os: ["windows"]) + node_map.set(:thing, :bar, os: "linux") + end + it "returns the correct value for windows" do + allow(node).to receive(:[]).with(:os).and_return("windows") + expect(node_map.get(node, :thing)).to eql(:foo) + end + it "returns the correct value for linux" do + allow(node).to receive(:[]).with(:os).and_return("linux") + expect(node_map.get(node, :thing)).to eql(:bar) + end + it "returns nil for a non-matching os" do + allow(node).to receive(:[]).with(:os).and_return("freebsd") + expect(node_map.get(node, :thing)).to eql(nil) + end + end + + describe "rejecting an os" do + before do + node_map.set(:thing, :foo, os: "!windows") + end + it "returns nil for windows" do + allow(node).to receive(:[]).with(:os).and_return("windows") + expect(node_map.get(node, :thing)).to eql(nil) + end + it "returns the correct value for linux" do + allow(node).to receive(:[]).with(:os).and_return("linux") + expect(node_map.get(node, :thing)).to eql(:foo) + end + end + + describe "filtering by os and platform_family" do + before do + node_map.set(:thing, :bar, os: "linux", platform_family: "rhel") + end + + it "returns the correct value when both match" do + allow(node).to receive(:[]).with(:os).and_return("linux") + allow(node).to receive(:[]).with(:platform_family).and_return("rhel") + expect(node_map.get(node, :thing)).to eql(:bar) + end + + it "returns nil for a non-matching os" do + allow(node).to receive(:[]).with(:os).and_return("freebsd") + expect(node_map.get(node, :thing)).to eql(nil) + end + + it "returns nil when the platform_family does not match" do + allow(node).to receive(:[]).with(:os).and_return("linux") + allow(node).to receive(:[]).with(:platform_family).and_return("debian") + expect(node_map.get(node, :thing)).to eql(nil) + end + end + + describe "with a block doing platform_version checks" do + before do + node_map.set(:thing, :foo, platform_family: "rhel") do |node| + node[:platform_version].to_i >= 7 + end + end + + it "returns the value when the node matches" do + allow(node).to receive(:[]).with(:platform_family).and_return("rhel") + allow(node).to receive(:[]).with(:platform_version).and_return("7.0") + expect(node_map.get(node, :thing)).to eql(:foo) + end + + it "returns nil when the block does not match" do + allow(node).to receive(:[]).with(:platform_family).and_return("rhel") + allow(node).to receive(:[]).with(:platform_version).and_return("6.4") + expect(node_map.get(node, :thing)).to eql(nil) + end + + it "returns nil when the platform_family filter does not match" do + allow(node).to receive(:[]).with(:platform_family).and_return("debian") + allow(node).to receive(:[]).with(:platform_version).and_return("7.0") + expect(node_map.get(node, :thing)).to eql(nil) + end + + it "returns nil when both do not match" do + allow(node).to receive(:[]).with(:platform_family).and_return("debian") + allow(node).to receive(:[]).with(:platform_version).and_return("6.0") + expect(node_map.get(node, :thing)).to eql(nil) + end + end + + describe "resource back-compat testing" do + it "should handle :on_platforms => :all" do + node_map.set(:chef_gem, :foo, :on_platforms => :all) + allow(node).to receive(:[]).with(:platform).and_return("windows") + expect(node_map.get(node, :chef_gem)).to eql(:foo) + end + it "should handle :on_platforms => [ 'windows' ]" do + node_map.set(:dsc_script, :foo, :on_platforms => [ 'windows' ]) + allow(node).to receive(:[]).with(:platform).and_return("windows") + expect(node_map.get(node, :dsc_script)).to eql(:foo) + end + it "should handle :on_platform => :all" do + node_map.set(:link, :foo, :on_platform => :all) + allow(node).to receive(:[]).with(:platform).and_return("windows") + expect(node_map.get(node, :link)).to eql(:foo) + end + end + +end + diff --git a/spec/unit/provider/log_spec.rb b/spec/unit/provider/log_spec.rb index a270ee4822..1ecc633ce1 100644 --- a/spec/unit/provider/log_spec.rb +++ b/spec/unit/provider/log_spec.rb @@ -32,10 +32,6 @@ describe Chef::Provider::Log::ChefLog do let(:provider) { Chef::Provider::Log::ChefLog.new(new_resource, run_context) } - it "should be registered with the default platform hash" do - expect(Chef::Platform.platforms[:default][:log]).not_to be_nil - end - it "should write the string to the Chef::Log object at default level (info)" do expect(Chef::Log).to receive(:info).with(log_str).and_return(true) provider.run_action(:write) diff --git a/spec/unit/provider/package/apt_spec.rb b/spec/unit/provider/package/apt_spec.rb index a94b248418..90e9dd6d3f 100644 --- a/spec/unit/provider/package/apt_spec.rb +++ b/spec/unit/provider/package/apt_spec.rb @@ -229,7 +229,7 @@ SHOWPKG_STDOUT @new_resource = nil @new_resource = Chef::Resource::AptPackage.new("irssi", @run_context) @new_resource.default_release("lenny-backports") - + @new_resource.provider = @provider @provider.new_resource = @new_resource @provider.should_receive(:shell_out!).with( diff --git a/spec/unit/provider_resolver_spec.rb b/spec/unit/provider_resolver_spec.rb index bc65bdc13c..927cca4f58 100644 --- a/spec/unit/provider_resolver_spec.rb +++ b/spec/unit/provider_resolver_spec.rb @@ -1,6 +1,6 @@ # -# Author:: Richard Manyanza () -# Copyright:: Copyright (c) 2014 Richard Manyanza. +# Author:: Lamont Granquist () +# Copyright:: Copyright (c) 2014 Opscode, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,74 +17,370 @@ # require 'spec_helper' +require 'chef/mixin/convert_to_class_name' + +include Chef::Mixin::ConvertToClassName describe Chef::ProviderResolver do - before(:each) do - @node = Chef::Node.new - @provider_resolver = Chef::ProviderResolver.new(@node) + + let(:node) do + node = Chef::Node.new + allow(node).to receive(:[]).with(:os).and_return(os) + allow(node).to receive(:[]).with(:platform_family).and_return(platform_family) + allow(node).to receive(:[]).with(:platform).and_return(platform) + allow(node).to receive(:[]).with(:platform_version).and_return(platform_version) + allow(node).to receive(:is_a?).and_return(Chef::Node) + node end - describe "Initialization" do - it "should not load providers" do - @provider_resolver.loaded?.should be_false + let(:provider_resolver) { Chef::ProviderResolver.new(node) } + + let(:action) { :start } + + let(:resolved_provider) { provider_resolver.resolve(resource, action) } + + let(:provider) { nil } + + let(:resource_name) { :service } + + let(:resource) { double(Chef::Resource, provider: provider, resource_name: resource_name) } + + describe "resolving service resource" do + def stub_service_providers(*services) + services ||= [] + allow(Chef::Platform::ServiceHelpers).to receive(:service_resource_providers) + .and_return(services) end - end + def stub_service_configs(*configs) + configs ||= [] + allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp") + .and_return(configs) + end - describe "Loading providers" do - end + before do + expect(provider_resolver).not_to receive(:maybe_chef_platform_lookup) + allow(resource).to receive(:service_name).and_return("ntp") + end + + shared_examples_for "a debian platform with upstart and update-rc.d" do + before do + stub_service_providers(:debian, :invokercd, :upstart) + end + + it "when only the SysV init script exists, it returns a Service::Debian provider" do + allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp") + .and_return( [ :initd ] ) + expect(resolved_provider).to eql(Chef::Provider::Service::Debian) + end + it "when both SysV and Upstart scripts exist, it returns a Service::Upstart provider" do + allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp") + .and_return( [ :initd, :upstart ] ) + expect(resolved_provider).to eql(Chef::Provider::Service::Upstart) + end + + it "when only the Upstart script exists, it returns a Service::Upstart provider" do + allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp") + .and_return( [ :upstart ] ) + expect(resolved_provider).to eql(Chef::Provider::Service::Upstart) + end - describe "on FreeBSD" do - before(:each) do - @node.normal[:platform] = :freebsd + it "when both do not exist, it calls the old style provider resolver and returns a Debian Provider" do + allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp") + .and_return( [ ] ) + expect(resolved_provider).to eql(Chef::Provider::Service::Debian) + end end - describe "loading" do - before(:each) do - @provider_resolver.load + shared_examples_for "a debian platform using the insserv provider" do + context "with a default install" do + before do + stub_service_providers(:debian, :invokercd, :insserv) + end + + it "uses the Service::Insserv Provider to manage sysv init scripts" do + allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp") + .and_return( [ :initd ] ) + expect(resolved_provider).to eql(Chef::Provider::Service::Insserv) + end end - it "should load FreeBSD providers" do - providers = [ - Chef::Provider::User::Pw, - Chef::Provider::Group::Pw, - Chef::Provider::Service::Freebsd, - Chef::Provider::Package::Freebsd, - Chef::Provider::Cron - ] + context "when the user has installed upstart" do + before do + stub_service_providers(:debian, :invokercd, :insserv, :upstart) + end + + it "when only the SysV init script exists, it returns a Service::Debian provider" do + allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp") + .and_return( [ :initd ] ) + expect(resolved_provider).to eql(Chef::Provider::Service::Insserv) + end + + it "when both SysV and Upstart scripts exist, it returns a Service::Upstart provider" do + allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp") + .and_return( [ :initd, :upstart ] ) + expect(resolved_provider).to eql(Chef::Provider::Service::Upstart) + end - @provider_resolver.providers.length.should == providers.length - providers.each do |provider| - @provider_resolver.providers.include?(provider).should be_true + it "when only the Upstart script exists, it returns a Service::Upstart provider" do + allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp") + .and_return( [ :upstart ] ) + expect(resolved_provider).to eql(Chef::Provider::Service::Upstart) + end + + it "when both do not exist, it calls the old style provider resolver and returns a Debian Provider" do + allow(Chef::Platform::ServiceHelpers).to receive(:config_for_service).with("ntp") + .and_return( [ ] ) + expect(resolved_provider).to eql(Chef::Provider::Service::Insserv) end end end - describe "resolving" do - it "should handle user" do - user = Chef::Resource::User.new('toor') - @provider_resolver.resolve(user).should == Chef::Provider::User::Pw + describe "on Linux" do + end + + describe "on Ubuntu 14.04" do + let(:os) { "linux" } + let(:platform) { "ubuntu" } + let(:platform_family) { "debian" } + let(:platform_version) { "14.04" } + + it_behaves_like "a debian platform with upstart and update-rc.d" + end + + describe "on Ubuntu 10.04" do + let(:os) { "linux" } + let(:platform) { "ubuntu" } + let(:platform_family) { "debian" } + let(:platform_version) { "10.04" } + + it_behaves_like "a debian platform with upstart and update-rc.d" + end + + # old debian uses the Debian provider (does not have insserv or upstart, or update-rc.d???) + describe "on Debian 4.0" do + let(:os) { "linux" } + let(:platform) { "debian" } + let(:platform_family) { "debian" } + let(:platform_version) { "4.0" } + + #it_behaves_like "a debian platform using the debian provider" + end + + # Debian replaced the debian provider with insserv in the FIXME:VERSION distro + describe "on Debian 7.0" do + let(:os) { "linux" } + let(:platform) { "debian" } + let(:platform_family) { "debian" } + let(:platform_version) { "7.0" } + + it_behaves_like "a debian platform using the insserv provider" + end + + %w{solaris2 openindiana opensolaris nexentacore omnios smartos}.each do |platform| + describe "on #{platform}" do + let(:os) { "solaris2" } + let(:platform) { platform } + let(:platform_family) { platform } + let(:platform_version) { "5.11" } + + it "returns a Solaris provider" do + stub_service_providers + stub_service_configs + expect(resolved_provider).to eql(Chef::Provider::Service::Solaris) + end + + it "always returns a Solaris provider" do + # no matter what we stub on the next two lines we should get a Solaris provider + stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd) + stub_service_configs(:initd, :upstart, :xinetd, :user_local_etc_rcd, :systemd) + expect(resolved_provider).to eql(Chef::Provider::Service::Solaris) + end + end + end + + %w{mswin mingw32 windows}.each do |platform| + describe "on #{platform}" do + let(:os) { "windows" } + let(:platform) { platform } + let(:platform_family) { "windows" } + let(:platform_version) { "5.11" } + + it "returns a Windows provider" do + stub_service_providers + stub_service_configs + expect(resolved_provider).to eql(Chef::Provider::Service::Windows) + end + + it "always returns a Windows provider" do + # no matter what we stub on the next two lines we should get a Windows provider + stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd) + stub_service_configs(:initd, :upstart, :xinetd, :user_local_etc_rcd, :systemd) + expect(resolved_provider).to eql(Chef::Provider::Service::Windows) + end end + end - it "should handle group" do - group = Chef::Resource::Group.new('ops') - @provider_resolver.resolve(group).should == Chef::Provider::Group::Pw + %w{mac_os_x mac_os_x_server}.each do |platform| + describe "on #{platform}" do + let(:os) { "darwin" } + let(:platform) { platform } + let(:platform_family) { "mac_os_x" } + let(:platform_version) { "10.9.2" } + + it "returns a Macosx provider" do + stub_service_providers + stub_service_configs + expect(resolved_provider).to eql(Chef::Provider::Service::Macosx) + end + + it "always returns a Macosx provider" do + # no matter what we stub on the next two lines we should get a Macosx provider + stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd) + stub_service_configs(:initd, :upstart, :xinetd, :user_local_etc_rcd, :systemd) + expect(resolved_provider).to eql(Chef::Provider::Service::Macosx) + end end + end - it "should handle service" do - service = Chef::Resource::Service.new('nginx') - @provider_resolver.resolve(service).should == Chef::Provider::Service::Freebsd + %w{freebsd netbsd}.each do |platform| + describe "on #{platform}" do + let(:os) { platform } + let(:platform) { platform } + let(:platform_family) { platform } + let(:platform_version) { "10.0-RELEASE" } + + it "returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do + stub_service_providers + stub_service_configs(:usr_local_etc_rcd) + expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd) + end + + it "returns a Freebsd provider if it finds the /etc/rc.d initscript" do + stub_service_providers + stub_service_configs(:etc_rcd) + expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd) + end + + it "always returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do + # should only care about :usr_local_etc_rcd stub in the service configs + stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd) + stub_service_configs(:usr_local_etc_rcd, :initd, :upstart, :xinetd, :systemd) + expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd) + end + + it "always returns a Freebsd provider if it finds the /usr/local/etc/rc.d initscript" do + # should only care about :etc_rcd stub in the service configs + stub_service_providers(:debian, :invokercd, :insserv, :upstart, :redhat, :systemd) + stub_service_configs(:etc_rcd, :initd, :upstart, :xinetd, :systemd) + expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd) + end + + it "foo" do + stub_service_providers + stub_service_configs + expect(resolved_provider).to eql(Chef::Provider::Service::Freebsd) + end end + end + + end + + describe "resolving static providers" do + def resource_class(resource) + Chef::Resource.const_get(convert_to_class_name(resource.to_s)) + end + static_mapping = { + apt_package: Chef::Provider::Package::Apt, + bash: Chef::Provider::Script, + bff_package: Chef::Provider::Package::Aix, + breakpoint: Chef::Provider::Breakpoint, + chef_gem: Chef::Provider::Package::Rubygems, + cookbook_file: Chef::Provider::CookbookFile, + csh: Chef::Provider::Script, + deploy: Chef::Provider::Deploy::Timestamped, + deploy_revision: Chef::Provider::Deploy::Revision, + directory: Chef::Provider::Directory, + dpkg_package: Chef::Provider::Package::Dpkg, + dsc_script: Chef::Provider::DscScript, + easy_install_package: Chef::Provider::Package::EasyInstall, + erl_call: Chef::Provider::ErlCall, + execute: Chef::Provider::Execute, + file: Chef::Provider::File, + gem_package: Chef::Provider::Package::Rubygems, + git: Chef::Provider::Git, + homebrew_package: Chef::Provider::Package::Homebrew, + http_request: Chef::Provider::HttpRequest, + ips_package: Chef::Provider::Package::Ips, + link: Chef::Provider::Link, + log: Chef::Provider::Log::ChefLog, + macports_package: Chef::Provider::Package::Macports, + pacman_package: Chef::Provider::Package::Pacman, + paludis_package: Chef::Provider::Package::Paludis, + perl: Chef::Provider::Script, + portage_package: Chef::Provider::Package::Portage, + python: Chef::Provider::Script, + remote_directory: Chef::Provider::RemoteDirectory, + route: Chef::Provider::Route, + rpm_package: Chef::Provider::Package::Rpm, + ruby: Chef::Provider::Script, + ruby_block: Chef::Provider::RubyBlock, + script: Chef::Provider::Script, + smartos_package: Chef::Provider::Package::SmartOS, + solaris_package: Chef::Provider::Package::Solaris, + subversion: Chef::Provider::Subversion, + template: Chef::Provider::Template, + timestamped_deploy: Chef::Provider::Deploy::Timestamped, + whyrun_safe_ruby_block: Chef::Provider::WhyrunSafeRubyBlock, + windows_package: Chef::Provider::Package::Windows, + windows_service: Chef::Provider::Service::Windows, + yum_package: Chef::Provider::Package::Yum, + } - it "should handle package" do - package = Chef::Resource::Package.new('zsh') - @provider_resolver.resolve(package).should == Chef::Provider::Package::Freebsd + describe "on Ubuntu 14.04" do + let(:os) { "linux" } + let(:platform) { "ubuntu" } + let(:platform_family) { "debian" } + let(:platform_version) { "14.04" } + + supported_providers = [ + :apt_package, :bash, :breakpoint, :chef_gem, :cookbook_file, :csh, :deploy, + :deploy_revision, :directory, :dpkg_package, :easy_install_package, + :erl_call, :execute, :file, :gem_package, :git, :http_request, :link, :log, :pacman_package, :paludis_package, + :perl, :python, :remote_directory, :route, :rpm_package, :ruby, :ruby_block, :script, + :subversion, :template, :timestamped_deploy, :whyrun_safe_ruby_block, :yum_package, + ] + + supported_providers.each do |static_resource| + static_provider = static_mapping[static_resource] + context "when the resource is a #{static_resource}" do + let(:resource) { double(Chef::Resource, provider: nil, resource_name: static_resource) } + let(:action) { :start } # in reality this doesn't matter much + it "should resolve to a #{static_provider} provider" do + expect(provider_resolver).not_to receive(:maybe_chef_platform_lookup) + expect(resolved_provider).to eql(static_provider) + end + end end - it "should handle cron" do - cron = Chef::Resource::Cron.new('security_status_report') - @provider_resolver.resolve(cron).should == Chef::Provider::Cron + unsupported_providers = [ + :bff_package, :dsc_script, :homebrew_package, :ips_package, :macports_package, + :smartos_package, :solaris_package, :windows_package, + :windows_service, + ] + + unsupported_providers.each do |static_resource| + static_provider = static_mapping[static_resource] + context "when the resource is a #{static_resource}" do + let(:resource) { double(Chef::Resource, provider: nil, resource_name: static_resource) } + let(:action) { :start } # in reality this doesn't matter much + it "should fall back into the old provider mapper code and hooks" do + retval = Object.new + expect(provider_resolver).to receive(:maybe_chef_platform_lookup).and_return(retval) + expect(resolved_provider).to equal(retval) + end + end end end end diff --git a/spec/unit/recipe_spec.rb b/spec/unit/recipe_spec.rb index cb7581b5fb..0e660dc0cc 100644 --- a/spec/unit/recipe_spec.rb +++ b/spec/unit/recipe_spec.rb @@ -119,7 +119,8 @@ describe Chef::Recipe do describe "should locate platform mapped resources" do it "locate resource for particular platform" do - Object.const_set('ShaunTheSheep', Class.new(Chef::Resource){ provides :laughter, :on_platforms => ["television"] }) + ShaunTheSheep = Class.new(Chef::Resource) + ShaunTheSheep.provides :laughter, :on_platforms => ["television"] node.automatic[:platform] = "television" node.automatic[:platform_version] = "123" res = recipe.laughter "timmy" @@ -128,7 +129,8 @@ describe Chef::Recipe do end it "locate a resource for all platforms" do - Object.const_set("YourMom", Class.new(Chef::Resource){ provides :love_and_caring }) + YourMom = Class.new(Chef::Resource) + YourMom.provides :love_and_caring res = recipe.love_and_caring "mommy" res.name.should eql("mommy") res.kind_of?(YourMom) @@ -188,16 +190,7 @@ describe Chef::Recipe do # zen_follower resource has this: # provides :follower, :on_platforms => ["zen"] before do - node.stub(:[]) do |key| - case key - when :platform - :zen - when :platform_version - "1.0.0" - else - nil - end - end + node.automatic_attrs[:platform] = "zen" end let(:resource_follower) do diff --git a/spec/unit/resource/apt_package_spec.rb b/spec/unit/resource/apt_package_spec.rb index 58b007c327..9503e0cbe1 100644 --- a/spec/unit/resource/apt_package_spec.rb +++ b/spec/unit/resource/apt_package_spec.rb @@ -17,25 +17,22 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::AptPackage, "initialize" do + static_provider_resolution( + resource: Chef::Resource::AptPackage, + provider: Chef::Provider::Package::Apt, + name: :apt_package, + action: :install, + os: "linux", + ) + before(:each) do @resource = Chef::Resource::AptPackage.new("foo") end - it "should return a Chef::Resource::AptPackage" do - @resource.should be_a_kind_of(Chef::Resource::AptPackage) - end - - it "should set the resource_name to :apt_package" do - @resource.resource_name.should eql(:apt_package) - end - - it "should set the provider to Chef::Provider::Package::Apt" do - @resource.provider.should eql(Chef::Provider::Package::Apt) - end - it "should support default_release" do @resource.default_release("lenny-backports") @resource.default_release.should eql("lenny-backports") diff --git a/spec/unit/resource/breakpoint_spec.rb b/spec/unit/resource/breakpoint_spec.rb index 412211a038..ed655b84a6 100644 --- a/spec/unit/resource/breakpoint_spec.rb +++ b/spec/unit/resource/breakpoint_spec.rb @@ -17,9 +17,17 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::Breakpoint do + static_provider_resolution( + resource: Chef::Resource::Breakpoint, + provider: Chef::Provider::Breakpoint, + name: :breakpoint, + action: :break, + ) + before do @breakpoint = Chef::Resource::Breakpoint.new end @@ -36,8 +44,4 @@ describe Chef::Resource::Breakpoint do @breakpoint.name.should match(/breakpoint_spec\.rb\:[\d]{2}\:in \`new\'$/) end - it "uses the breakpoint provider" do - @breakpoint.provider.should == Chef::Provider::Breakpoint - end - end diff --git a/spec/unit/resource/chef_gem_spec.rb b/spec/unit/resource/chef_gem_spec.rb index dda65f8741..6a419b3f3b 100644 --- a/spec/unit/resource/chef_gem_spec.rb +++ b/spec/unit/resource/chef_gem_spec.rb @@ -18,24 +18,17 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::ChefGem, "initialize" do - before(:each) do - @resource = Chef::Resource::ChefGem.new("foo") - end - - it "should return a Chef::Resource::ChefGem" do - @resource.should be_a_kind_of(Chef::Resource::ChefGem) - end - - it "should set the resource_name to :chef_gem" do - @resource.resource_name.should eql(:chef_gem) - end + static_provider_resolution( + resource: Chef::Resource::ChefGem, + provider: Chef::Provider::Package::Rubygems, + name: :chef_gem, + action: :install, + ) - it "should set the provider to Chef::Provider::Package::Rubygems" do - @resource.provider.should eql(Chef::Provider::Package::Rubygems) - end end describe Chef::Resource::ChefGem, "gem_binary" do diff --git a/spec/unit/resource/deploy_revision_spec.rb b/spec/unit/resource/deploy_revision_spec.rb index 1f509992aa..d136aa251e 100644 --- a/spec/unit/resource/deploy_revision_spec.rb +++ b/spec/unit/resource/deploy_revision_spec.rb @@ -17,31 +17,26 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::DeployRevision do - it "defaults to the revision deploy provider" do - @resource = Chef::Resource::DeployRevision.new("deploy _this_!") - @resource.provider.should == Chef::Provider::Deploy::Revision - end - - it "has a name of deploy_revision" do - @resource = Chef::Resource::DeployRevision.new("deploy _this_!") - @resource.resource_name.should == :deploy_revision - end + static_provider_resolution( + resource: Chef::Resource::DeployRevision, + provider: Chef::Provider::Deploy::Revision, + name: :deploy_revision, + action: :deploy, + ) end describe Chef::Resource::DeployBranch do - it "defaults to the revision deploy provider" do - @resource = Chef::Resource::DeployBranch.new("deploy _this_!") - @resource.provider.should == Chef::Provider::Deploy::Revision - end - - it "has a name of deploy_branch" do - @resource = Chef::Resource::DeployBranch.new("deploy _this_!") - @resource.resource_name.should == :deploy_branch - end + static_provider_resolution( + resource: Chef::Resource::DeployBranch, + provider: Chef::Provider::Deploy::Revision, + name: :deploy_branch, + action: :deploy, + ) end diff --git a/spec/unit/resource/deploy_spec.rb b/spec/unit/resource/deploy_spec.rb index 7cc25ed41c..914ea19030 100644 --- a/spec/unit/resource/deploy_spec.rb +++ b/spec/unit/resource/deploy_spec.rb @@ -17,9 +17,18 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::Deploy do + static_provider_resolution( + resource: Chef::Resource::Deploy, + provider: Chef::Provider::Deploy::Timestamped, + name: :deploy, + action: :deploy, + ) + + class << self def resource_has_a_string_attribute(attr_name) it "has a String attribute for #{attr_name.to_s}" do @@ -196,10 +205,6 @@ describe Chef::Resource::Deploy do @resource.restart.should == restart_like_this end - it "defaults to using the Deploy::Timestamped provider" do - @resource.provider.should == Chef::Provider::Deploy::Timestamped - end - it "allows providers to be set with a full class name" do @resource.provider Chef::Provider::Deploy::Timestamped @resource.provider.should == Chef::Provider::Deploy::Timestamped diff --git a/spec/unit/resource/dpkg_package_spec.rb b/spec/unit/resource/dpkg_package_spec.rb index 9ef498a577..931e6763bd 100644 --- a/spec/unit/resource/dpkg_package_spec.rb +++ b/spec/unit/resource/dpkg_package_spec.rb @@ -17,22 +17,16 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::DpkgPackage, "initialize" do - before(:each) do - @resource = Chef::Resource::DpkgPackage.new("foo") - end + static_provider_resolution( + resource: Chef::Resource::DpkgPackage, + provider: Chef::Provider::Package::Dpkg, + name: :dpkg_package, + action: :install, + os: 'linux', + ) - it "should return a Chef::Resource::DpkgPackage" do - @resource.should be_a_kind_of(Chef::Resource::DpkgPackage) - end - - it "should set the resource_name to :dpkg_package" do - @resource.resource_name.should eql(:dpkg_package) - end - - it "should set the provider to Chef::Provider::Package::Dpkg" do - @resource.provider.should eql(Chef::Provider::Package::Dpkg) - end end diff --git a/spec/unit/resource/easy_install_package_spec.rb b/spec/unit/resource/easy_install_package_spec.rb index 9682c8177b..d3a5f4a0fe 100644 --- a/spec/unit/resource/easy_install_package_spec.rb +++ b/spec/unit/resource/easy_install_package_spec.rb @@ -17,30 +17,21 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::EasyInstallPackage, "initialize" do + static_provider_resolution( + resource: Chef::Resource::EasyInstallPackage, + provider: Chef::Provider::Package::EasyInstall, + name: :easy_install_package, + action: :install, + ) + before(:each) do @resource = Chef::Resource::EasyInstallPackage.new("foo") end - it "should create a new Chef::Resource::EasyInstallPackage" do - @resource.should be_a_kind_of(Chef::Resource) - @resource.should be_a_kind_of(Chef::Resource::EasyInstallPackage) - end - - it "should return a Chef::Resource::EasyInstallPackage" do - @resource.should be_a_kind_of(Chef::Resource::EasyInstallPackage) - end - - it "should set the resource_name to :easy_install_package" do - @resource.resource_name.should eql(:easy_install_package) - end - - it "should set the provider to Chef::Provider::Package::EasyInstall" do - @resource.provider.should eql(Chef::Provider::Package::EasyInstall) - end - it "should allow you to set the easy_install_binary attribute" do @resource.easy_install_binary "/opt/local/bin/easy_install" @resource.easy_install_binary.should eql("/opt/local/bin/easy_install") diff --git a/spec/unit/resource/gem_package_spec.rb b/spec/unit/resource/gem_package_spec.rb index 98703455de..01c4fb6106 100644 --- a/spec/unit/resource/gem_package_spec.rb +++ b/spec/unit/resource/gem_package_spec.rb @@ -17,24 +17,17 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::GemPackage, "initialize" do - before(:each) do - @resource = Chef::Resource::GemPackage.new("foo") - end - - it "should return a Chef::Resource::GemPackage" do - @resource.should be_a_kind_of(Chef::Resource::GemPackage) - end - - it "should set the resource_name to :gem_package" do - @resource.resource_name.should eql(:gem_package) - end + static_provider_resolution( + resource: Chef::Resource::GemPackage, + provider: Chef::Provider::Package::Rubygems, + name: :gem_package, + action: :install, + ) - it "should set the provider to Chef::Provider::Package::Rubygems" do - @resource.provider.should eql(Chef::Provider::Package::Rubygems) - end end describe Chef::Resource::GemPackage, "gem_binary" do diff --git a/spec/unit/resource/git_spec.rb b/spec/unit/resource/git_spec.rb index 95a30c28a4..da7aee1014 100644 --- a/spec/unit/resource/git_spec.rb +++ b/spec/unit/resource/git_spec.rb @@ -17,9 +17,17 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::Git do + static_provider_resolution( + resource: Chef::Resource::Git, + provider: Chef::Provider::Git, + name: :git, + action: :sync, + ) + before(:each) do @git = Chef::Resource::Git.new("my awesome webapp") end @@ -29,10 +37,6 @@ describe Chef::Resource::Git do @git.should be_an_instance_of(Chef::Resource::Git) end - it "uses the git provider" do - @git.provider.should eql(Chef::Provider::Git) - end - it "uses aliases revision as branch" do @git.branch "HEAD" @git.revision.should eql("HEAD") diff --git a/spec/unit/resource/homebrew_package_spec.rb b/spec/unit/resource/homebrew_package_spec.rb index bb657607b7..bb248d1189 100644 --- a/spec/unit/resource/homebrew_package_spec.rb +++ b/spec/unit/resource/homebrew_package_spec.rb @@ -16,26 +16,19 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::HomebrewPackage, 'initialize' do - let(:resource) { Chef::Resource::HomebrewPackage.new('emacs') } - - it 'returns a Chef::Resource::HomebrewPackage' do - expect(resource).to be_a_kind_of(Chef::Resource::HomebrewPackage) - end - - it 'sets the resource_name to :homebrew_package' do - expect(resource.resource_name).to eql(:homebrew_package) - end + static_provider_resolution( + resource: Chef::Resource::HomebrewPackage, + provider: Chef::Provider::Package::Homebrew, + name: :homebrew_package, + action: :install, + os: "mac_os_x", + ) - it 'sets the provider to Chef::Provider::Package::Homebrew' do - expect(resource.provider).to eql(Chef::Provider::Package::Homebrew) - end - - it 'sets the homebrew_user to nil' do - expect(resource.homebrew_user).to eql(nil) - end + let(:resource) { Chef::Resource::HomebrewPackage.new('emacs') } shared_examples 'home_brew user set and returned' do it 'returns the configured homebrew_user' do diff --git a/spec/unit/resource/ips_package_spec.rb b/spec/unit/resource/ips_package_spec.rb index 61661922fa..8718c5c093 100644 --- a/spec/unit/resource/ips_package_spec.rb +++ b/spec/unit/resource/ips_package_spec.rb @@ -17,25 +17,22 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::IpsPackage, "initialize" do + static_provider_resolution( + resource: Chef::Resource::IpsPackage, + provider: Chef::Provider::Package::Ips, + name: :ips_package, + action: :install, + os: "solaris2", + ) + before(:each) do @resource = Chef::Resource::IpsPackage.new("crypto/gnupg") end - it "should return a Chef::Resource::IpsPackage" do - @resource.should be_a_kind_of(Chef::Resource::IpsPackage) - end - - it "should set the resource_name to :ips_package" do - @resource.resource_name.should eql(:ips_package) - end - - it "should set the provider to Chef::Provider::Package::Ips" do - @resource.provider.should eql(Chef::Provider::Package::Ips) - end - it "should support accept_license" do @resource.accept_license(true) @resource.accept_license.should eql(true) diff --git a/spec/unit/resource/macports_package_spec.rb b/spec/unit/resource/macports_package_spec.rb index 7e2e200487..0a203b2e97 100644 --- a/spec/unit/resource/macports_package_spec.rb +++ b/spec/unit/resource/macports_package_spec.rb @@ -17,21 +17,16 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::MacportsPackage, "initialize" do - before(:each) do - @resource = Chef::Resource::MacportsPackage.new("foo") - end - it "should return a Chef::Resource::MacportsPackage" do - @resource.should be_a_kind_of(Chef::Resource::MacportsPackage) - end + static_provider_resolution( + resource: Chef::Resource::MacportsPackage, + provider: Chef::Provider::Package::Macports, + name: :macports_package, + action: :install, + os: "mac_os_x", + ) - it "should set the resource_name to :macports_package" do - @resource.resource_name.should eql(:macports_package) - end - - it "should set the provider to Chef::Provider::Package::Macports" do - @resource.provider.should eql(Chef::Provider::Package::Macports) - end end diff --git a/spec/unit/resource/pacman_package_spec.rb b/spec/unit/resource/pacman_package_spec.rb index ec5feeb82c..975863d04f 100644 --- a/spec/unit/resource/pacman_package_spec.rb +++ b/spec/unit/resource/pacman_package_spec.rb @@ -17,22 +17,16 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::PacmanPackage, "initialize" do - before(:each) do - @resource = Chef::Resource::PacmanPackage.new("foo") - end + static_provider_resolution( + resource: Chef::Resource::PacmanPackage, + provider: Chef::Provider::Package::Pacman, + name: :pacman_package, + action: :install, + os: "linux", + ) - it "should return a Chef::Resource::PacmanPackage" do - @resource.should be_a_kind_of(Chef::Resource::PacmanPackage) - end - - it "should set the resource_name to :pacman_package" do - @resource.resource_name.should eql(:pacman_package) - end - - it "should set the provider to Chef::Provider::Package::Pacman" do - @resource.provider.should eql(Chef::Provider::Package::Pacman) - end end diff --git a/spec/unit/resource/rpm_package_spec.rb b/spec/unit/resource/rpm_package_spec.rb index 25930a5484..d209c6a5a2 100644 --- a/spec/unit/resource/rpm_package_spec.rb +++ b/spec/unit/resource/rpm_package_spec.rb @@ -17,22 +17,18 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::RpmPackage, "initialize" do - before(:each) do - @resource = Chef::Resource::RpmPackage.new("foo") + %w{linux aix}.each do |os| + static_provider_resolution( + resource: Chef::Resource::RpmPackage, + provider: Chef::Provider::Package::Rpm, + name: :rpm_package, + action: :install, + os: os + ) end - it "should return a Chef::Resource::RpmPackage" do - @resource.should be_a_kind_of(Chef::Resource::RpmPackage) - end - - it "should set the resource_name to :rpm_package" do - @resource.resource_name.should eql(:rpm_package) - end - - it "should set the provider to Chef::Provider::Package::Rpm" do - @resource.provider.should eql(Chef::Provider::Package::Rpm) - end end diff --git a/spec/unit/resource/service_spec.rb b/spec/unit/resource/service_spec.rb index ec62d012bb..9b779e5830 100644 --- a/spec/unit/resource/service_spec.rb +++ b/spec/unit/resource/service_spec.rb @@ -29,20 +29,10 @@ describe Chef::Resource::Service do @resource.should be_a_kind_of(Chef::Resource) @resource.should be_a_kind_of(Chef::Resource::Service) end - + it "should not set a provider unless node[:init_package] is defined as systemd" do @resource.provider.should == nil end - - it "should set the provider to Chef::Provider::Service::Systemd if node[:init_package] is systemd" do - node = Chef::Node.new - node.set[:init_package] = "systemd" - cookbook_collection = Chef::CookbookCollection.new([]) - events = Chef::EventDispatch::Dispatcher.new - run_context = Chef::RunContext.new(node, cookbook_collection, events) - @resource = Chef::Resource::Service.new("chef", run_context) - @resource.provider.should == Chef::Provider::Service::Systemd - end it "should set the service_name to the first argument to new" do @resource.service_name.should eql("chef") diff --git a/spec/unit/resource/smartos_package_spec.rb b/spec/unit/resource/smartos_package_spec.rb index 391713c8ff..c2cf546dd5 100644 --- a/spec/unit/resource/smartos_package_spec.rb +++ b/spec/unit/resource/smartos_package_spec.rb @@ -16,23 +16,18 @@ # limitations under the License. # -require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper")) +require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::SmartosPackage, "initialize" do - before(:each) do - @resource = Chef::Resource::SmartosPackage.new("foo") - end + static_provider_resolution( + resource: Chef::Resource::SmartosPackage, + provider: Chef::Provider::Package::SmartOS, + name: :smartos_package, + action: :install, + os: "solaris2", + platform_family: "smartos", + ) - it "should return a Chef::Resource::SmartosPackage" do - @resource.should be_a_kind_of(Chef::Resource::SmartosPackage) - end - - it "should set the resource_name to :smartos_package" do - @resource.resource_name.should eql(:smartos_package) - end - - it "should set the provider to Chef::Provider::Package::SmartOS" do - @resource.provider.should eql(Chef::Provider::Package::SmartOS) - end end diff --git a/spec/unit/resource/solaris_package_spec.rb b/spec/unit/resource/solaris_package_spec.rb index 6d0260ab5a..ab4e03807d 100644 --- a/spec/unit/resource/solaris_package_spec.rb +++ b/spec/unit/resource/solaris_package_spec.rb @@ -17,41 +17,26 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::SolarisPackage, "initialize" do - before(:each) do - @resource = Chef::Resource::SolarisPackage.new("foo") - end - - it "should return a Chef::Resource::SolarisPackage object" do - @resource.should be_a_kind_of(Chef::Resource::SolarisPackage) + %w{solaris2 nexentacore}.each do |platform_family| + static_provider_resolution( + resource: Chef::Resource::SolarisPackage, + provider: Chef::Provider::Package::Solaris, + name: :solaris_package, + action: :install, + os: "solaris2", + platform_family: platform_family, + ) end - it "should not raise any Error when valid number of arguments are provided" do - expect { Chef::Resource::SolarisPackage.new("foo") }.to_not raise_error - end - - it "should raise ArgumentError when incorrect number of arguments are provided" do - expect { Chef::Resource::SolarisPackage.new }.to raise_error(ArgumentError) + before(:each) do + @resource = Chef::Resource::SolarisPackage.new("foo") end it "should set the package_name to the name provided" do @resource.package_name.should eql("foo") end - - it "should set the resource_name to :solaris_package" do - @resource.resource_name.should eql(:solaris_package) - end - - it "should set the run_context to the run_context provided" do - @run_context = double() - @run_context.stub(:node) - resource = Chef::Resource::SolarisPackage.new("foo", @run_context) - resource.run_context.should eql(@run_context) - end - - it "should set the provider to Chef::Provider::Package::Solaris" do - @resource.provider.should eql(Chef::Provider::Package::Solaris) - end end diff --git a/spec/unit/resource/subversion_spec.rb b/spec/unit/resource/subversion_spec.rb index ae06ce665a..a52d8421c6 100644 --- a/spec/unit/resource/subversion_spec.rb +++ b/spec/unit/resource/subversion_spec.rb @@ -17,9 +17,17 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::Subversion do + static_provider_resolution( + resource: Chef::Resource::Subversion, + provider: Chef::Provider::Subversion, + name: :subversion, + action: :install, + ) + before do @svn = Chef::Resource::Subversion.new("ohai, svn project!") end @@ -29,10 +37,6 @@ describe Chef::Resource::Subversion do @svn.should be_a_kind_of(Chef::Resource::Scm) end - it "uses the subversion provider" do - @svn.provider.should eql(Chef::Provider::Subversion) - end - it "allows the force_export action" do @svn.allowed_actions.should include(:force_export) end diff --git a/spec/unit/resource/timestamped_deploy_spec.rb b/spec/unit/resource/timestamped_deploy_spec.rb index f380ffca87..2af9d8bb0f 100644 --- a/spec/unit/resource/timestamped_deploy_spec.rb +++ b/spec/unit/resource/timestamped_deploy_spec.rb @@ -18,11 +18,37 @@ require 'spec_helper' -describe Chef::Resource::TimestampedDeploy do +describe Chef::Resource::TimestampedDeploy, "initialize" do - it "defaults to the TimestampedDeploy provider" do - @resource = Chef::Resource::TimestampedDeploy.new("stuff") - @resource.provider.should == Chef::Provider::Deploy::Timestamped + let(:node) { + node = Chef::Node.new + node.automatic_attrs[:os] = 'linux' + node.automatic_attrs[:platform_family] = 'rhel' + node + } + let(:events) { Chef::EventDispatch::Dispatcher.new } + let(:provider_resolver) { Chef::ProviderResolver.new(node) } + let(:run_context) { + run_context = Chef::RunContext.new(node, {}, events) + run_context.provider_resolver = provider_resolver + run_context + } + let(:resource) { Chef::Resource::TimestampedDeploy.new("stuff", run_context) } + + it "should return a Chef::Resource::TimestampedDeploy" do + expect(resource).to be_a_kind_of(Chef::Resource::TimestampedDeploy) + end + + it "should set the resource_name to :timestamped_deploy" do + expect(resource.resource_name).to eql(:deploy) end + it "should leave the provider nil" do + expect(resource.provider).to eql(nil) + end + + it "should resolve to a Chef::Provider::Deploy::Timestamped" do + expect(resource.provider_for_action(:install)).to be_a(Chef::Provider::Deploy::Timestamped) + end end + diff --git a/spec/unit/resource/yum_package_spec.rb b/spec/unit/resource/yum_package_spec.rb index 57ab4dfcd9..7e1979fdfd 100644 --- a/spec/unit/resource/yum_package_spec.rb +++ b/spec/unit/resource/yum_package_spec.rb @@ -17,24 +17,19 @@ # require 'spec_helper' +require 'support/shared/unit/resource/static_provider_resolution' describe Chef::Resource::YumPackage, "initialize" do - before(:each) do - @resource = Chef::Resource::YumPackage.new("foo") - end - - it "should return a Chef::Resource::YumPackage" do - @resource.should be_a_kind_of(Chef::Resource::YumPackage) - end - - it "should set the resource_name to :yum_package" do - @resource.resource_name.should eql(:yum_package) - end + static_provider_resolution( + resource: Chef::Resource::YumPackage, + provider: Chef::Provider::Package::Yum, + name: :yum_package, + action: :install, + os: 'linux', + platform_family: 'rhel', + ) - it "should set the provider to Chef::Provider::Package::Yum" do - @resource.provider.should eql(Chef::Provider::Package::Yum) - end end describe Chef::Resource::YumPackage, "arch" do diff --git a/spec/unit/resource_platform_map_spec.rb b/spec/unit/resource_platform_map_spec.rb deleted file mode 100644 index 99673d868f..0000000000 --- a/spec/unit/resource_platform_map_spec.rb +++ /dev/null @@ -1,164 +0,0 @@ -# -# Author:: Seth Chisamore () -# Copyright:: Copyright (c) 2011 Opscode, Inc. -# 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::Resource::PlatformMap do - - before(:each) do - @platform_map = Chef::Resource::PlatformMap.new({ - :windows => { - "6.1" => { - :file => "softiefile", - :else => "thing" - }, - :default => { - :file => Chef::Resource::File, - :ping => "pong", - :cat => "nice" - } - }, - :pop_tron => { - }, - :default => { - :soundwave => "lazerbeak", - :directory => Chef::Resource::Directory, - } - }) - end - - describe 'filtering the map' do - it "returns resources for platform and version" do - pmap = @platform_map.filter("Windows", "6.1") - pmap.should be_a_kind_of(Hash) - pmap[:file].should eql("softiefile") - end - - it "returns platform default resources if version does not exist" do - pmap = @platform_map.filter("windows", "1") - pmap.should be_a_kind_of(Hash) - pmap[:file].should eql(Chef::Resource::File) - end - - it "returns global default resources if none exist for plaform" do - pmap = @platform_map.filter("pop_tron", "1") - pmap.should be_a_kind_of(Hash) - pmap[:directory].should eql(Chef::Resource::Directory) - end - - it "returns global default resources if platform does not exist" do - pmap = @platform_map.filter("BeOS", "1") - pmap.should be_a_kind_of(Hash) - pmap[:soundwave].should eql("lazerbeak") - end - - it "returns a merged map of platform version and plaform default resources" do - pmap = @platform_map.filter("Windows", "6.1") - pmap[:file].should eql("softiefile") - pmap[:ping].should eql("pong") - end - - it "returns a merged map of platform specific version and global defaults" do - pmap = @platform_map.filter("Windows", "6.1") - pmap[:file].should eql("softiefile") - pmap[:soundwave].should eql("lazerbeak") - end - end - - describe 'finding a resource' do - it "returns a resource for a platform directly by short name" do - @platform_map.get(:file, "windows", "6.1").should eql("softiefile") - end - - it "returns a default resource if platform and version don't exist" do - @platform_map.get(:remote_file).should eql(Chef::Resource::RemoteFile) - end - - it "raises an exception if a resource cannot be found" do - lambda { @platform_map.get(:coffee, "windows", "6.1")}.should raise_error(NameError) - end - - it "returns a resource with a Chef::Resource object" do - kitty = Chef::Resource::Cat.new("loulou") - @platform_map.get(kitty, "windows", "6.1").should eql("nice") - end - end - - describe 'building the map' do - it "allows passing of a resource map at creation time" do - @new_map = Chef::Resource::PlatformMap.new({:the_dude => {:default => 'abides'}}) - @new_map.map[:the_dude][:default].should eql("abides") - end - - it "defaults to a resource map with :default key" do - @new_map = Chef::Resource::PlatformMap.new - @new_map.map.has_key?(:default) - end - - it "updates the resource map with a map" do - @platform_map.set( - :platform => :darwin, - :version => "9.2.2", - :short_name => :file, - :resource => "masterful" - ) - @platform_map.map[:darwin]["9.2.2"][:file].should eql("masterful") - - @platform_map.set( - :platform => :darwin, - :short_name => :file, - :resource => "masterful" - ) - @platform_map.map[:darwin][:default][:file].should eql("masterful") - - @platform_map.set( - :short_name => :file, - :resource => "masterful" - ) - @platform_map.map[:default][:file].should eql("masterful") - - @platform_map.set( - :platform => :hero, - :version => "9.2.2", - :short_name => :file, - :resource => "masterful" - ) - @platform_map.map[:hero]["9.2.2"][:file].should eql("masterful") - - @platform_map.set( - :short_name => :file, - :resource => "masterful" - ) - @platform_map.map[:default][:file].should eql("masterful") - - @platform_map.set( - :short_name => :file, - :resource => "masterful" - ) - @platform_map.map[:default][:file].should eql("masterful") - - @platform_map.set( - :platform => :neurosis, - :short_name => :package, - :resource => "masterful" - ) - @platform_map.map[:neurosis][:default][:package].should eql("masterful") - end - end - -end diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index 584ec8175c..2163cf181e 100644 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -692,24 +692,33 @@ describe Chef::Resource do describe "building the platform map" do + let(:klz) { Class.new(Chef::Resource) } + + before do + Chef::Resource::Klz = klz + end + + after do + Chef::Resource.send(:remove_const, :Klz) + end + it 'adds mappings for a single platform' do - klz = Class.new(Chef::Resource) - Chef::Resource.platform_map.should_receive(:set).with( - :platform => :autobots, :short_name => :dinobot, :resource => klz + expect(Chef::Resource.node_map).to receive(:set).with( + :dinobot, Chef::Resource::Klz, { platform: ['autobots'] } ) - klz.provides :dinobot, :on_platforms => ['autobots'] + klz.provides :dinobot, platform: ['autobots'] end it 'adds mappings for multiple platforms' do - klz = Class.new(Chef::Resource) - Chef::Resource.platform_map.should_receive(:set).twice - klz.provides :energy, :on_platforms => ['autobots','decepticons'] + expect(Chef::Resource.node_map).to receive(:set).with( + :energy, Chef::Resource::Klz, { platform: ['autobots', 'decepticons']} + ) + klz.provides :energy, platform: ['autobots', 'decepticons'] end it 'adds mappings for all platforms' do - klz = Class.new(Chef::Resource) - Chef::Resource.platform_map.should_receive(:set).with( - :short_name => :tape_deck, :resource => klz + expect(Chef::Resource.node_map).to receive(:set).with( + :tape_deck, Chef::Resource::Klz, {} ) klz.provides :tape_deck end @@ -717,28 +726,26 @@ describe Chef::Resource do end describe "lookups from the platform map" do + let(:klz1) { Class.new(Chef::Resource) } + let(:klz2) { Class.new(Chef::Resource) } before(:each) do + Chef::Resource::Klz1 = klz1 + Chef::Resource::Klz2 = klz2 @node = Chef::Node.new @node.name("bumblebee") @node.automatic[:platform] = "autobots" @node.automatic[:platform_version] = "6.1" - Object.const_set('Soundwave', Class.new(Chef::Resource)) - Object.const_set('Grimlock', Class.new(Chef::Resource){ provides :dinobot, :on_platforms => ['autobots'] }) + Object.const_set('Soundwave', klz1) + klz2.provides :dinobot, :on_platforms => ['autobots'] + Object.const_set('Grimlock', klz2) end after(:each) do Object.send(:remove_const, :Soundwave) Object.send(:remove_const, :Grimlock) - end - - describe "resource_for_platform" do - it 'return a resource by short_name and platform' do - Chef::Resource.resource_for_platform(:dinobot,'autobots','6.1').should eql(Grimlock) - end - it "returns a resource by short_name if nothing else matches" do - Chef::Resource.resource_for_node(:soundwave, @node).should eql(Soundwave) - end + Chef::Resource.send(:remove_const, :Klz1) + Chef::Resource.send(:remove_const, :Klz2) end describe "resource_for_node" do diff --git a/spec/unit/runner_spec.rb b/spec/unit/runner_spec.rb index 68d8b0e011..9bd4199418 100644 --- a/spec/unit/runner_spec.rb +++ b/spec/unit/runner_spec.rb @@ -81,322 +81,329 @@ end describe Chef::Runner do - before(:each) do - @node = Chef::Node.new - @node.name "latte" - @node.automatic[:platform] = "mac_os_x" - @node.automatic[:platform_version] = "10.5.1" - @events = Chef::EventDispatch::Dispatcher.new - @run_context = Chef::RunContext.new(@node, Chef::CookbookCollection.new({}), @events) - @first_resource = Chef::Resource::Cat.new("loulou1", @run_context) - @run_context.resource_collection << @first_resource - Chef::Platform.set( - :resource => :cat, - :provider => Chef::Provider::SnakeOil - ) - @runner = Chef::Runner.new(@run_context) + let(:node) do + node = Chef::Node.new + node.name "latte" + node.automatic[:platform] = "mac_os_x" + node.automatic[:platform_version] = "10.5.1" + node end - it "should pass each resource in the collection to a provider" do - @run_context.resource_collection.should_receive(:execute_each_resource).once - @runner.converge - end + let(:events) { Chef::EventDispatch::Dispatcher.new } + let(:run_context) { Chef::RunContext.new(node, Chef::CookbookCollection.new({}), events) } + let(:first_resource) { Chef::Resource::Cat.new("loulou1", run_context) } + let(:runner) { Chef::Runner.new(run_context) } - it "should use the provider specified by the resource (if it has one)" do - provider = Chef::Provider::Easy.new(@run_context.resource_collection[0], @run_context) - # Expect provider to be called twice, because will fall back to old provider lookup - @run_context.resource_collection[0].should_receive(:provider).twice.and_return(Chef::Provider::Easy) - Chef::Provider::Easy.should_receive(:new).once.and_return(provider) - @runner.converge + before do + run_context.resource_collection << first_resource end - it "should use the platform provider if it has one" do - Chef::Platform.should_receive(:find_provider_for_node).once.and_return(Chef::Provider::SnakeOil) - @runner.converge - end + context "when we fall through to old Chef::Platform resolution" do + before do + # set up old Chef::Platform resolution instead of provider_resolver + Chef::Platform.set( + :resource => :cat, + :provider => Chef::Provider::SnakeOil + ) + allow(run_context.provider_resolver).to receive(:maybe_dynamic_provider_resolution).with(first_resource, anything()).and_return(nil) + end - it "should run the action for each resource" do - Chef::Platform.should_receive(:find_provider_for_node).once.and_return(Chef::Provider::SnakeOil) - provider = Chef::Provider::SnakeOil.new(@run_context.resource_collection[0], @run_context) - provider.should_receive(:action_sell).once.and_return(true) - Chef::Provider::SnakeOil.should_receive(:new).once.and_return(provider) - @runner.converge + it "should use the platform provider if it has one" do + expect(Chef::Platform).to receive(:find_provider_for_node).with(node, first_resource).and_call_original + runner.converge + end end - it "should raise exceptions as thrown by a provider" do - provider = Chef::Provider::SnakeOil.new(@run_context.resource_collection[0], @run_context) - Chef::Provider::SnakeOil.stub(:new).once.and_return(provider) - provider.stub(:action_sell).once.and_raise(ArgumentError) - lambda { @runner.converge }.should raise_error(ArgumentError) - end + context "when we are doing dynamic provider resolution" do - it "should not raise exceptions thrown by providers if the resource has ignore_failure set to true" do - @run_context.resource_collection[0].stub(:ignore_failure).and_return(true) - provider = Chef::Provider::SnakeOil.new(@run_context.resource_collection[0], @run_context) - Chef::Provider::SnakeOil.stub(:new).once.and_return(provider) - provider.stub(:action_sell).once.and_raise(ArgumentError) - lambda { @runner.converge }.should_not raise_error - end + it "should pass each resource in the collection to a provider" do + expect(run_context.resource_collection).to receive(:execute_each_resource).once + runner.converge + end - it "should retry with the specified delay if retries are specified" do - @first_resource.retries 3 - provider = Chef::Provider::SnakeOil.new(@run_context.resource_collection[0], @run_context) - Chef::Provider::SnakeOil.stub(:new).once.and_return(provider) - provider.stub(:action_sell).and_raise(ArgumentError) - @first_resource.should_receive(:sleep).with(2).exactly(3).times - lambda { @runner.converge }.should raise_error(ArgumentError) - end + it "should use the provider specified by the resource (if it has one)" do + provider = Chef::Provider::Easy.new(run_context.resource_collection[0], run_context) + # Expect provider to be called twice, because will fall back to old provider lookup + expect(run_context.resource_collection[0]).to receive(:provider).twice.and_return(Chef::Provider::Easy) + expect(Chef::Provider::Easy).to receive(:new).once.and_return(provider) + runner.converge + end - it "should execute immediate actions on changed resources" do - notifying_resource = Chef::Resource::Cat.new("peanut", @run_context) - notifying_resource.action = :purr # only action that will set updated on the resource + it "should run the action for each resource" do + provider = Chef::Provider::SnakeOil.new(run_context.resource_collection[0], run_context) + expect(provider).to receive(:action_sell).once.and_return(true) + expect(Chef::Provider::SnakeOil).to receive(:new).once.and_return(provider) + runner.converge + end - @run_context.resource_collection << notifying_resource - @first_resource.action = :nothing # won't be updated unless notified by other resource + it "should raise exceptions as thrown by a provider" do + provider = Chef::Provider::SnakeOil.new(run_context.resource_collection[0], run_context) + allow(Chef::Provider::SnakeOil).to receive(:new).once.and_return(provider) + allow(provider).to receive(:action_sell).once.and_raise(ArgumentError) + expect { runner.converge }.to raise_error(ArgumentError) + end - notifying_resource.notifies(:purr, @first_resource, :immediately) + it "should not raise exceptions thrown by providers if the resource has ignore_failure set to true" do + allow(run_context.resource_collection[0]).to receive(:ignore_failure).and_return(true) + provider = Chef::Provider::SnakeOil.new(run_context.resource_collection[0], run_context) + allow(Chef::Provider::SnakeOil).to receive(:new).once.and_return(provider) + allow(provider).to receive(:action_sell).once.and_raise(ArgumentError) + expect { runner.converge }.not_to raise_error + end - @runner.converge + it "should retry with the specified delay if retries are specified" do + first_resource.retries 3 + provider = Chef::Provider::SnakeOil.new(run_context.resource_collection[0], run_context) + allow(Chef::Provider::SnakeOil).to receive(:new).once.and_return(provider) + allow(provider).to receive(:action_sell).and_raise(ArgumentError) + expect(first_resource).to receive(:sleep).with(2).exactly(3).times + expect { runner.converge }.to raise_error(ArgumentError) + end - @first_resource.should be_updated - end + it "should execute immediate actions on changed resources" do + notifying_resource = Chef::Resource::Cat.new("peanut", run_context) + notifying_resource.action = :purr # only action that will set updated on the resource - it "should follow a chain of actions" do - @first_resource.action = :nothing + run_context.resource_collection << notifying_resource + first_resource.action = :nothing # won't be updated unless notified by other resource - middle_resource = Chef::Resource::Cat.new("peanut", @run_context) - middle_resource.action = :nothing - @run_context.resource_collection << middle_resource - middle_resource.notifies(:purr, @first_resource, :immediately) + notifying_resource.notifies(:purr, first_resource, :immediately) - last_resource = Chef::Resource::Cat.new("snuffles", @run_context) - last_resource.action = :purr - @run_context.resource_collection << last_resource - last_resource.notifies(:purr, middle_resource, :immediately) + runner.converge - @runner.converge + expect(first_resource).to be_updated + end - last_resource.should be_updated # by action(:purr) - middle_resource.should be_updated # by notification from last_resource - @first_resource.should be_updated # by notification from middle_resource - end + it "should follow a chain of actions" do + first_resource.action = :nothing - it "should execute delayed actions on changed resources" do - @first_resource.action = :nothing - second_resource = Chef::Resource::Cat.new("peanut", @run_context) - second_resource.action = :purr + middle_resource = Chef::Resource::Cat.new("peanut", run_context) + middle_resource.action = :nothing + run_context.resource_collection << middle_resource + middle_resource.notifies(:purr, first_resource, :immediately) - @run_context.resource_collection << second_resource - second_resource.notifies(:purr, @first_resource, :delayed) + last_resource = Chef::Resource::Cat.new("snuffles", run_context) + last_resource.action = :purr + run_context.resource_collection << last_resource + last_resource.notifies(:purr, middle_resource, :immediately) - @runner.converge + runner.converge - @first_resource.should be_updated - end + expect(last_resource).to be_updated # by action(:purr) + expect(middle_resource).to be_updated # by notification from last_resource + expect(first_resource).to be_updated # by notification from middle_resource + end - it "should execute delayed notifications when a failure occurs in the chef client run" do - @first_resource.action = :nothing - second_resource = Chef::Resource::Cat.new("peanut", @run_context) - second_resource.action = :purr + it "should execute delayed actions on changed resources" do + first_resource.action = :nothing + second_resource = Chef::Resource::Cat.new("peanut", run_context) + second_resource.action = :purr - @run_context.resource_collection << second_resource - second_resource.notifies(:purr, @first_resource, :delayed) + run_context.resource_collection << second_resource + second_resource.notifies(:purr, first_resource, :delayed) - third_resource = FailureResource.new("explode", @run_context) - @run_context.resource_collection << third_resource + runner.converge - lambda {@runner.converge}.should raise_error(FailureProvider::ChefClientFail) + expect(first_resource).to be_updated + end - @first_resource.should be_updated - end + it "should execute delayed notifications when a failure occurs in the chef client run" do + first_resource.action = :nothing + second_resource = Chef::Resource::Cat.new("peanut", run_context) + second_resource.action = :purr - it "should execute delayed notifications when a failure occurs in a notification" do - @first_resource.action = :nothing - second_resource = Chef::Resource::Cat.new("peanut", @run_context) - second_resource.action = :purr + run_context.resource_collection << second_resource + second_resource.notifies(:purr, first_resource, :delayed) - @run_context.resource_collection << second_resource + third_resource = FailureResource.new("explode", run_context) + run_context.resource_collection << third_resource - third_resource = FailureResource.new("explode", @run_context) - third_resource.action = :nothing - @run_context.resource_collection << third_resource + expect { runner.converge }.to raise_error(FailureProvider::ChefClientFail) - second_resource.notifies(:fail, third_resource, :delayed) - second_resource.notifies(:purr, @first_resource, :delayed) + expect(first_resource).to be_updated + end - lambda {@runner.converge}.should raise_error(FailureProvider::ChefClientFail) + it "should execute delayed notifications when a failure occurs in a notification" do + first_resource.action = :nothing + second_resource = Chef::Resource::Cat.new("peanut", run_context) + second_resource.action = :purr - @first_resource.should be_updated - end + run_context.resource_collection << second_resource - it "should execute delayed notifications when a failure occurs in multiple notifications" do - @first_resource.action = :nothing - second_resource = Chef::Resource::Cat.new("peanut", @run_context) - second_resource.action = :purr + third_resource = FailureResource.new("explode", run_context) + third_resource.action = :nothing + run_context.resource_collection << third_resource - @run_context.resource_collection << second_resource + second_resource.notifies(:fail, third_resource, :delayed) + second_resource.notifies(:purr, first_resource, :delayed) - third_resource = FailureResource.new("explode", @run_context) - third_resource.action = :nothing - @run_context.resource_collection << third_resource + expect {runner.converge}.to raise_error(FailureProvider::ChefClientFail) - fourth_resource = FailureResource.new("explode again", @run_context) - fourth_resource.action = :nothing - @run_context.resource_collection << fourth_resource + expect(first_resource).to be_updated + end - second_resource.notifies(:fail, third_resource, :delayed) - second_resource.notifies(:fail, fourth_resource, :delayed) - second_resource.notifies(:purr, @first_resource, :delayed) + it "should execute delayed notifications when a failure occurs in multiple notifications" do + first_resource.action = :nothing + second_resource = Chef::Resource::Cat.new("peanut", run_context) + second_resource.action = :purr - exception = nil - begin - @runner.converge - rescue => e - exception = e - end - exception.should be_a(Chef::Exceptions::MultipleFailures) + run_context.resource_collection << second_resource + + third_resource = FailureResource.new("explode", run_context) + third_resource.action = :nothing + run_context.resource_collection << third_resource + + fourth_resource = FailureResource.new("explode again", run_context) + fourth_resource.action = :nothing + run_context.resource_collection << fourth_resource + + second_resource.notifies(:fail, third_resource, :delayed) + second_resource.notifies(:fail, fourth_resource, :delayed) + second_resource.notifies(:purr, first_resource, :delayed) + + exception = nil + begin + runner.converge + rescue => e + exception = e + end + expect(exception).to be_a(Chef::Exceptions::MultipleFailures) - expected_message =<<-E + expected_message =<<-E Multiple failures occurred: * FailureProvider::ChefClientFail occurred in delayed notification: [explode] (dynamically defined) had an error: FailureProvider::ChefClientFail: chef had an error of some sort * FailureProvider::ChefClientFail occurred in delayed notification: [explode again] (dynamically defined) had an error: FailureProvider::ChefClientFail: chef had an error of some sort -E - exception.message.should == expected_message + E + expect(exception.message).to eq(expected_message) - @first_resource.should be_updated - end - - it "does not duplicate delayed notifications" do - SnitchyProvider.clear_action_record - - Chef::Platform.set( - :resource => :cat, - :provider => SnitchyProvider - ) + expect(first_resource).to be_updated + end - @first_resource.action = :nothing + it "does not duplicate delayed notifications" do + SnitchyProvider.clear_action_record - second_resource = Chef::Resource::Cat.new("peanut", @run_context) - second_resource.action = :first_action - @run_context.resource_collection << second_resource + first_resource.action = :nothing + first_resource.provider = SnitchyProvider - third_resource = Chef::Resource::Cat.new("snickers", @run_context) - third_resource.action = :first_action - @run_context.resource_collection << third_resource + second_resource = Chef::Resource::Cat.new("peanut", run_context) + second_resource.action = :first_action + second_resource.provider = SnitchyProvider + run_context.resource_collection << second_resource - second_resource.notifies(:second_action, @first_resource, :delayed) - second_resource.notifies(:third_action, @first_resource, :delayed) + third_resource = Chef::Resource::Cat.new("snickers", run_context) + third_resource.action = :first_action + third_resource.provider = SnitchyProvider + run_context.resource_collection << third_resource - third_resource.notifies(:second_action, @first_resource, :delayed) - third_resource.notifies(:third_action, @first_resource, :delayed) + second_resource.notifies(:second_action, first_resource, :delayed) + second_resource.notifies(:third_action, first_resource, :delayed) - @runner.converge - # resources 2 and 3 call :first_action in the course of normal resource - # execution, and schedule delayed actions :second and :third on the first - # resource. The duplicate actions should "collapse" to a single notification - # and order should be preserved. - SnitchyProvider.all_actions_called.should == [:first, :first, :second, :third] - end + third_resource.notifies(:second_action, first_resource, :delayed) + third_resource.notifies(:third_action, first_resource, :delayed) - it "executes delayed notifications in the order they were declared" do - SnitchyProvider.clear_action_record + runner.converge + # resources 2 and 3 call :first_action in the course of normal resource + # execution, and schedule delayed actions :second and :third on the first + # resource. The duplicate actions should "collapse" to a single notification + # and order should be preserved. + expect(SnitchyProvider.all_actions_called).to eq([:first, :first, :second, :third]) + end - Chef::Platform.set( - :resource => :cat, - :provider => SnitchyProvider - ) + it "executes delayed notifications in the order they were declared" do + SnitchyProvider.clear_action_record - @first_resource.action = :nothing + first_resource.action = :nothing + first_resource.provider = SnitchyProvider - second_resource = Chef::Resource::Cat.new("peanut", @run_context) - second_resource.action = :first_action - @run_context.resource_collection << second_resource + second_resource = Chef::Resource::Cat.new("peanut", run_context) + second_resource.action = :first_action + second_resource.provider = SnitchyProvider + run_context.resource_collection << second_resource - third_resource = Chef::Resource::Cat.new("snickers", @run_context) - third_resource.action = :first_action - @run_context.resource_collection << third_resource + third_resource = Chef::Resource::Cat.new("snickers", run_context) + third_resource.action = :first_action + third_resource.provider = SnitchyProvider + run_context.resource_collection << third_resource - second_resource.notifies(:second_action, @first_resource, :delayed) - second_resource.notifies(:second_action, @first_resource, :delayed) + second_resource.notifies(:second_action, first_resource, :delayed) + second_resource.notifies(:second_action, first_resource, :delayed) - third_resource.notifies(:third_action, @first_resource, :delayed) - third_resource.notifies(:third_action, @first_resource, :delayed) + third_resource.notifies(:third_action, first_resource, :delayed) + third_resource.notifies(:third_action, first_resource, :delayed) - @runner.converge - SnitchyProvider.all_actions_called.should == [:first, :first, :second, :third] - end + runner.converge + expect(SnitchyProvider.all_actions_called).to eq([:first, :first, :second, :third]) + end - it "does not fire notifications if the resource was not updated by the last action executed" do - # REGRESSION TEST FOR CHEF-1452 - SnitchyProvider.clear_action_record + it "does not fire notifications if the resource was not updated by the last action executed" do + # REGRESSION TEST FOR CHEF-1452 + SnitchyProvider.clear_action_record - Chef::Platform.set( - :resource => :cat, - :provider => SnitchyProvider - ) + first_resource.action = :first_action + first_resource.provider = SnitchyProvider - @first_resource.action = :first_action + second_resource = Chef::Resource::Cat.new("peanut", run_context) + second_resource.action = :nothing + second_resource.provider = SnitchyProvider + run_context.resource_collection << second_resource - second_resource = Chef::Resource::Cat.new("peanut", @run_context) - second_resource.action = :nothing - @run_context.resource_collection << second_resource + third_resource = Chef::Resource::Cat.new("snickers", run_context) + third_resource.action = :nothing + third_resource.provider = SnitchyProvider + run_context.resource_collection << third_resource - third_resource = Chef::Resource::Cat.new("snickers", @run_context) - third_resource.action = :nothing - @run_context.resource_collection << third_resource + first_resource.notifies(:second_action, second_resource, :immediately) + second_resource.notifies(:third_action, third_resource, :immediately) - @first_resource.notifies(:second_action, second_resource, :immediately) - second_resource.notifies(:third_action, third_resource, :immediately) + runner.converge - @runner.converge + # All of the resources should only fire once: + expect(SnitchyProvider.all_actions_called).to eq([:first, :second, :third]) - # All of the resources should only fire once: - SnitchyProvider.all_actions_called.should == [:first, :second, :third] + # all of the resources should be marked as updated for reporting purposes + expect(first_resource).to be_updated + expect(second_resource).to be_updated + expect(third_resource).to be_updated + end - # all of the resources should be marked as updated for reporting purposes - @first_resource.should be_updated - second_resource.should be_updated - third_resource.should be_updated - end + it "should check a resource's only_if and not_if if notified by another resource" do + first_resource.action = :buy - it "should check a resource's only_if and not_if if notified by another resource" do - @first_resource.action = :buy + only_if_called_times = 0 + first_resource.only_if {only_if_called_times += 1; true} - only_if_called_times = 0 - @first_resource.only_if {only_if_called_times += 1; true} + not_if_called_times = 0 + first_resource.not_if {not_if_called_times += 1; false} - not_if_called_times = 0 - @first_resource.not_if {not_if_called_times += 1; false} + second_resource = Chef::Resource::Cat.new("carmel", run_context) + run_context.resource_collection << second_resource + second_resource.notifies(:purr, first_resource, :delayed) + second_resource.action = :purr - second_resource = Chef::Resource::Cat.new("carmel", @run_context) - @run_context.resource_collection << second_resource - second_resource.notifies(:purr, @first_resource, :delayed) - second_resource.action = :purr + # hits only_if first time when the resource is run in order, second on notify + runner.converge - # hits only_if first time when the resource is run in order, second on notify - @runner.converge + expect(only_if_called_times).to eq(2) + expect(not_if_called_times).to eq(2) + end - only_if_called_times.should == 2 - not_if_called_times.should == 2 - end + it "should resolve resource references in notifications when resources are defined lazily" do + first_resource.action = :nothing - it "should resolve resource references in notifications when resources are defined lazily" do - @first_resource.action = :nothing + lazy_resources = lambda { + last_resource = Chef::Resource::Cat.new("peanut", run_context) + run_context.resource_collection << last_resource + last_resource.notifies(:purr, first_resource.to_s, :delayed) + last_resource.action = :purr + } + second_resource = Chef::Resource::RubyBlock.new("myblock", run_context) + run_context.resource_collection << second_resource + second_resource.block { lazy_resources.call } - lazy_resources = lambda { - last_resource = Chef::Resource::Cat.new("peanut", @run_context) - @run_context.resource_collection << last_resource - last_resource.notifies(:purr, @first_resource.to_s, :delayed) - last_resource.action = :purr - } - second_resource = Chef::Resource::RubyBlock.new("myblock", @run_context) - @run_context.resource_collection << second_resource - second_resource.block { lazy_resources.call } + runner.converge - @runner.converge + expect(first_resource).to be_updated + end - @first_resource.should be_updated end - end - -- cgit v1.2.1