summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2014-10-23 16:13:39 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2014-10-23 16:13:39 -0700
commit561bc9f25280192f52b794ef177dc7b605c6b31d (patch)
treeb3271a50fe7efde09edf996474250a9eeda07ddf
parent5e47c9f4821f740ac2d4ff6dca30da4838b072c6 (diff)
downloadchef-561bc9f25280192f52b794ef177dc7b605c6b31d.tar.gz
replace replaces with the priority map
-rw-r--r--lib/chef/node_map.rb7
-rw-r--r--lib/chef/platform/provider_priority_map.rb86
-rw-r--r--lib/chef/provider.rb4
-rw-r--r--lib/chef/provider/service/debian.rb3
-rw-r--r--lib/chef/provider/service/freebsd.rb1
-rw-r--r--lib/chef/provider/service/insserv.rb4
-rw-r--r--lib/chef/provider/service/invokercd.rb2
-rw-r--r--lib/chef/provider/service/macosx.rb1
-rw-r--r--lib/chef/provider/service/redhat.rb1
-rw-r--r--lib/chef/provider/service/solaris.rb1
-rw-r--r--lib/chef/provider/service/systemd.rb8
-rw-r--r--lib/chef/provider/service/upstart.rb4
-rw-r--r--lib/chef/provider_resolver.rb38
-rw-r--r--spec/unit/node_map_spec.rb2
-rw-r--r--spec/unit/provider_resolver_spec.rb3
15 files changed, 123 insertions, 42 deletions
diff --git a/lib/chef/node_map.rb b/lib/chef/node_map.rb
index 20433c8e87..2ca6d9ba17 100644
--- a/lib/chef/node_map.rb
+++ b/lib/chef/node_map.rb
@@ -51,7 +51,10 @@ class Chef
validate_filter!(filters)
deprecate_filter!(filters)
@map[key] ||= []
- @map[key].push({ filters: filters, block: block, value: value })
+ # we match on the first value we find, so we want to unshift so that the
+ # last setter wins
+ # FIXME: need a test for this behavior
+ @map[key].unshift({ filters: filters, block: block, value: value })
self
end
@@ -63,6 +66,8 @@ class Chef
# @return [Object] Value
#
def get(node, key)
+ # FIXME: real exception
+ raise "first argument must be a Chef::Node" unless node.is_a?(Chef::Node)
return nil unless @map.has_key?(key)
@map[key].each do |matcher|
if filters_match?(node, matcher[:filters]) &&
diff --git a/lib/chef/platform/provider_priority_map.rb b/lib/chef/platform/provider_priority_map.rb
new file mode 100644
index 0000000000..3bd2bf558a
--- /dev/null
+++ b/lib/chef/platform/provider_priority_map.rb
@@ -0,0 +1,86 @@
+
+require 'chef/providers'
+
+class Chef
+ class Platform
+ class ProviderPriorityMap
+ include Singleton
+
+ def initialize
+ load_default_map
+ end
+
+ def load_default_map
+
+ #
+ # Linux
+ #
+
+ # default block for linux O/Sen must come before platform_family exceptions
+ priority :service, [
+ Chef::Provider::Service::Systemd,
+ Chef::Provider::Service::Insserv,
+ Chef::Provider::Service::Redhat,
+ ], os: "linux"
+
+ priority :service, [
+ Chef::Provider::Service::Systemd,
+ Chef::Provider::Service::Arch,
+ ], platform_family: "arch"
+
+ priority :service, [
+ Chef::Provider::Service::Systemd,
+ Chef::Provider::Service::Gentoo,
+ ], platform_family: "gentoo"
+
+ priority :service, [
+ # on debian-ish system if an upstart script exists that always wins
+ Chef::Provider::Service::Upstart,
+ Chef::Provider::Service::Systemd,
+ Chef::Provider::Service::Insserv,
+ Chef::Provider::Service::Debian,
+ Chef::Provider::Service::Invokercd,
+ ], platform_family: "debian"
+
+ priority :service, [
+ Chef::Provider::Service::Systemd,
+ Chef::Provider::Service::Insserv,
+ Chef::Provider::Service::Redhat,
+ ], platform_family: [ "rhel", "fedora", "suse" ]
+
+ #
+ # BSDen
+ #
+
+ priority :service, [
+ Chef::Provider::Service::Freebsd,
+ ], os: [ "freebsd", "netbsd" ]
+
+ #
+ # Solaris-en
+ #
+
+ priority :service, [
+ Chef::Provider::Service::Solaris,
+ ], os: "solaris2"
+
+ #
+ # Mac
+ #
+
+ priority :service, [
+ Chef::Provider::Service::Macosx,
+ ], os: "darwin"
+ end
+
+ def priority_map
+ @priority_map ||= Chef::NodeMap.new
+ end
+
+ def priority(*args)
+ priority_map.set(*args)
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/provider.rb b/lib/chef/provider.rb
index 45c37a35f7..d933164c8c 100644
--- a/lib/chef/provider.rb
+++ b/lib/chef/provider.rb
@@ -47,10 +47,6 @@ class Chef
node_map.set(resource_name.to_sym, true, opts, &block)
end
- def replaces(*classnames)
- self.replace_classes += classnames
- end
-
# provides a node on the resource (early binding)
def provides?(node, resource)
node_map.get(node, resource.resource_name)
diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb
index 4b53635a18..bf7c5efa49 100644
--- a/lib/chef/provider/service/debian.rb
+++ b/lib/chef/provider/service/debian.rb
@@ -27,9 +27,6 @@ class Chef
provides :service, platform_family: "debian"
- replaces Chef::Provider::Service::Init
- replaces Chef::Provider::Service::Invokercd
-
def self.handles?(resource, action)
Chef::Platform::ServiceHelpers.service_resource_providers.include?(:debian)
end
diff --git a/lib/chef/provider/service/freebsd.rb b/lib/chef/provider/service/freebsd.rb
index ec192124f3..e4a456ac25 100644
--- a/lib/chef/provider/service/freebsd.rb
+++ b/lib/chef/provider/service/freebsd.rb
@@ -28,7 +28,6 @@ class Chef
attr_reader :enabled_state_found
provides :service, os: [ "freebsd", "netbsd" ]
- replaces Chef::Provider::Service::Init
include Chef::Mixin::ShellOut
diff --git a/lib/chef/provider/service/insserv.rb b/lib/chef/provider/service/insserv.rb
index e14138d8a7..8f151d242f 100644
--- a/lib/chef/provider/service/insserv.rb
+++ b/lib/chef/provider/service/insserv.rb
@@ -25,10 +25,6 @@ class Chef
class Insserv < Chef::Provider::Service::Init
provides :service, os: "linux"
- replaces Chef::Provider::Service::Init
- replaces Chef::Provider::Service::Debian
- replaces Chef::Provider::Service::Invokercd
- replaces Chef::Provider::Service::Redhat
def self.handles?(resource, action)
Chef::Platform::ServiceHelpers.service_resource_providers.include?(:insserv)
diff --git a/lib/chef/provider/service/invokercd.rb b/lib/chef/provider/service/invokercd.rb
index 91da13df43..bbf0861a68 100644
--- a/lib/chef/provider/service/invokercd.rb
+++ b/lib/chef/provider/service/invokercd.rb
@@ -25,8 +25,6 @@ class Chef
provides :service, platform_family: "debian"
- replaces Chef::Provider::Service::Init
-
def self.handles?(resource, action)
Chef::Platform::ServiceHelpers.service_resource_providers.include?(:invokerc)
end
diff --git a/lib/chef/provider/service/macosx.rb b/lib/chef/provider/service/macosx.rb
index 959e166253..10ad1aa29d 100644
--- a/lib/chef/provider/service/macosx.rb
+++ b/lib/chef/provider/service/macosx.rb
@@ -27,7 +27,6 @@ class Chef
class Macosx < Chef::Provider::Service::Simple
provides :service, os: "darwin"
- replaces Chef::Provider::Service::Init
def self.gather_plist_dirs
locations = %w{/Library/LaunchAgents
diff --git a/lib/chef/provider/service/redhat.rb b/lib/chef/provider/service/redhat.rb
index 15208c0778..87e8d903cf 100644
--- a/lib/chef/provider/service/redhat.rb
+++ b/lib/chef/provider/service/redhat.rb
@@ -27,7 +27,6 @@ class Chef
CHKCONFIG_MISSING = /No such/
provides :service, platform_family: [ "rhel", "fedora", "suse" ]
- replaces Chef::Provider::Service::Init
def self.handles?(resource, action)
Chef::Platform::ServiceHelpers.service_resource_providers.include?(:redhat)
diff --git a/lib/chef/provider/service/solaris.rb b/lib/chef/provider/service/solaris.rb
index 5658e0ceba..eaea6bb1ab 100644
--- a/lib/chef/provider/service/solaris.rb
+++ b/lib/chef/provider/service/solaris.rb
@@ -27,7 +27,6 @@ class Chef
attr_reader :maintenance
provides :service, os: "solaris2"
- replaces Chef::Provider::Service::Init
def initialize(new_resource, run_context=nil)
super
diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb
index 731321daf3..35a364d3f7 100644
--- a/lib/chef/provider/service/systemd.rb
+++ b/lib/chef/provider/service/systemd.rb
@@ -22,14 +22,6 @@ require 'chef/provider/service/simple'
class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
provides :service, os: "linux"
- # We welcome our new systemd masters
- replaces Chef::Provider::Service::Init
- replaces Chef::Provider::Service::Debian
- replaces Chef::Provider::Service::Redhat
- replaces Chef::Provider::Service::Invokercd
- replaces Chef::Provider::Service::Insserv
- replaces Chef::Provider::Service::Arch
- replaces Chef::Provider::Service::Gentoo
def self.handles?(resource, action)
Chef::Platform::ServiceHelpers.service_resource_providers.include?(:systemd)
diff --git a/lib/chef/provider/service/upstart.rb b/lib/chef/provider/service/upstart.rb
index 2b367d91a0..513a1630d3 100644
--- a/lib/chef/provider/service/upstart.rb
+++ b/lib/chef/provider/service/upstart.rb
@@ -28,10 +28,6 @@ class Chef
UPSTART_STATE_FORMAT = /\w+ \(?(\w+)\)?[\/ ](\w+)/
provides :service, os: "linux"
- replaces Chef::Provider::Service::Init
- replaces Chef::Provider::Service::Debian
- replaces Chef::Provider::Service::Insserv
- replaces Chef::Provider::Service::Invokercd
def self.handles?(resource, action)
Chef::Platform::ServiceHelpers.service_resource_providers.include?(:upstart) &&
diff --git a/lib/chef/provider_resolver.rb b/lib/chef/provider_resolver.rb
index 5ffd8da900..c0a537624e 100644
--- a/lib/chef/provider_resolver.rb
+++ b/lib/chef/provider_resolver.rb
@@ -17,6 +17,7 @@
#
require 'chef/exceptions'
+require 'chef/platform/provider_priority_map'
class Chef
class ProviderResolver
@@ -48,25 +49,33 @@ class Chef
# try dynamically finding a provider based on querying the providers to see what they support
def maybe_dynamic_provider_resolution(resource, action)
- handlers = providers.select do |klass|
+ # this cut only depends on the node value and is going to be static for all nodes
+ # will contain all providers that could possibly support a resource on a node
+ enabled_handlers = providers.select do |klass|
klass.provides?(node, resource)
end
- # log this so we know what providers will work for the generic resource on the node
- Chef::Log.debug "providers for generic #{resource.resource_name} resource enabled on node include: #{handlers}"
+ # log this so we know what providers will work for the generic resource on the node (early cut)
+ Chef::Log.debug "providers for generic #{resource.resource_name} resource enabled on node include: #{enabled_handlers}"
- handlers.select! do |klass|
+ # ask all the enabled providers if they can actually support the resource
+ supported_handlers = enabled_handlers.select do |klass|
klass.handles?(resource, action)
end
- # log this separately from above so we know what providers were excluded by config
- Chef::Log.debug "providers that support resource #{resource} include: #{handlers}"
+ # what providers were excluded by machine state (late cut)
+ Chef::Log.debug "providers that refused resource #{resource} were: #{enabled_handlers - supported_handlers}"
+ Chef::Log.debug "providers that support resource #{resource} include: #{supported_handlers}"
- # classes can declare that they replace other classes, gather them all
- replacements = handlers.map { |klass| klass.replaces }.flatten
+ handlers = supported_handlers.empty? ? enabled_handlers : supported_handlers
- # reject all the classes that have been replaced
- handlers -= replacements
+ if handlers.count >= 2
+ priority_list = [ get_provider_priority_map(resource.resource_name, node) ].flatten.compact
+
+ handlers = handlers.sort_by { |x| i = priority_list.index x; i.nil? ? Float::INFINITY : i }
+
+ handlers = [ handlers.first ]
+ end
Chef::Log.debug "providers that survived replacement include: #{handlers}"
@@ -81,5 +90,14 @@ class Chef
def maybe_chef_platform_lookup(resource)
Chef::Platform.find_provider_for_node(node, resource)
end
+
+ # dep injection hooks
+ def get_provider_priority_map(resource_name, node)
+ provider_priority_map.get(node, resource_name)
+ end
+
+ def provider_priority_map
+ Chef::Platform::ProviderPriorityMap.instance.priority_map
+ end
end
end
diff --git a/spec/unit/node_map_spec.rb b/spec/unit/node_map_spec.rb
index 90160ec096..fe7372961b 100644
--- a/spec/unit/node_map_spec.rb
+++ b/spec/unit/node_map_spec.rb
@@ -23,7 +23,7 @@ describe Chef::NodeMap do
let(:node_map) { Chef::NodeMap.new }
- let(:node) { double(Chef::Node) }
+ let(:node) { Chef::Node.new }
describe "with a bad filter name" do
it "should raise an error" do
diff --git a/spec/unit/provider_resolver_spec.rb b/spec/unit/provider_resolver_spec.rb
index 78dcdbd0ea..927cca4f58 100644
--- a/spec/unit/provider_resolver_spec.rb
+++ b/spec/unit/provider_resolver_spec.rb
@@ -24,11 +24,12 @@ include Chef::Mixin::ConvertToClassName
describe Chef::ProviderResolver do
let(:node) do
- node = double(Chef::Node)
+ 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