summaryrefslogtreecommitdiff
path: root/spec/unit/provider_resolver_spec.rb
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2014-10-24 10:45:43 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2014-10-24 10:45:43 -0700
commit97aaf5bbcdfd0810722b123bdc67e883a7ca8077 (patch)
tree25663bf1d4f53664b96844251091b51273ad84c7 /spec/unit/provider_resolver_spec.rb
parentcb1bcb1f08816f551f96e713624718f58da3c9b3 (diff)
downloadchef-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.rb384
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