diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2014-10-24 10:45:43 -0700 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2014-10-24 10:45:43 -0700 |
commit | 97aaf5bbcdfd0810722b123bdc67e883a7ca8077 (patch) | |
tree | 25663bf1d4f53664b96844251091b51273ad84c7 /spec/unit/provider_resolver_spec.rb | |
parent | cb1bcb1f08816f551f96e713624718f58da3c9b3 (diff) | |
download | chef-97aaf5bbcdfd0810722b123bdc67e883a7ca8077.tar.gz |
Chef-12 RC Provider Resolver
makes resource and provider class resolution more dynamic.
begins deprecation of Chef::Platform static mapping.
Diffstat (limited to 'spec/unit/provider_resolver_spec.rb')
-rw-r--r-- | spec/unit/provider_resolver_spec.rb | 384 |
1 files changed, 340 insertions, 44 deletions
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 (<liseki@nyikacraftsmen.com>) -# Copyright:: Copyright (c) 2014 Richard Manyanza. +# Author:: Lamont Granquist (<lamont@getchef.com>) +# 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 |