summaryrefslogtreecommitdiff
path: root/lib
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 /lib
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 'lib')
-rw-r--r--lib/chef/dsl/recipe.rb1
-rw-r--r--lib/chef/exceptions.rb13
-rw-r--r--lib/chef/json_compat.rb2
-rw-r--r--lib/chef/mixin/convert_to_class_name.rb54
-rw-r--r--lib/chef/mixin/descendants_tracker.rb82
-rw-r--r--lib/chef/node_map.rb146
-rw-r--r--lib/chef/platform/provider_mapping.rb35
-rw-r--r--lib/chef/platform/provider_priority_map.rb80
-rw-r--r--lib/chef/platform/service_helpers.rb113
-rw-r--r--lib/chef/provider.rb50
-rw-r--r--lib/chef/provider/breakpoint.rb2
-rw-r--r--lib/chef/provider/cookbook_file.rb2
-rw-r--r--lib/chef/provider/deploy/revision.rb2
-rw-r--r--lib/chef/provider/deploy/timestamped.rb2
-rw-r--r--lib/chef/provider/directory.rb2
-rw-r--r--lib/chef/provider/dsc_script.rb3
-rw-r--r--lib/chef/provider/erl_call.rb2
-rw-r--r--lib/chef/provider/execute.rb2
-rw-r--r--lib/chef/provider/file.rb2
-rw-r--r--lib/chef/provider/git.rb2
-rw-r--r--lib/chef/provider/group/pw.rb3
-rw-r--r--lib/chef/provider/http_request.rb2
-rw-r--r--lib/chef/provider/link.rb2
-rw-r--r--lib/chef/provider/log.rb2
-rw-r--r--lib/chef/provider/package/aix.rb2
-rw-r--r--lib/chef/provider/package/apt.rb2
-rw-r--r--lib/chef/provider/package/dpkg.rb2
-rw-r--r--lib/chef/provider/package/easy_install.rb2
-rw-r--r--lib/chef/provider/package/freebsd.rb154
-rw-r--r--lib/chef/provider/package/homebrew.rb4
-rw-r--r--lib/chef/provider/package/ips.rb2
-rw-r--r--lib/chef/provider/package/macports.rb3
-rw-r--r--lib/chef/provider/package/pacman.rb2
-rw-r--r--lib/chef/provider/package/paludis.rb4
-rw-r--r--lib/chef/provider/package/rpm.rb2
-rw-r--r--lib/chef/provider/package/rubygems.rb3
-rw-r--r--lib/chef/provider/package/smartos.rb2
-rw-r--r--lib/chef/provider/package/solaris.rb2
-rw-r--r--lib/chef/provider/package/yum.rb2
-rw-r--r--lib/chef/provider/remote_directory.rb4
-rw-r--r--lib/chef/provider/route.rb2
-rw-r--r--lib/chef/provider/ruby_block.rb2
-rw-r--r--lib/chef/provider/script.rb6
-rw-r--r--lib/chef/provider/service/arch.rb6
-rw-r--r--lib/chef/provider/service/debian.rb64
-rw-r--r--lib/chef/provider/service/freebsd.rb5
-rw-r--r--lib/chef/provider/service/gentoo.rb3
-rw-r--r--lib/chef/provider/service/init.rb2
-rw-r--r--lib/chef/provider/service/insserv.rb22
-rw-r--r--lib/chef/provider/service/invokercd.rb6
-rw-r--r--lib/chef/provider/service/macosx.rb2
-rw-r--r--lib/chef/provider/service/redhat.rb12
-rw-r--r--lib/chef/provider/service/simple.rb2
-rw-r--r--lib/chef/provider/service/solaris.rb2
-rw-r--r--lib/chef/provider/service/systemd.rb7
-rw-r--r--lib/chef/provider/service/upstart.rb7
-rw-r--r--lib/chef/provider/service/windows.rb4
-rw-r--r--lib/chef/provider/subversion.rb2
-rw-r--r--lib/chef/provider/template.rb1
-rw-r--r--lib/chef/provider/user/pw.rb3
-rw-r--r--lib/chef/provider/whyrun_safe_ruby_block.rb2
-rw-r--r--lib/chef/provider_resolver.rb82
-rw-r--r--lib/chef/providers.rb4
-rw-r--r--lib/chef/resource.rb107
-rw-r--r--lib/chef/resource/apt_package.rb4
-rw-r--r--lib/chef/resource/bash.rb1
-rw-r--r--lib/chef/resource/bff_package.rb1
-rw-r--r--lib/chef/resource/breakpoint.rb2
-rw-r--r--lib/chef/resource/chef_gem.rb3
-rw-r--r--lib/chef/resource/cookbook_file.rb3
-rw-r--r--lib/chef/resource/csh.rb1
-rw-r--r--lib/chef/resource/deploy.rb1
-rw-r--r--lib/chef/resource/deploy_revision.rb7
-rw-r--r--lib/chef/resource/directory.rb3
-rw-r--r--lib/chef/resource/dpkg_package.rb3
-rw-r--r--lib/chef/resource/dsc_script.rb3
-rw-r--r--lib/chef/resource/easy_install_package.rb3
-rw-r--r--lib/chef/resource/erl_call.rb1
-rw-r--r--lib/chef/resource/execute.rb1
-rw-r--r--lib/chef/resource/file.rb4
-rw-r--r--lib/chef/resource/freebsd_package.rb2
-rw-r--r--lib/chef/resource/gem_package.rb3
-rw-r--r--lib/chef/resource/git.rb3
-rw-r--r--lib/chef/resource/homebrew_package.rb3
-rw-r--r--lib/chef/resource/http_request.rb1
-rw-r--r--lib/chef/resource/ips_package.rb4
-rw-r--r--lib/chef/resource/link.rb3
-rw-r--r--lib/chef/resource/log.rb4
-rw-r--r--lib/chef/resource/macports_package.rb4
-rw-r--r--lib/chef/resource/pacman_package.rb3
-rw-r--r--lib/chef/resource/paludis_package.rb4
-rw-r--r--lib/chef/resource/perl.rb1
-rw-r--r--lib/chef/resource/python.rb2
-rw-r--r--lib/chef/resource/remote_directory.rb3
-rw-r--r--lib/chef/resource/remote_file.rb2
-rw-r--r--lib/chef/resource/rpm_package.rb3
-rw-r--r--lib/chef/resource/ruby.rb1
-rw-r--r--lib/chef/resource/ruby_block.rb3
-rw-r--r--lib/chef/resource/script.rb1
-rw-r--r--lib/chef/resource/service.rb4
-rw-r--r--lib/chef/resource/smartos_package.rb7
-rw-r--r--lib/chef/resource/solaris_package.rb8
-rw-r--r--lib/chef/resource/subversion.rb1
-rw-r--r--lib/chef/resource/template.rb3
-rw-r--r--lib/chef/resource/timestamped_deploy.rb3
-rw-r--r--lib/chef/resource/whyrun_safe_ruby_block.rb1
-rw-r--r--lib/chef/resource/windows_package.rb4
-rw-r--r--lib/chef/resource/windows_service.rb3
-rw-r--r--lib/chef/resource/yum_package.rb4
-rw-r--r--lib/chef/resource_platform_map.rb151
-rw-r--r--lib/chef/run_context.rb4
-rw-r--r--lib/chef/runner.rb5
112 files changed, 863 insertions, 579 deletions
diff --git a/lib/chef/dsl/recipe.rb b/lib/chef/dsl/recipe.rb
index 94b0d2d18b..120497d56e 100644
--- a/lib/chef/dsl/recipe.rb
+++ b/lib/chef/dsl/recipe.rb
@@ -17,7 +17,6 @@
# limitations under the License.
#
-require 'chef/resource_platform_map'
require 'chef/mixin/convert_to_class_name'
require 'chef/exceptions'
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb
index 67429ac5a2..25f08455fc 100644
--- a/lib/chef/exceptions.rb
+++ b/lib/chef/exceptions.rb
@@ -91,7 +91,11 @@ class Chef
class ResourceNotFound < RuntimeError; end
# Can't find a Resource of this type that is valid on this platform.
- class NoSuchResourceType < NameError; end
+ class NoSuchResourceType < NameError
+ def initialize(short_name, node)
+ super "Cannot find a resource for #{short_name} on #{node[:platform]} version #{node[:platform_version]}"
+ end
+ end
class InvalidResourceSpecification < ArgumentError; end
class SolrConnectionError < RuntimeError; end
@@ -355,5 +359,12 @@ class Chef
end
class InvalidSearchQuery < ArgumentError; end
+
+ # Raised by Chef::ProviderResolver
+ class AmbiguousProviderResolution < RuntimeError
+ def initialize(resource, classes)
+ super "Found more than one provider for #{resource.resource_name} resource: #{classes}"
+ end
+ end
end
end
diff --git a/lib/chef/json_compat.rb b/lib/chef/json_compat.rb
index 0796984ab2..d0b3b4c7f8 100644
--- a/lib/chef/json_compat.rb
+++ b/lib/chef/json_compat.rb
@@ -152,7 +152,7 @@ class Chef
when CHEF_RESOURCELIST
Chef::ResourceCollection::ResourceList
when /^Chef::Resource/
- Chef::Resource.find_subclass_by_name(json_class)
+ Chef::Resource.find_descendants_by_name(json_class)
else
raise Chef::Exceptions::JSON::ParseError, "Unsupported `json_class` type '#{json_class}'"
end
diff --git a/lib/chef/mixin/convert_to_class_name.rb b/lib/chef/mixin/convert_to_class_name.rb
index f849b8de6a..19f229fdd3 100644
--- a/lib/chef/mixin/convert_to_class_name.rb
+++ b/lib/chef/mixin/convert_to_class_name.rb
@@ -61,6 +61,60 @@ class Chef
base.to_s + (file_base == 'default' ? '' : "_#{file_base}")
end
+ # Copied from rails activesupport. In ruby >= 2.0 const_get will just do this, so this can
+ # be deprecated and removed.
+ #
+ # MIT LICENSE is here: https://github.com/rails/rails/blob/master/activesupport/MIT-LICENSE
+
+ # Tries to find a constant with the name specified in the argument string.
+ #
+ # 'Module'.constantize # => Module
+ # 'Test::Unit'.constantize # => Test::Unit
+ #
+ # The name is assumed to be the one of a top-level constant, no matter
+ # whether it starts with "::" or not. No lexical context is taken into
+ # account:
+ #
+ # C = 'outside'
+ # module M
+ # C = 'inside'
+ # C # => 'inside'
+ # 'C'.constantize # => 'outside', same as ::C
+ # end
+ #
+ # NameError is raised when the name is not in CamelCase or the constant is
+ # unknown.
+ def constantize(camel_cased_word)
+ names = camel_cased_word.split('::')
+
+ # Trigger a built-in NameError exception including the ill-formed constant in the message.
+ Object.const_get(camel_cased_word) if names.empty?
+
+ # Remove the first blank element in case of '::ClassName' notation.
+ names.shift if names.size > 1 && names.first.empty?
+
+ names.inject(Object) do |constant, name|
+ if constant == Object
+ constant.const_get(name)
+ else
+ candidate = constant.const_get(name)
+ next candidate if constant.const_defined?(name, false)
+ next candidate unless Object.const_defined?(name)
+
+ # Go down the ancestors to check if it is owned directly. The check
+ # stops when we reach Object or the end of ancestors tree.
+ constant = constant.ancestors.inject do |const, ancestor|
+ break const if ancestor == Object
+ break ancestor if ancestor.const_defined?(name, false)
+ const
+ end
+
+ # owner is in Object, so raise
+ constant.const_get(name, false)
+ end
+ end
+ end
+
end
end
end
diff --git a/lib/chef/mixin/descendants_tracker.rb b/lib/chef/mixin/descendants_tracker.rb
new file mode 100644
index 0000000000..75d1f620d4
--- /dev/null
+++ b/lib/chef/mixin/descendants_tracker.rb
@@ -0,0 +1,82 @@
+#
+# Copyright (c) 2005-2012 David Heinemeier Hansson
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+
+# This is lifted from rails activesupport (note the copyright above):
+# https://github.com/rails/rails/blob/9f84e60ac9d7bf07d6ae1bc94f3941f5b8f1a228/activesupport/lib/active_support/descendants_tracker.rb
+
+class Chef
+ module Mixin
+ module DescendantsTracker
+ @@direct_descendants = {}
+
+ class << self
+ def direct_descendants(klass)
+ @@direct_descendants[klass] || []
+ end
+
+ def descendants(klass)
+ arr = []
+ accumulate_descendants(klass, arr)
+ arr
+ end
+
+ def find_descendants_by_name(klass, name)
+ descendants(klass).first {|c| c.name == name }
+ end
+
+ # This is the only method that is not thread safe, but is only ever called
+ # during the eager loading phase.
+ def store_inherited(klass, descendant)
+ (@@direct_descendants[klass] ||= []) << descendant
+ end
+
+ private
+
+ def accumulate_descendants(klass, acc)
+ if direct_descendants = @@direct_descendants[klass]
+ acc.concat(direct_descendants)
+ direct_descendants.each { |direct_descendant| accumulate_descendants(direct_descendant, acc) }
+ end
+ end
+ end
+
+ def inherited(base)
+ DescendantsTracker.store_inherited(self, base)
+ super
+ end
+
+ def direct_descendants
+ DescendantsTracker.direct_descendants(self)
+ end
+
+ def find_descendants_by_name(name)
+ DescendantsTracker.find_descendants_by_name(self, name)
+ end
+
+ def descendants
+ DescendantsTracker.descendants(self)
+ end
+ end
+ end
+end
diff --git a/lib/chef/node_map.rb b/lib/chef/node_map.rb
new file mode 100644
index 0000000000..2ca6d9ba17
--- /dev/null
+++ b/lib/chef/node_map.rb
@@ -0,0 +1,146 @@
+#
+# Author:: Lamont Granquist (<lamont@chef.io>)
+# 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.
+#
+
+class Chef
+ class NodeMap
+
+ VALID_OPTS = [
+ :on_platform,
+ :on_platforms,
+ :platform,
+ :os,
+ :platform_family,
+ ]
+
+ DEPRECATED_OPTS = [
+ :on_platform,
+ :on_platforms,
+ ]
+
+ # Create a new NodeMap
+ #
+ def initialize
+ @map = {}
+ end
+
+ # Set a key/value pair on the map with a filter. The filter must be true
+ # when applied to the node in order to retrieve the value.
+ #
+ # @param key [Object] Key to store
+ # @param value [Object] Value associated with the key
+ # @param filters [Hash] Node filter options to apply to key retrieval
+ # @yield [node] Arbitrary node filter as a block which takes a node argument
+ # @return [NodeMap] Returns self for possible chaining
+ #
+ def set(key, value, filters = {}, &block)
+ validate_filter!(filters)
+ deprecate_filter!(filters)
+ @map[key] ||= []
+ # 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
+
+ # Get a value from the NodeMap via applying the node to the filters that
+ # were set on the key.
+ #
+ # @param node [Chef::Node] The Chef::Node object for the run
+ # @param key [Object] Key to look up
+ # @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]) &&
+ block_matches?(node, matcher[:block])
+ return matcher[:value]
+ end
+ end
+ nil
+ end
+
+ private
+
+ # only allow valid filter options
+ def validate_filter!(filters)
+ filters.each_key do |key|
+ # FIXME: real exception
+ raise "Bad key #{key} in Chef::NodeMap filter expression" unless VALID_OPTS.include?(key)
+ end
+ end
+
+ # warn on deprecated filter options
+ def deprecate_filter!(filters)
+ filters.each_key do |key|
+ Chef::Log.warn "The #{key} option to node_map has been deprecated" if DEPRECATED_OPTS.include?(key)
+ end
+ end
+
+ # @todo: this works fine, but is probably hard to understand
+ def negative_match(filter, param)
+ # We support strings prefaced by '!' to mean 'not'. In particular, this is most useful
+ # for os matching on '!windows'.
+ negative_matches = filter.select { |f| f[0] == '!' }
+ return true if !negative_matches.empty? && negative_matches.include?('!' + param)
+
+ # We support the symbol :all to match everything, for backcompat, but this can and should
+ # simply be ommitted.
+ positive_matches = filter.reject { |f| f[0] == '!' || f == :all }
+ return true if !positive_matches.empty? && !positive_matches.include?(param)
+
+ # sorry double-negative: this means we pass this filter.
+ false
+ end
+
+ def filters_match?(node, filters)
+ return true if filters.empty?
+
+ # each filter is applied in turn. if any fail, then it shortcuts and returns false.
+ # if it passes or does not exist it succeeds and continues on. so multiple filters are
+ # effectively joined by 'and'. all filters can be single strings, or arrays which are
+ # effectively joined by 'or'.
+
+ os_filter = [ filters[:os] ].flatten.compact
+ unless os_filter.empty?
+ return false if negative_match(os_filter, node[:os])
+ end
+
+ platform_family_filter = [ filters[:platform_family] ].flatten.compact
+ unless platform_family_filter.empty?
+ return false if negative_match(platform_family_filter, node[:platform_family])
+ end
+
+ # :on_platform and :on_platforms here are synonyms which are deprecated
+ platform_filter = [ filters[:platform] || filters[:on_platform] || filters[:on_platforms] ].flatten.compact
+ unless platform_filter.empty?
+ return false if negative_match(platform_filter, node[:platform])
+ end
+
+ return true
+ end
+
+ def block_matches?(node, block)
+ return true if block.nil?
+ block.call node
+ end
+ end
+end
diff --git a/lib/chef/platform/provider_mapping.rb b/lib/chef/platform/provider_mapping.rb
index e6d948276c..382df342f5 100644
--- a/lib/chef/platform/provider_mapping.rb
+++ b/lib/chef/platform/provider_mapping.rb
@@ -41,7 +41,6 @@ class Chef
:mac_os_x => {
:default => {
:package => Chef::Provider::Package::Homebrew,
- :service => Chef::Provider::Service::Macosx,
:user => Chef::Provider::User::Dscl,
:group => Chef::Provider::Group::Dscl
}
@@ -49,7 +48,6 @@ class Chef
:mac_os_x_server => {
:default => {
:package => Chef::Provider::Package::Homebrew,
- :service => Chef::Provider::Service::Macosx,
:user => Chef::Provider::User::Dscl,
:group => Chef::Provider::Group::Dscl
}
@@ -57,7 +55,6 @@ class Chef
:freebsd => {
:default => {
:group => Chef::Provider::Group::Pw,
- :service => Chef::Provider::Service::Freebsd,
:user => Chef::Provider::User::Pw,
:cron => Chef::Provider::Cron
}
@@ -203,7 +200,7 @@ class Chef
:group => Chef::Provider::Group::Gpasswd
},
"< 12.0" => {
- :group => Chef::Provider::Group::Suse,
+ :group => Chef::Provider::Group::Suse,
:service => Chef::Provider::Service::Redhat
}
},
@@ -276,7 +273,6 @@ class Chef
:mswin => {
:default => {
:env => Chef::Provider::Env::Windows,
- :service => Chef::Provider::Service::Windows,
:user => Chef::Provider::User::Windows,
:group => Chef::Provider::Group::Windows,
:mount => Chef::Provider::Mount::Windows,
@@ -287,7 +283,6 @@ class Chef
:mingw32 => {
:default => {
:env => Chef::Provider::Env::Windows,
- :service => Chef::Provider::Service::Windows,
:user => Chef::Provider::User::Windows,
:group => Chef::Provider::Group::Windows,
:mount => Chef::Provider::Mount::Windows,
@@ -298,7 +293,6 @@ class Chef
:windows => {
:default => {
:env => Chef::Provider::Env::Windows,
- :service => Chef::Provider::Service::Windows,
:user => Chef::Provider::User::Windows,
:group => Chef::Provider::Group::Windows,
:mount => Chef::Provider::Mount::Windows,
@@ -310,7 +304,6 @@ class Chef
:openindiana => {
:default => {
:mount => Chef::Provider::Mount::Solaris,
- :service => Chef::Provider::Service::Solaris,
:package => Chef::Provider::Package::Ips,
:cron => Chef::Provider::Cron::Solaris,
:group => Chef::Provider::Group::Usermod
@@ -319,7 +312,6 @@ class Chef
:opensolaris => {
:default => {
:mount => Chef::Provider::Mount::Solaris,
- :service => Chef::Provider::Service::Solaris,
:package => Chef::Provider::Package::Ips,
:cron => Chef::Provider::Cron::Solaris,
:group => Chef::Provider::Group::Usermod
@@ -328,7 +320,6 @@ class Chef
:nexentacore => {
:default => {
:mount => Chef::Provider::Mount::Solaris,
- :service => Chef::Provider::Service::Solaris,
:package => Chef::Provider::Package::Solaris,
:cron => Chef::Provider::Cron::Solaris,
:group => Chef::Provider::Group::Usermod
@@ -337,7 +328,6 @@ class Chef
:omnios => {
:default => {
:mount => Chef::Provider::Mount::Solaris,
- :service => Chef::Provider::Service::Solaris,
:package => Chef::Provider::Package::Ips,
:cron => Chef::Provider::Cron::Solaris,
:group => Chef::Provider::Group::Usermod,
@@ -347,7 +337,6 @@ class Chef
:solaris2 => {
:default => {
:mount => Chef::Provider::Mount::Solaris,
- :service => Chef::Provider::Service::Solaris,
:package => Chef::Provider::Package::Ips,
:cron => Chef::Provider::Cron::Solaris,
:group => Chef::Provider::Group::Usermod,
@@ -355,7 +344,6 @@ class Chef
},
"< 5.11" => {
:mount => Chef::Provider::Mount::Solaris,
- :service => Chef::Provider::Service::Solaris,
:package => Chef::Provider::Package::Solaris,
:cron => Chef::Provider::Cron::Solaris,
:group => Chef::Provider::Group::Usermod,
@@ -365,7 +353,6 @@ class Chef
:smartos => {
:default => {
:mount => Chef::Provider::Mount::Solaris,
- :service => Chef::Provider::Service::Solaris,
:package => Chef::Provider::Package::SmartOS,
:cron => Chef::Provider::Cron::Solaris,
:group => Chef::Provider::Group::Usermod
@@ -373,7 +360,6 @@ class Chef
},
:netbsd => {
:default => {
- :service => Chef::Provider::Service::Freebsd,
:group => Chef::Provider::Group::Groupmod
}
},
@@ -407,29 +393,10 @@ class Chef
}
},
:default => {
- :file => Chef::Provider::File,
- :directory => Chef::Provider::Directory,
- :link => Chef::Provider::Link,
- :template => Chef::Provider::Template,
- :remote_directory => Chef::Provider::RemoteDirectory,
- :execute => Chef::Provider::Execute,
:mount => Chef::Provider::Mount::Mount,
- :script => Chef::Provider::Script,
- :service => Chef::Provider::Service::Init,
- :perl => Chef::Provider::Script,
- :python => Chef::Provider::Script,
- :ruby => Chef::Provider::Script,
- :bash => Chef::Provider::Script,
- :csh => Chef::Provider::Script,
:user => Chef::Provider::User::Useradd,
:group => Chef::Provider::Group::Gpasswd,
- :http_request => Chef::Provider::HttpRequest,
- :route => Chef::Provider::Route,
:ifconfig => Chef::Provider::Ifconfig,
- :ruby_block => Chef::Provider::RubyBlock,
- :whyrun_safe_ruby_block => Chef::Provider::WhyrunSafeRubyBlock,
- :erl_call => Chef::Provider::ErlCall,
- :log => Chef::Provider::Log::ChefLog
}
}
end
diff --git a/lib/chef/platform/provider_priority_map.rb b/lib/chef/platform/provider_priority_map.rb
new file mode 100644
index 0000000000..ccf6ef0bbe
--- /dev/null
+++ b/lib/chef/platform/provider_priority_map.rb
@@ -0,0 +1,80 @@
+
+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/platform/service_helpers.rb b/lib/chef/platform/service_helpers.rb
new file mode 100644
index 0000000000..440391843e
--- /dev/null
+++ b/lib/chef/platform/service_helpers.rb
@@ -0,0 +1,113 @@
+#
+# Author:: Lamont Granquist (<lamont@chef.io>)
+# 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.
+#
+
+# XXX: mixing shellout into a mixin into classes has to be code smell
+require 'chef/mixin/shell_out'
+
+class Chef
+ class Platform
+ class ServiceHelpers
+ class << self
+
+ include Chef::Mixin::ShellOut
+
+ # This helper is mostly used to sort out the mess of different
+ # linux mechanisms that can be used to start services. It does
+ # not necessarily need to linux-specific, but currently all our
+ # other service providers are narrowly platform-specific with no
+ # alternatives.
+ def service_resource_providers
+ service_resource_providers = []
+
+ if ::File.exist?("/usr/sbin/update-rc.d")
+ service_resource_providers << :debian
+ end
+
+ if ::File.exist?("/usr/sbin/invoke-rc.d")
+ service_resource_providers << :invokercd
+ end
+
+ if ::File.exist?("/sbin/insserv")
+ service_resource_providers << :insserv
+ end
+
+ # debian >= 6.0 has /etc/init but does not have upstart
+ if ::File.exist?("/etc/init") && ::File.exist?("/sbin/start")
+ service_resource_providers << :upstart
+ end
+
+ if ::File.exist?("/sbin/chkconfig")
+ service_resource_providers << :redhat
+ end
+
+ if ::File.exist?("/bin/systemctl")
+ # FIXME: look for systemd as init provider
+ service_resource_providers << :systemd
+ end
+
+ service_resource_providers
+ end
+
+ def config_for_service(service_name)
+ configs = []
+
+ if ::File.exist?("/etc/init.d/#{service_name}")
+ configs << :initd
+ end
+
+ if ::File.exist?("/etc/init/#{service_name}.conf")
+ configs << :upstart
+ end
+
+ if ::File.exist?("/etc/xinetd.d/#{service_name}")
+ configs << :xinetd
+ end
+
+ if ::File.exist?("/etc/rc.d/#{service_name}")
+ configs << :etc_rcd
+ end
+
+ if ::File.exist?("/usr/local/etc/rc.d/#{service_name}")
+ configs << :usr_local_etc_rcd
+ end
+
+ if ::File.exist?("/bin/systemctl") && platform_has_systemd_unit?(service_name)
+ configs << :systemd
+ end
+
+ configs
+ end
+
+ private
+
+ def extract_systemd_services(output)
+ # first line finds e.g. "sshd.service"
+ services = output.lines.split.map { |l| l.split[0] }
+ # this splits off the suffix after the last dot to return "sshd"
+ services += services.map { |s| s.sub(/(.*)\..*/, '\1') }
+ end
+
+ def platform_has_systemd_unit?(service_name)
+ services = extract_systemd_services(shell_out!("systemctl --all").stdout) +
+ extract_systemd_services(shell_out!("systemctl --list-unit-files").stdout)
+ services.include?(service_name)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/provider.rb b/lib/chef/provider.rb
index 7cfdf7cbe5..680fe9782f 100644
--- a/lib/chef/provider.rb
+++ b/lib/chef/provider.rb
@@ -22,60 +22,36 @@ require 'chef/mixin/convert_to_class_name'
require 'chef/mixin/enforce_ownership_and_permissions'
require 'chef/mixin/why_run'
require 'chef/mixin/shell_out'
+require 'chef/mixin/descendants_tracker'
+require 'chef/platform/service_helpers'
+require 'chef/node_map'
class Chef
class Provider
include Chef::Mixin::WhyRun
include Chef::Mixin::ShellOut
-
+ extend Chef::Mixin::DescendantsTracker
class << self
- include Enumerable
-
- @@providers = []
-
- attr_reader :implementations
- attr_reader :supported_platforms
-
- def inherited(klass)
- @@providers << klass
+ def node_map
+ @node_map ||= Chef::NodeMap.new
end
- def providers
- @@providers
+ def provides(resource_name, opts={}, &block)
+ node_map.set(resource_name.to_sym, true, opts, &block)
end
- def each
- providers.each { |provider| yield provider }
- providers
- end
-
- def implements(*resources)
- options = resources.last.is_a?(Hash) ? resources.pop : {}
-
- @implementations = resources.map { |resource| resource.to_sym }
- @supported_platforms = Array(options[:on_platforms] || :all)
+ # provides a node on the resource (early binding)
+ def provides?(node, resource)
+ node_map.get(node, resource.resource_name)
end
- def implements?(resource)
- klass_name = resource.class.to_s.split('::').last
- resource_name = klass_name.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase
-
- implementations && implementations.include?(resource_name.to_sym)
- end
-
- def supports_platform?(platform)
- supported_platforms && (
- supported_platforms.include?(:all) ||
- supported_platforms.include?(platform.to_sym))
- end
-
- def enabled?(node)
+ # supports the given resource and action (late binding)
+ def supports?(resource, action)
true
end
end
-
attr_accessor :new_resource
attr_accessor :current_resource
attr_accessor :run_context
diff --git a/lib/chef/provider/breakpoint.rb b/lib/chef/provider/breakpoint.rb
index 224e2758eb..663d558f66 100644
--- a/lib/chef/provider/breakpoint.rb
+++ b/lib/chef/provider/breakpoint.rb
@@ -20,6 +20,8 @@ class Chef
class Provider
class Breakpoint < Chef::Provider
+ provides :breakpoint
+
def load_current_resource
end
diff --git a/lib/chef/provider/cookbook_file.rb b/lib/chef/provider/cookbook_file.rb
index 26d6ebf1d9..b501a9b41d 100644
--- a/lib/chef/provider/cookbook_file.rb
+++ b/lib/chef/provider/cookbook_file.rb
@@ -24,6 +24,8 @@ class Chef
class Provider
class CookbookFile < Chef::Provider::File
+ provides :cookbook_file
+
extend Chef::Deprecation::Warnings
include Chef::Deprecation::Provider::CookbookFile
add_deprecation_warnings_for(Chef::Deprecation::Provider::CookbookFile.instance_methods)
diff --git a/lib/chef/provider/deploy/revision.rb b/lib/chef/provider/deploy/revision.rb
index c98c1e5c75..62aa0e87f6 100644
--- a/lib/chef/provider/deploy/revision.rb
+++ b/lib/chef/provider/deploy/revision.rb
@@ -27,6 +27,8 @@ class Chef
class Provider
class Deploy
class Revision < Chef::Provider::Deploy
+ provides :deploy_revision
+ provides :deploy_branch
def all_releases
sorted_releases
diff --git a/lib/chef/provider/deploy/timestamped.rb b/lib/chef/provider/deploy/timestamped.rb
index ce921161e0..ba3f6683f0 100644
--- a/lib/chef/provider/deploy/timestamped.rb
+++ b/lib/chef/provider/deploy/timestamped.rb
@@ -20,6 +20,8 @@ class Chef
class Provider
class Deploy
class Timestamped < Chef::Provider::Deploy
+ provides :timestamped_deploy
+ provides :deploy
protected
diff --git a/lib/chef/provider/directory.rb b/lib/chef/provider/directory.rb
index 067737b9d4..c9c3d466b9 100644
--- a/lib/chef/provider/directory.rb
+++ b/lib/chef/provider/directory.rb
@@ -27,6 +27,8 @@ class Chef
class Provider
class Directory < Chef::Provider::File
+ provides :directory
+
def whyrun_supported?
true
end
diff --git a/lib/chef/provider/dsc_script.rb b/lib/chef/provider/dsc_script.rb
index a70f4b5048..5db50e74b3 100644
--- a/lib/chef/provider/dsc_script.rb
+++ b/lib/chef/provider/dsc_script.rb
@@ -24,6 +24,9 @@ require 'chef/util/path_helper'
class Chef
class Provider
class DscScript < Chef::Provider
+
+ provides :dsc_script, os: "windows"
+
def initialize(dsc_resource, run_context)
super(dsc_resource, run_context)
@dsc_resource = dsc_resource
diff --git a/lib/chef/provider/erl_call.rb b/lib/chef/provider/erl_call.rb
index cdd494a243..f5855bcce6 100644
--- a/lib/chef/provider/erl_call.rb
+++ b/lib/chef/provider/erl_call.rb
@@ -25,6 +25,8 @@ class Chef
class ErlCall < Chef::Provider
include Chef::Mixin::Command
+ provides :erl_call
+
def initialize(node, new_resource)
super(node, new_resource)
end
diff --git a/lib/chef/provider/execute.rb b/lib/chef/provider/execute.rb
index 54632c0684..48b2a344d1 100644
--- a/lib/chef/provider/execute.rb
+++ b/lib/chef/provider/execute.rb
@@ -23,6 +23,8 @@ class Chef
class Provider
class Execute < Chef::Provider
+ provides :execute
+
def load_current_resource
true
end
diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb
index 256248f240..a9390cc45c 100644
--- a/lib/chef/provider/file.rb
+++ b/lib/chef/provider/file.rb
@@ -54,6 +54,8 @@ class Chef
include Chef::Deprecation::Provider::File
add_deprecation_warnings_for(Chef::Deprecation::Provider::File.instance_methods)
+ provides :file
+
attr_reader :deployment_strategy
attr_accessor :needs_creating
diff --git a/lib/chef/provider/git.rb b/lib/chef/provider/git.rb
index 2ef119e839..8418f22933 100644
--- a/lib/chef/provider/git.rb
+++ b/lib/chef/provider/git.rb
@@ -25,6 +25,8 @@ class Chef
class Provider
class Git < Chef::Provider
+ provides :git
+
def whyrun_supported?
true
end
diff --git a/lib/chef/provider/group/pw.rb b/lib/chef/provider/group/pw.rb
index 79a4160807..c39c20da67 100644
--- a/lib/chef/provider/group/pw.rb
+++ b/lib/chef/provider/group/pw.rb
@@ -21,9 +21,6 @@ class Chef
class Group
class Pw < Chef::Provider::Group
- implements :group,
- :on_platforms => :freebsd
-
def load_current_resource
super
end
diff --git a/lib/chef/provider/http_request.rb b/lib/chef/provider/http_request.rb
index ba54b10195..61aff434ed 100644
--- a/lib/chef/provider/http_request.rb
+++ b/lib/chef/provider/http_request.rb
@@ -23,6 +23,8 @@ class Chef
class Provider
class HttpRequest < Chef::Provider
+ provides :http_request
+
attr_accessor :http
def whyrun_supported?
diff --git a/lib/chef/provider/link.rb b/lib/chef/provider/link.rb
index 639dc4f3ff..417d6a21b0 100644
--- a/lib/chef/provider/link.rb
+++ b/lib/chef/provider/link.rb
@@ -28,6 +28,8 @@ class Chef
class Provider
class Link < Chef::Provider
+ provides :link
+
include Chef::Mixin::EnforceOwnershipAndPermissions
include Chef::Mixin::FileClass
diff --git a/lib/chef/provider/log.rb b/lib/chef/provider/log.rb
index 9379ceeefa..40eaf0aa28 100644
--- a/lib/chef/provider/log.rb
+++ b/lib/chef/provider/log.rb
@@ -25,6 +25,8 @@ class Chef
# Chef log provider, allows logging to chef's logs from recipes
class ChefLog < Chef::Provider
+ provides :log
+
def whyrun_supported?
true
end
diff --git a/lib/chef/provider/package/aix.rb b/lib/chef/provider/package/aix.rb
index da3e6d1684..88de4679ba 100644
--- a/lib/chef/provider/package/aix.rb
+++ b/lib/chef/provider/package/aix.rb
@@ -26,6 +26,8 @@ class Chef
class Package
class Aix < Chef::Provider::Package
+ provides :bff_package, os: "aix"
+
include Chef::Mixin::GetSourceFromPackage
def define_resource_requirements
diff --git a/lib/chef/provider/package/apt.rb b/lib/chef/provider/package/apt.rb
index 0d91d0d1f0..eb2c038eaa 100644
--- a/lib/chef/provider/package/apt.rb
+++ b/lib/chef/provider/package/apt.rb
@@ -25,6 +25,8 @@ class Chef
class Package
class Apt < Chef::Provider::Package
+ provides :apt_package, os: "linux"
+
attr_accessor :is_virtual_package
def load_current_resource
diff --git a/lib/chef/provider/package/dpkg.rb b/lib/chef/provider/package/dpkg.rb
index a1f1c797b1..3a9cecc660 100644
--- a/lib/chef/provider/package/dpkg.rb
+++ b/lib/chef/provider/package/dpkg.rb
@@ -30,6 +30,8 @@ class Chef
DPKG_INSTALLED = /^Status: install ok installed/
DPKG_VERSION = /^Version: (.+)$/
+ provides :dpkg_package, os: "linux"
+
include Chef::Mixin::GetSourceFromPackage
def define_resource_requirements
diff --git a/lib/chef/provider/package/easy_install.rb b/lib/chef/provider/package/easy_install.rb
index 2af8a72e61..90727b738d 100644
--- a/lib/chef/provider/package/easy_install.rb
+++ b/lib/chef/provider/package/easy_install.rb
@@ -25,6 +25,8 @@ class Chef
class Package
class EasyInstall < Chef::Provider::Package
+ provides :easy_install_package
+
def install_check(name)
check = false
diff --git a/lib/chef/provider/package/freebsd.rb b/lib/chef/provider/package/freebsd.rb
deleted file mode 100644
index f5ec0cec47..0000000000
--- a/lib/chef/provider/package/freebsd.rb
+++ /dev/null
@@ -1,154 +0,0 @@
-#
-# Authors:: Bryan McLellan (btm@loftninjas.org)
-# Matthew Landauer (matthew@openaustralia.org)
-# Copyright:: Copyright (c) 2009 Bryan McLellan, Matthew Landauer
-# 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 'chef/provider/package'
-require 'chef/mixin/shell_out'
-require 'chef/resource/package'
-require 'chef/mixin/get_source_from_package'
-
-class Chef
- class Provider
- class Package
- class Freebsd < Chef::Provider::Package
- include Chef::Mixin::ShellOut
-
- include Chef::Mixin::GetSourceFromPackage
-
- implements :package,
- :freebsd_package,
- :on_platforms => :freebsd
-
-
- def initialize(*args)
- super
- @current_resource = Chef::Resource::Package.new(@new_resource.name)
- end
-
- def current_installed_version
- pkg_info = shell_out!("pkg_info -E \"#{package_name}*\"", :env => nil, :returns => [0,1])
- pkg_info.stdout[/^#{Regexp.escape(package_name)}-(.+)/, 1]
- end
-
- def port_path
- case @new_resource.package_name
- # When the package name starts with a '/' treat it as the full path to the ports directory
- when /^\//
- @new_resource.package_name
- # Otherwise if the package name contains a '/' not at the start (like 'www/wordpress') treat as a relative
- # path from /usr/ports
- when /\//
- "/usr/ports/#{@new_resource.package_name}"
- # Otherwise look up the path to the ports directory using 'whereis'
- else
- whereis = shell_out!("whereis -s #{@new_resource.package_name}", :env => nil)
- unless path = whereis.stdout[/^#{Regexp.escape(@new_resource.package_name)}:\s+(.+)$/, 1]
- raise Chef::Exceptions::Package, "Could not find port with the name #{@new_resource.package_name}"
- end
- path
- end
- end
-
- def ports_makefile_variable_value(variable)
- make_v = shell_out!("make -V #{variable}", :cwd => port_path, :env => nil, :returns => [0,1])
- make_v.stdout.strip.split($\).first # $\ is the line separator, i.e., newline
- end
-
- def ports_candidate_version
- ports_makefile_variable_value("PORTVERSION")
- end
-
- def file_candidate_version_path
- Dir["#{@new_resource.source}/#{@current_resource.package_name}*"][-1].to_s
- end
-
- def file_candidate_version
- file_candidate_version_path.split(/-/).last.split(/.tbz/).first
- end
-
- def load_current_resource
- @current_resource.package_name(@new_resource.package_name)
-
- @current_resource.version(current_installed_version)
- Chef::Log.debug("#{@new_resource} current version is #{@current_resource.version}") if @current_resource.version
-
- case @new_resource.source
- when /^http/, /^ftp/
- @candidate_version = "0.0.0"
- when /^\//
- @candidate_version = file_candidate_version
- else
- @candidate_version = ports_candidate_version
- end
-
- Chef::Log.debug("#{@new_resource} ports candidate version is #{@candidate_version}") if @candidate_version
-
- @current_resource
- end
-
- def latest_link_name
- ports_makefile_variable_value("LATEST_LINK")
- end
-
- # The name of the package (without the version number) as understood by pkg_add and pkg_info
- def package_name
- if ::File.exist?("/usr/ports/Makefile")
- if ports_makefile_variable_value("PKGNAME") =~ /^(.+)-[^-]+$/
- $1
- else
- raise Chef::Exceptions::Package, "Unexpected form for PKGNAME variable in #{port_path}/Makefile"
- end
- else
- @new_resource.package_name
- end
- end
-
- def install_package(name, version)
- unless @current_resource.version
- case @new_resource.source
- when /^ports$/
- shell_out!("make -DBATCH install", :timeout => 1200, :env => nil, :cwd => port_path).status
- when /^http/, /^ftp/
- if @new_resource.source =~ /\/$/
- shell_out!("pkg_add -r #{package_name}", :env => { "PACKAGESITE" => @new_resource.source, 'LC_ALL' => nil }).status
- else
- shell_out!("pkg_add -r #{package_name}", :env => { "PACKAGEROOT" => @new_resource.source, 'LC_ALL' => nil }).status
- end
- Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
- when /^\//
- shell_out!("pkg_add #{file_candidate_version_path}", :env => { "PKG_PATH" => @new_resource.source , 'LC_ALL'=>nil}).status
- Chef::Log.debug("#{@new_resource} installed from: #{@new_resource.source}")
- else
- shell_out!("pkg_add -r #{latest_link_name}", :env => nil).status
- end
- end
- end
-
- def remove_package(name, version)
- # a version is mandatory
- if version
- shell_out!("pkg_delete #{package_name}-#{version}", :env => nil).status
- else
- shell_out!("pkg_delete #{package_name}-#{@current_resource.version}", :env => nil).status
- end
- end
-
- end
- end
- end
-end
diff --git a/lib/chef/provider/package/homebrew.rb b/lib/chef/provider/package/homebrew.rb
index a9aeea1415..822f4c8a42 100644
--- a/lib/chef/provider/package/homebrew.rb
+++ b/lib/chef/provider/package/homebrew.rb
@@ -25,7 +25,11 @@ class Chef
class Provider
class Package
class Homebrew < Chef::Provider::Package
+
+ provides :homebrew_package, os: "mac_os_x"
+
include Chef::Mixin::HomebrewUser
+
def load_current_resource
self.current_resource = Chef::Resource::Package.new(new_resource.name)
current_resource.package_name(new_resource.package_name)
diff --git a/lib/chef/provider/package/ips.rb b/lib/chef/provider/package/ips.rb
index 4090507303..87022d770a 100644
--- a/lib/chef/provider/package/ips.rb
+++ b/lib/chef/provider/package/ips.rb
@@ -27,6 +27,8 @@ class Chef
class Package
class Ips < Chef::Provider::Package
+ provides :ips_package, os: "solaris2"
+
attr_accessor :virtual
def define_resource_requirements
diff --git a/lib/chef/provider/package/macports.rb b/lib/chef/provider/package/macports.rb
index 05247e6d31..cd142eca42 100644
--- a/lib/chef/provider/package/macports.rb
+++ b/lib/chef/provider/package/macports.rb
@@ -2,6 +2,9 @@ class Chef
class Provider
class Package
class Macports < Chef::Provider::Package
+
+ provides :macports_package, os: "mac_os_x"
+
def load_current_resource
@current_resource = Chef::Resource::Package.new(@new_resource.name)
@current_resource.package_name(@new_resource.package_name)
diff --git a/lib/chef/provider/package/pacman.rb b/lib/chef/provider/package/pacman.rb
index a9ff0edf7f..85c0208d76 100644
--- a/lib/chef/provider/package/pacman.rb
+++ b/lib/chef/provider/package/pacman.rb
@@ -25,6 +25,8 @@ class Chef
class Package
class Pacman < Chef::Provider::Package
+ provides :pacman_package, os: "linux"
+
def load_current_resource
@current_resource = Chef::Resource::Package.new(@new_resource.name)
@current_resource.package_name(@new_resource.package_name)
diff --git a/lib/chef/provider/package/paludis.rb b/lib/chef/provider/package/paludis.rb
index f363b38e50..407e0d0110 100644
--- a/lib/chef/provider/package/paludis.rb
+++ b/lib/chef/provider/package/paludis.rb
@@ -24,6 +24,8 @@ class Chef
class Package
class Paludis < Chef::Provider::Package
+ provides :paludis_package, os: "linux"
+
def load_current_resource
@current_resource = Chef::Resource::Package.new(@new_resource.package_name)
@current_resource.package_name(@new_resource.package_name)
@@ -45,7 +47,7 @@ class Chef
@current_resource.version(res[2])
else
@candidate_version = res[2]
- @current_resource.version(nil)
+ @current_resource.version(nil)
end
end
end
diff --git a/lib/chef/provider/package/rpm.rb b/lib/chef/provider/package/rpm.rb
index c0a6444252..131587e066 100644
--- a/lib/chef/provider/package/rpm.rb
+++ b/lib/chef/provider/package/rpm.rb
@@ -25,6 +25,8 @@ class Chef
class Package
class Rpm < Chef::Provider::Package
+ provides :rpm_package, os: [ "linux", "aix" ]
+
include Chef::Mixin::GetSourceFromPackage
def define_resource_requirements
diff --git a/lib/chef/provider/package/rubygems.rb b/lib/chef/provider/package/rubygems.rb
index 6c7e1c066e..3c0ca40693 100644
--- a/lib/chef/provider/package/rubygems.rb
+++ b/lib/chef/provider/package/rubygems.rb
@@ -359,6 +359,9 @@ class Chef
Chef::Log.logger
end
+ provides :chef_gem
+ provides :gem_package
+
include Chef::Mixin::GetSourceFromPackage
def initialize(new_resource, run_context=nil)
diff --git a/lib/chef/provider/package/smartos.rb b/lib/chef/provider/package/smartos.rb
index 19a6b9efef..7cef91953a 100644
--- a/lib/chef/provider/package/smartos.rb
+++ b/lib/chef/provider/package/smartos.rb
@@ -29,6 +29,8 @@ class Chef
class SmartOS < Chef::Provider::Package
attr_accessor :is_virtual_package
+ provides :smartos_package, os: "solaris2", platform_family: "smartos"
+
def load_current_resource
Chef::Log.debug("#{@new_resource} loading current resource")
@current_resource = Chef::Resource::Package.new(@new_resource.name)
diff --git a/lib/chef/provider/package/solaris.rb b/lib/chef/provider/package/solaris.rb
index 19f844b66a..53dd00dd07 100644
--- a/lib/chef/provider/package/solaris.rb
+++ b/lib/chef/provider/package/solaris.rb
@@ -27,6 +27,8 @@ class Chef
include Chef::Mixin::GetSourceFromPackage
+ provides :solaris_package, os: "solaris2"
+
# def initialize(*args)
# super
# @current_resource = Chef::Resource::Package.new(@new_resource.name)
diff --git a/lib/chef/provider/package/yum.rb b/lib/chef/provider/package/yum.rb
index e77319c254..505f5fd6a3 100644
--- a/lib/chef/provider/package/yum.rb
+++ b/lib/chef/provider/package/yum.rb
@@ -29,6 +29,8 @@ class Chef
class Package
class Yum < Chef::Provider::Package
+ provides :yum_package, os: "linux"
+
class RPMUtils
class << self
diff --git a/lib/chef/provider/remote_directory.rb b/lib/chef/provider/remote_directory.rb
index 5bd1cb5493..9a7416e318 100644
--- a/lib/chef/provider/remote_directory.rb
+++ b/lib/chef/provider/remote_directory.rb
@@ -32,6 +32,8 @@ class Chef
class Provider
class RemoteDirectory < Chef::Provider::Directory
+ provides :remote_directory
+
include Chef::Mixin::FileClass
def action_create
@@ -63,7 +65,7 @@ class Chef
def ls(path)
files = Dir.glob(::File.join(Chef::Util::PathHelper.escape_glob(path), '**', '*'),
::File::FNM_DOTMATCH)
-
+
# Remove current directory and previous directory
files.reject! do |name|
basename = Pathname.new(name).basename().to_s
diff --git a/lib/chef/provider/route.rb b/lib/chef/provider/route.rb
index 208a4f4139..72a5029a94 100644
--- a/lib/chef/provider/route.rb
+++ b/lib/chef/provider/route.rb
@@ -24,6 +24,8 @@ require 'ipaddr'
class Chef::Provider::Route < Chef::Provider
include Chef::Mixin::Command
+ provides :route
+
attr_accessor :is_running
MASK = {'0.0.0.0' => '0',
diff --git a/lib/chef/provider/ruby_block.rb b/lib/chef/provider/ruby_block.rb
index b0d94a3f8d..eb93fd5708 100644
--- a/lib/chef/provider/ruby_block.rb
+++ b/lib/chef/provider/ruby_block.rb
@@ -20,6 +20,8 @@
class Chef
class Provider
class RubyBlock < Chef::Provider
+ provides :ruby_block
+
def whyrun_supported?
true
end
diff --git a/lib/chef/provider/script.rb b/lib/chef/provider/script.rb
index 4aacf4f524..1615517553 100644
--- a/lib/chef/provider/script.rb
+++ b/lib/chef/provider/script.rb
@@ -22,6 +22,12 @@ require 'chef/provider/execute'
class Chef
class Provider
class Script < Chef::Provider::Execute
+ provides :bash
+ provides :csh
+ provides :perl
+ provides :python
+ provides :ruby
+ provides :script
def initialize(new_resource, run_context)
super
diff --git a/lib/chef/provider/service/arch.rb b/lib/chef/provider/service/arch.rb
index 9be5fb6fe3..888fb3fdf5 100644
--- a/lib/chef/provider/service/arch.rb
+++ b/lib/chef/provider/service/arch.rb
@@ -20,6 +20,12 @@ require 'chef/provider/service/init'
class Chef::Provider::Service::Arch < Chef::Provider::Service::Init
+ provides :service, platform_family: "arch"
+
+ def self.supports?(resource, action)
+ ::File.exist?("/etc/rc.d/#{resource.service_name}")
+ end
+
def initialize(new_resource, run_context)
super
@init_command = "/etc/rc.d/#{@new_resource.service_name}"
diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb
index 1ebef90349..25b1960b26 100644
--- a/lib/chef/provider/service/debian.rb
+++ b/lib/chef/provider/service/debian.rb
@@ -25,13 +25,19 @@ class Chef
UPDATE_RC_D_ENABLED_MATCHES = /\/rc[\dS].d\/S|not installed/i
UPDATE_RC_D_PRIORITIES = /\/rc([\dS]).d\/([SK])(\d\d)/i
+ provides :service, platform_family: "debian"
+
+ def self.supports?(resource, action)
+ Chef::Platform::ServiceHelpers.service_resource_providers.include?(:debian)
+ end
+
def load_current_resource
super
@priority_success = true
@rcd_status = nil
- @current_resource.priority(get_priority)
- @current_resource.enabled(service_currently_enabled?(@current_resource.priority))
- @current_resource
+ current_resource.priority(get_priority)
+ current_resource.enabled(service_currently_enabled?(current_resource.priority))
+ current_resource
end
def define_resource_requirements
@@ -47,7 +53,7 @@ class Chef
requirements.assert(:all_actions) do |a|
a.assertion { @priority_success }
- a.failure_message Chef::Exceptions::Service, "/usr/sbin/update-rc.d -n -f #{@current_resource.service_name} failed - #{@rcd_status.inspect}"
+ a.failure_message Chef::Exceptions::Service, "/usr/sbin/update-rc.d -n -f #{current_resource.service_name} failed - #{@rcd_status.inspect}"
# This can happen if the service is not yet installed,so we'll fake it.
a.whyrun ["Unable to determine priority of service, assuming service would have been correctly installed earlier in the run.",
"Assigning temporary priorities to continue.",
@@ -59,7 +65,7 @@ class Chef
"3"=>[:start, "20"],
"4"=>[:start, "20"],
"5"=>[:start, "20"]}
- @current_resource.priority(temp_priorities)
+ current_resource.priority(temp_priorities)
end
end
end
@@ -67,7 +73,7 @@ class Chef
def get_priority
priority = {}
- @rcd_status = popen4("/usr/sbin/update-rc.d -n -f #{@current_resource.service_name} remove") do |pid, stdin, stdout, stderr|
+ @rcd_status = popen4("/usr/sbin/update-rc.d -n -f #{current_resource.service_name} remove") do |pid, stdin, stdout, stderr|
[stdout, stderr].each do |iop|
iop.each_line do |line|
@@ -99,7 +105,7 @@ class Chef
def service_currently_enabled?(priority)
enabled = false
priority.each { |runlevel, arguments|
- Chef::Log.debug("#{@new_resource} runlevel #{runlevel}, action #{arguments[0]}, priority #{arguments[1]}")
+ Chef::Log.debug("#{new_resource} runlevel #{runlevel}, action #{arguments[0]}, priority #{arguments[1]}")
# if we are in a update-rc.d default startup runlevel && we start in this runlevel
if %w[ 1 2 3 4 5 S ].include?(runlevel) && arguments[0] == :start
enabled = true
@@ -111,63 +117,63 @@ class Chef
# Override method from parent to ensure priority is up-to-date
def action_enable
- if @new_resource.priority.nil?
+ if new_resource.priority.nil?
priority_ok = true
else
- priority_ok = @current_resource.priority == @new_resource.priority
+ priority_ok = @current_resource.priority == new_resource.priority
end
- if @current_resource.enabled and priority_ok
- Chef::Log.debug("#{@new_resource} already enabled - nothing to do")
+ if current_resource.enabled and priority_ok
+ Chef::Log.debug("#{new_resource} already enabled - nothing to do")
else
- converge_by("enable service #{@new_resource}") do
+ converge_by("enable service #{new_resource}") do
enable_service
- Chef::Log.info("#{@new_resource} enabled")
+ Chef::Log.info("#{new_resource} enabled")
end
end
load_new_resource_state
- @new_resource.enabled(true)
+ new_resource.enabled(true)
end
def enable_service
- if @new_resource.priority.is_a? Integer
- shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove")
- shell_out!("/usr/sbin/update-rc.d #{@new_resource.service_name} defaults #{@new_resource.priority} #{100 - @new_resource.priority}")
- elsif @new_resource.priority.is_a? Hash
+ if new_resource.priority.is_a? Integer
+ shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} remove")
+ shell_out!("/usr/sbin/update-rc.d #{new_resource.service_name} defaults #{new_resource.priority} #{100 - new_resource.priority}")
+ elsif new_resource.priority.is_a? Hash
# we call the same command regardless of we're enabling or disabling
# users passing a Hash are responsible for setting their own start priorities
set_priority
else # No priority, go with update-rc.d defaults
- shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove")
- shell_out!("/usr/sbin/update-rc.d #{@new_resource.service_name} defaults")
+ shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} remove")
+ shell_out!("/usr/sbin/update-rc.d #{new_resource.service_name} defaults")
end
end
def disable_service
- if @new_resource.priority.is_a? Integer
+ if new_resource.priority.is_a? Integer
# Stop processes in reverse order of start using '100 - start_priority'
- shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove")
- shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} stop #{100 - @new_resource.priority} 2 3 4 5 .")
- elsif @new_resource.priority.is_a? Hash
+ shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} remove")
+ shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} stop #{100 - new_resource.priority} 2 3 4 5 .")
+ elsif new_resource.priority.is_a? Hash
# we call the same command regardless of we're enabling or disabling
# users passing a Hash are responsible for setting their own stop priorities
set_priority
else
# no priority, using '100 - 20 (update-rc.d default)' to stop in reverse order of start
- shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove")
- shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} stop 80 2 3 4 5 .")
+ shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} remove")
+ shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} stop 80 2 3 4 5 .")
end
end
def set_priority
args = ""
- @new_resource.priority.each do |level, o|
+ new_resource.priority.each do |level, o|
action = o[0]
priority = o[1]
args += "#{action} #{priority} #{level} . "
end
- shell_out!("/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove")
- shell_out!("/usr/sbin/update-rc.d #{@new_resource.service_name} #{args}")
+ shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} remove")
+ shell_out!("/usr/sbin/update-rc.d #{new_resource.service_name} #{args}")
end
end
end
diff --git a/lib/chef/provider/service/freebsd.rb b/lib/chef/provider/service/freebsd.rb
index e0d9696f61..e4a456ac25 100644
--- a/lib/chef/provider/service/freebsd.rb
+++ b/lib/chef/provider/service/freebsd.rb
@@ -27,8 +27,9 @@ class Chef
attr_reader :enabled_state_found
- implements :service,
- :on_platforms => [:freebsd, :netbsd]
+ provides :service, os: [ "freebsd", "netbsd" ]
+
+ include Chef::Mixin::ShellOut
def initialize(new_resource, run_context)
super
diff --git a/lib/chef/provider/service/gentoo.rb b/lib/chef/provider/service/gentoo.rb
index e2dff10994..3dab920f06 100644
--- a/lib/chef/provider/service/gentoo.rb
+++ b/lib/chef/provider/service/gentoo.rb
@@ -22,6 +22,9 @@ require 'chef/mixin/command'
require 'chef/util/path_helper'
class Chef::Provider::Service::Gentoo < Chef::Provider::Service::Init
+
+ provides :service, platform_family: "gentoo"
+
def load_current_resource
@new_resource.supports[:status] = true
diff --git a/lib/chef/provider/service/init.rb b/lib/chef/provider/service/init.rb
index 5d8bb5bb38..ab40a720f6 100644
--- a/lib/chef/provider/service/init.rb
+++ b/lib/chef/provider/service/init.rb
@@ -26,6 +26,8 @@ class Chef
attr_accessor :init_command
+ provides :service, os: "!windows"
+
def initialize(new_resource, run_context)
super
@init_command = "/etc/init.d/#{@new_resource.service_name}"
diff --git a/lib/chef/provider/service/insserv.rb b/lib/chef/provider/service/insserv.rb
index 1ee817707a..df5a162a45 100644
--- a/lib/chef/provider/service/insserv.rb
+++ b/lib/chef/provider/service/insserv.rb
@@ -24,26 +24,32 @@ class Chef
class Service
class Insserv < Chef::Provider::Service::Init
+ provides :service, os: "linux"
+
+ def self.supports?(resource, action)
+ Chef::Platform::ServiceHelpers.service_resource_providers.include?(:insserv)
+ end
+
def load_current_resource
super
- # Look for a /etc/rc.*/SnnSERVICE link to signifiy that the service would be started in a runlevel
- if Dir.glob("/etc/rc**/S*#{Chef::Util::PathHelper.escape_glob(@current_resource.service_name)}").empty?
- @current_resource.enabled false
+ # Look for a /etc/rc.*/SnnSERVICE link to signify that the service would be started in a runlevel
+ if Dir.glob("/etc/rc**/S*#{Chef::Util::PathHelper.escape_glob(current_resource.service_name)}").empty?
+ current_resource.enabled false
else
- @current_resource.enabled true
+ current_resource.enabled true
end
- @current_resource
+ current_resource
end
def enable_service()
- shell_out!("/sbin/insserv -r -f #{@new_resource.service_name}")
- shell_out!("/sbin/insserv -d -f #{@new_resource.service_name}")
+ shell_out!("/sbin/insserv -r -f #{new_resource.service_name}")
+ shell_out!("/sbin/insserv -d -f #{new_resource.service_name}")
end
def disable_service()
- shell_out!("/sbin/insserv -r -f #{@new_resource.service_name}")
+ shell_out!("/sbin/insserv -r -f #{new_resource.service_name}")
end
end
end
diff --git a/lib/chef/provider/service/invokercd.rb b/lib/chef/provider/service/invokercd.rb
index e6afa7272a..c7472211bc 100644
--- a/lib/chef/provider/service/invokercd.rb
+++ b/lib/chef/provider/service/invokercd.rb
@@ -23,6 +23,12 @@ class Chef
class Service
class Invokercd < Chef::Provider::Service::Init
+ provides :service, platform_family: "debian"
+
+ def self.supports?(resource, action)
+ Chef::Platform::ServiceHelpers.service_resource_providers.include?(:invokerc)
+ end
+
def initialize(new_resource, run_context)
super
@init_command = "/usr/sbin/invoke-rc.d #{@new_resource.service_name}"
diff --git a/lib/chef/provider/service/macosx.rb b/lib/chef/provider/service/macosx.rb
index ad1535327b..10ad1aa29d 100644
--- a/lib/chef/provider/service/macosx.rb
+++ b/lib/chef/provider/service/macosx.rb
@@ -26,6 +26,8 @@ class Chef
class Service
class Macosx < Chef::Provider::Service::Simple
+ provides :service, os: "darwin"
+
def self.gather_plist_dirs
locations = %w{/Library/LaunchAgents
/Library/LaunchDaemons
diff --git a/lib/chef/provider/service/redhat.rb b/lib/chef/provider/service/redhat.rb
index 7a7b2a1c40..90744ae268 100644
--- a/lib/chef/provider/service/redhat.rb
+++ b/lib/chef/provider/service/redhat.rb
@@ -26,11 +26,17 @@ class Chef
CHKCONFIG_ON = /\d:on/
CHKCONFIG_MISSING = /No such/
+ provides :service, platform_family: [ "rhel", "fedora", "suse" ]
+
+ def self.supports?(resource, action)
+ Chef::Platform::ServiceHelpers.service_resource_providers.include?(:redhat)
+ end
+
def initialize(new_resource, run_context)
super
- @init_command = "/sbin/service #{@new_resource.service_name}"
- @new_resource.supports[:status] = true
- @service_missing = false
+ @init_command = "/sbin/service #{@new_resource.service_name}"
+ @new_resource.supports[:status] = true
+ @service_missing = false
end
def define_resource_requirements
diff --git a/lib/chef/provider/service/simple.rb b/lib/chef/provider/service/simple.rb
index bd51d15f84..ee403ee163 100644
--- a/lib/chef/provider/service/simple.rb
+++ b/lib/chef/provider/service/simple.rb
@@ -25,6 +25,8 @@ class Chef
class Service
class Simple < Chef::Provider::Service
+ # this must be subclassed to be useful so does not directly implement :service
+
attr_reader :status_load_success
def load_current_resource
diff --git a/lib/chef/provider/service/solaris.rb b/lib/chef/provider/service/solaris.rb
index f0584dcf6d..eaea6bb1ab 100644
--- a/lib/chef/provider/service/solaris.rb
+++ b/lib/chef/provider/service/solaris.rb
@@ -26,6 +26,8 @@ class Chef
class Solaris < Chef::Provider::Service
attr_reader :maintenance
+ provides :service, os: "solaris2"
+
def initialize(new_resource, run_context=nil)
super
@init_command = "/usr/sbin/svcadm"
diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb
index 31feee65d4..311751ab9a 100644
--- a/lib/chef/provider/service/systemd.rb
+++ b/lib/chef/provider/service/systemd.rb
@@ -20,6 +20,13 @@ require 'chef/resource/service'
require 'chef/provider/service/simple'
class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
+
+ provides :service, os: "linux"
+
+ def self.supports?(resource, action)
+ Chef::Platform::ServiceHelpers.service_resource_providers.include?(:systemd)
+ end
+
def load_current_resource
@current_resource = Chef::Resource::Service.new(@new_resource.name)
@current_resource.service_name(@new_resource.service_name)
diff --git a/lib/chef/provider/service/upstart.rb b/lib/chef/provider/service/upstart.rb
index 670bf9e5f8..41bd850d6a 100644
--- a/lib/chef/provider/service/upstart.rb
+++ b/lib/chef/provider/service/upstart.rb
@@ -27,6 +27,13 @@ class Chef
class Upstart < Chef::Provider::Service::Simple
UPSTART_STATE_FORMAT = /\w+ \(?(\w+)\)?[\/ ](\w+)/
+ provides :service, os: "linux"
+
+ def self.supports?(resource, action)
+ Chef::Platform::ServiceHelpers.service_resource_providers.include?(:upstart) &&
+ Chef::Platform::ServiceHelpers.config_for_service(resource.service_name).include?(:upstart)
+ end
+
# Upstart does more than start or stop a service, creating multiple 'states' [1] that a service can be in.
# In chef, when we ask a service to start, we expect it to have started before performing the next step
# since we have top down dependencies. Which is to say we may follow witha resource next that requires
diff --git a/lib/chef/provider/service/windows.rb b/lib/chef/provider/service/windows.rb
index d31aad4c9d..4b1d2079ec 100644
--- a/lib/chef/provider/service/windows.rb
+++ b/lib/chef/provider/service/windows.rb
@@ -25,6 +25,10 @@ end
class Chef::Provider::Service::Windows < Chef::Provider::Service
+ provides :service, os: "windows"
+
+ include Chef::Mixin::ShellOut
+
#Win32::Service.get_start_type
AUTO_START = 'auto start'
MANUAL = 'demand start'
diff --git a/lib/chef/provider/subversion.rb b/lib/chef/provider/subversion.rb
index 6cf31c8ec8..f4a0e6fc13 100644
--- a/lib/chef/provider/subversion.rb
+++ b/lib/chef/provider/subversion.rb
@@ -27,6 +27,8 @@ class Chef
class Provider
class Subversion < Chef::Provider
+ provides :subversion
+
SVN_INFO_PATTERN = /^([\w\s]+): (.+)$/
include Chef::Mixin::Command
diff --git a/lib/chef/provider/template.rb b/lib/chef/provider/template.rb
index 48cc45f3a8..1e759074b9 100644
--- a/lib/chef/provider/template.rb
+++ b/lib/chef/provider/template.rb
@@ -25,6 +25,7 @@ require 'chef/deprecation/warnings'
class Chef
class Provider
class Template < Chef::Provider::File
+ provides :template
extend Chef::Deprecation::Warnings
include Chef::Deprecation::Provider::Template
diff --git a/lib/chef/provider/user/pw.rb b/lib/chef/provider/user/pw.rb
index 0dc80103da..fe71e93561 100644
--- a/lib/chef/provider/user/pw.rb
+++ b/lib/chef/provider/user/pw.rb
@@ -23,9 +23,6 @@ class Chef
class User
class Pw < Chef::Provider::User
- implements :user,
- :on_platforms => :freebsd
-
def load_current_resource
super
raise Chef::Exceptions::User, "Could not find binary /usr/sbin/pw for #{@new_resource}" unless ::File.exists?("/usr/sbin/pw")
diff --git a/lib/chef/provider/whyrun_safe_ruby_block.rb b/lib/chef/provider/whyrun_safe_ruby_block.rb
index e5f35debd7..3b95752cc4 100644
--- a/lib/chef/provider/whyrun_safe_ruby_block.rb
+++ b/lib/chef/provider/whyrun_safe_ruby_block.rb
@@ -19,6 +19,8 @@
class Chef
class Provider
class WhyrunSafeRubyBlock < Chef::Provider::RubyBlock
+ provides :whyrun_safe_ruby_block
+
def action_run
@new_resource.block.call
@new_resource.updated_by_last_action(true)
diff --git a/lib/chef/provider_resolver.rb b/lib/chef/provider_resolver.rb
index 91b85e3aa0..c819b0c87f 100644
--- a/lib/chef/provider_resolver.rb
+++ b/lib/chef/provider_resolver.rb
@@ -16,42 +16,88 @@
# limitations under the License.
#
+require 'chef/exceptions'
+require 'chef/platform/provider_priority_map'
+
class Chef
class ProviderResolver
attr_reader :node
- attr_reader :providers
def initialize(node)
@node = node
- @providers = []
- @loaded = false
end
- def load(reload = false)
- return if loaded? && !reload
+ # return a deterministically sorted list of Chef::Provider subclasses
+ def providers
+ Chef::Provider.descendants.sort {|a,b| a.to_s <=> b.to_s }
+ end
- @providers = [] if reload
+ def resolve(resource, action)
+ maybe_explicit_provider(resource) ||
+ maybe_dynamic_provider_resolution(resource, action) ||
+ maybe_chef_platform_lookup(resource)
+ end
- Chef::Provider.each do |provider|
- @providers << provider if provider.supports_platform?(@node[:platform])
- end
+ private
- @loaded = true
+ # if resource.provider is set, just return one of those objects
+ def maybe_explicit_provider(resource)
+ return nil unless resource.provider
+ resource.provider
end
- def loaded?
- !!@loaded
- end
+ # try dynamically finding a provider based on querying the providers to see what they support
+ def maybe_dynamic_provider_resolution(resource, action)
+ # 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
- def resolve(resource)
- self.load if !loaded?
+ # 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}"
- providers = @providers.find_all do |provider|
- provider.enabled?(node) && provider.implements?(resource)
+ # ask all the enabled providers if they can actually support the resource
+ supported_handlers = enabled_handlers.select do |klass|
+ klass.supports?(resource, action)
end
- resource.evaluate_providers(providers)
+ # 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}"
+
+ handlers = supported_handlers.empty? ? enabled_handlers : supported_handlers
+
+ 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}"
+
+ raise Chef::Exceptions::AmbiguousProviderResolution.new(resource, handlers) if handlers.count >= 2
+
+ return nil if handlers.empty?
+
+ handlers[0]
+ end
+
+ # try the old static lookup of providers by platform
+ 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/lib/chef/providers.rb b/lib/chef/providers.rb
index bceb1f7106..c4f1ce769d 100644
--- a/lib/chef/providers.rb
+++ b/lib/chef/providers.rb
@@ -75,13 +75,13 @@ require 'chef/provider/package/smartos'
require 'chef/provider/package/aix'
require 'chef/provider/service/arch'
-require 'chef/provider/service/debian'
require 'chef/provider/service/freebsd'
require 'chef/provider/service/gentoo'
require 'chef/provider/service/init'
-require 'chef/provider/service/insserv'
require 'chef/provider/service/invokercd'
+require 'chef/provider/service/debian'
require 'chef/provider/service/redhat'
+require 'chef/provider/service/insserv'
require 'chef/provider/service/simple'
require 'chef/provider/service/systemd'
require 'chef/provider/service/upstart'
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index 5099446335..c38f36aa72 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -27,11 +27,12 @@ require 'chef/guard_interpreter/resource_guard_interpreter'
require 'chef/resource/conditional'
require 'chef/resource/conditional_action_not_nothing'
require 'chef/resource_collection'
-require 'chef/resource_platform_map'
+require 'chef/node_map'
require 'chef/node'
require 'chef/platform'
require 'chef/mixin/deprecation'
+require 'chef/mixin/descendants_tracker'
class Chef
class Resource
@@ -133,6 +134,7 @@ F
include Chef::Mixin::Deprecation
extend Chef::Mixin::ConvertToClassName
+ extend Chef::Mixin::DescendantsTracker
if Module.method(:const_defined?).arity == 1
def self.strict_const_defined?(const)
@@ -144,24 +146,13 @@ F
end
end
- # Track all subclasses of Resource. This is used so names can be looked up
- # when attempting to deserialize from JSON. (See: json_compat)
- def self.resource_classes
- # Using a class variable here ensures we have one variable to track
- # subclasses shared by the entire class hierarchy; without this, each
- # subclass would have its own list of subclasses.
- @@resource_classes ||= []
- end
-
- # Callback when subclass is defined. Adds subclass to list of subclasses.
- def self.inherited(subclass)
- resource_classes << subclass
- end
-
- # Look up a subclass by +class_name+ which should be a string that matches
- # `Subclass.name`
- def self.find_subclass_by_name(class_name)
- resource_classes.first {|c| c.name == class_name }
+ class << self
+ # back-compat
+ # NOTE: that we do not support unregistering classes as descendents like
+ # we used to for LWRP unloading because that was horrible and removed in
+ # Chef-12.
+ alias :resource_classes :descendants
+ alias :find_subclass_by_name :find_descendants_by_name
end
# Set or return the list of "state attributes" implemented by the Resource
@@ -687,21 +678,10 @@ F
raise ArgumentError, "nil is not a valid action for resource #{self}" if action.nil?
end
- def evaluate_providers(providers)
- provider = providers.first
- end
-
def provider_for_action(action)
- # leverage new platform => short_name => resource
- # which requires explicitly setting provider in
- # resource class
- if self.provider
- provider = self.provider.new(self, self.run_context)
- provider.action = action
- provider
- else # fall back to old provider resolution
- Chef::Platform.provider_for_resource(self, action)
- end
+ provider = run_context.provider_resolver.resolve(self, action).new(self, run_context)
+ provider.action = action
+ provider
end
def custom_exception_message(e)
@@ -776,8 +756,8 @@ F
@provider_base ||= Chef::Provider
end
- def self.platform_map
- @@platform_map ||= PlatformMap.new
+ def self.node_map
+ @@node_map ||= NodeMap.new
end
# Maps a short_name (and optionally a platform and version) to a
@@ -786,66 +766,55 @@ F
# (I'm looking at you Chef::Resource::Package)
# Ex:
# class WindowsFile < Chef::Resource
- # provides :file, :on_platforms => ["windows"]
+ # provides :file, os: "linux", platform_family: "rhel", platform: "redhat"
+ # provides :file, os: "!windows
+ # provides :file, os: [ "linux", "aix" ]
+ # provides :file, os: "solaris2" do |node|
+ # node['platform_version'].to_f <= 5.11
+ # end
# # ...other stuff
# end
#
- # TODO: 2011-11-02 schisamo - platform_version support
- def self.provides(short_name, opts={})
+ def self.provides(short_name, opts={}, &block)
short_name_sym = short_name
if short_name.kind_of?(String)
+ # YAGNI: this is probably completely unnecessary and can be removed?
+ Chef::Log.warn "[DEPRECATION] Passing a String to Chef::Resource#provides will be removed"
short_name.downcase!
short_name.gsub!(/\s/, "_")
short_name_sym = short_name.to_sym
end
- if opts.has_key?(:on_platforms)
- platforms = [opts[:on_platforms]].flatten
- platforms.each do |p|
- p = :default if :all == p.to_sym
- platform_map.set(
- :platform => p.to_sym,
- :short_name => short_name_sym,
- :resource => self
- )
- end
- else
- platform_map.set(
- :short_name => short_name_sym,
- :resource => self
- )
- end
+ node_map.set(short_name_sym, constantize(self.name), opts, &block)
end
- # Returns a resource based on a short_name anda platform and version.
- #
+ # Returns a resource based on a short_name and node
#
# ==== Parameters
# short_name<Symbol>:: short_name of the resource (ie :directory)
- # platform<Symbol,String>:: platform name
- # version<String>:: platform version
+ # node<Chef::Node>:: Node object to look up platform and version in
#
# === Returns
# <Chef::Resource>:: returns the proper Chef::Resource class
- def self.resource_for_platform(short_name, platform=nil, version=nil)
- platform_map.get(short_name, platform, version)
+ def self.resource_for_node(short_name, node)
+ klass = node_map.get(node, short_name) ||
+ resource_matching_short_name(short_name)
+ raise Chef::Exceptions::NoSuchResourceType.new(short_name, node) if klass.nil?
+ klass
end
- # Returns a resource based on a short_name and a node's
- # platform and version.
- #
+ # Returns the class of a Chef::Resource based on the short name
# ==== Parameters
# short_name<Symbol>:: short_name of the resource (ie :directory)
- # node<Chef::Node>:: Node object to look up platform and version in
#
# === Returns
# <Chef::Resource>:: returns the proper Chef::Resource class
- def self.resource_for_node(short_name, node)
+ def self.resource_matching_short_name(short_name)
begin
- platform, version = Chef::Platform.find_platform_and_version(node)
- rescue ArgumentError
+ rname = convert_to_class_name(short_name.to_s)
+ Chef::Resource.const_get(rname)
+ rescue NameError
+ nil
end
- resource = resource_for_platform(short_name, platform, version)
- resource
end
private
diff --git a/lib/chef/resource/apt_package.rb b/lib/chef/resource/apt_package.rb
index 050cf838ae..f944825ac3 100644
--- a/lib/chef/resource/apt_package.rb
+++ b/lib/chef/resource/apt_package.rb
@@ -23,10 +23,12 @@ class Chef
class Resource
class AptPackage < Chef::Resource::Package
+ provides :apt_package
+ provides :package, os: "linux", platform_family: [ "debian" ]
+
def initialize(name, run_context=nil)
super
@resource_name = :apt_package
- @provider = Chef::Provider::Package::Apt
@default_release = nil
end
diff --git a/lib/chef/resource/bash.rb b/lib/chef/resource/bash.rb
index c56de5fe20..0add0ce501 100644
--- a/lib/chef/resource/bash.rb
+++ b/lib/chef/resource/bash.rb
@@ -17,6 +17,7 @@
#
require 'chef/resource/script'
+require 'chef/provider/script'
class Chef
class Resource
diff --git a/lib/chef/resource/bff_package.rb b/lib/chef/resource/bff_package.rb
index 2d78483e4b..917f0d1d50 100644
--- a/lib/chef/resource/bff_package.rb
+++ b/lib/chef/resource/bff_package.rb
@@ -26,7 +26,6 @@ class Chef
def initialize(name, run_context=nil)
super
@resource_name = :bff_package
- @provider = Chef::Provider::Package::Aix
end
end
diff --git a/lib/chef/resource/breakpoint.rb b/lib/chef/resource/breakpoint.rb
index 83c397bd5b..b2210262d2 100644
--- a/lib/chef/resource/breakpoint.rb
+++ b/lib/chef/resource/breakpoint.rb
@@ -28,7 +28,7 @@ class Chef
super(@name, *args)
@action = "break"
@allowed_actions << :break
- @provider = Chef::Provider::Breakpoint
+ @resource_name = :breakpoint
end
end
end
diff --git a/lib/chef/resource/chef_gem.rb b/lib/chef/resource/chef_gem.rb
index af45cb93e6..b4ead11f1d 100644
--- a/lib/chef/resource/chef_gem.rb
+++ b/lib/chef/resource/chef_gem.rb
@@ -23,13 +23,12 @@ class Chef
class Resource
class ChefGem < Chef::Resource::Package::GemPackage
- provides :chef_gem, :on_platforms => :all
+ provides :chef_gem
def initialize(name, run_context=nil)
super
@resource_name = :chef_gem
@gem_binary = RbConfig::CONFIG['bindir'] + "/gem"
- @provider = Chef::Provider::Package::Rubygems
end
# The chef_gem resources is for installing gems to the current gem environment only for use by Chef cookbooks.
diff --git a/lib/chef/resource/cookbook_file.rb b/lib/chef/resource/cookbook_file.rb
index 2709cf64f4..7be353b648 100644
--- a/lib/chef/resource/cookbook_file.rb
+++ b/lib/chef/resource/cookbook_file.rb
@@ -27,7 +27,7 @@ class Chef
class CookbookFile < Chef::Resource::File
include Chef::Mixin::Securable
- provides :cookbook_file, :on_platforms => :all
+ provides :cookbook_file
def initialize(name, run_context=nil)
super
@@ -36,7 +36,6 @@ class Chef
@action = "create"
@source = ::File.basename(name)
@cookbook = nil
- @provider = Chef::Provider::CookbookFile
end
def source(source_filename=nil)
diff --git a/lib/chef/resource/csh.rb b/lib/chef/resource/csh.rb
index 95aa8afd7a..36659c349b 100644
--- a/lib/chef/resource/csh.rb
+++ b/lib/chef/resource/csh.rb
@@ -17,6 +17,7 @@
#
require 'chef/resource/script'
+require 'chef/provider/script'
class Chef
class Resource
diff --git a/lib/chef/resource/deploy.rb b/lib/chef/resource/deploy.rb
index a08e8aeeea..4252aa230f 100644
--- a/lib/chef/resource/deploy.rb
+++ b/lib/chef/resource/deploy.rb
@@ -77,7 +77,6 @@ class Chef
@shallow_clone = false
@scm_provider = Chef::Provider::Git
@svn_force_export = false
- @provider = Chef::Provider::Deploy::Timestamped
@allowed_actions.push(:force_deploy, :deploy, :rollback)
@additional_remotes = Hash[]
@keep_releases = 5
diff --git a/lib/chef/resource/deploy_revision.rb b/lib/chef/resource/deploy_revision.rb
index ceac26e91a..e144ce2162 100644
--- a/lib/chef/resource/deploy_revision.rb
+++ b/lib/chef/resource/deploy_revision.rb
@@ -22,14 +22,19 @@ class Chef
# Convenience class for using the deploy resource with the revision
# deployment strategy (provider)
class DeployRevision < Chef::Resource::Deploy
+
+ provides :deploy_revision
+
def initialize(*args, &block)
super
@resource_name = :deploy_revision
- @provider = Chef::Provider::Deploy::Revision
end
end
class DeployBranch < Chef::Resource::DeployRevision
+
+ provides :deploy_branch
+
def initialize(*args, &block)
super
@resource_name = :deploy_branch
diff --git a/lib/chef/resource/directory.rb b/lib/chef/resource/directory.rb
index 423c0bbe27..1ab7f0d16d 100644
--- a/lib/chef/resource/directory.rb
+++ b/lib/chef/resource/directory.rb
@@ -32,7 +32,7 @@ class Chef
include Chef::Mixin::Securable
- provides :directory, :on_platforms => :all
+ provides :directory
def initialize(name, run_context=nil)
super
@@ -41,7 +41,6 @@ class Chef
@action = :create
@recursive = false
@allowed_actions.push(:create, :delete)
- @provider = Chef::Provider::Directory
end
def recursive(arg=nil)
diff --git a/lib/chef/resource/dpkg_package.rb b/lib/chef/resource/dpkg_package.rb
index 2fb5b5c249..35a47e8a82 100644
--- a/lib/chef/resource/dpkg_package.rb
+++ b/lib/chef/resource/dpkg_package.rb
@@ -23,10 +23,11 @@ class Chef
class Resource
class DpkgPackage < Chef::Resource::Package
+ provides :dpkg_package, os: "linux"
+
def initialize(name, run_context=nil)
super
@resource_name = :dpkg_package
- @provider = Chef::Provider::Package::Dpkg
end
end
diff --git a/lib/chef/resource/dsc_script.rb b/lib/chef/resource/dsc_script.rb
index 76ac6659d6..82907c25db 100644
--- a/lib/chef/resource/dsc_script.rb
+++ b/lib/chef/resource/dsc_script.rb
@@ -22,13 +22,12 @@ class Chef
class Resource
class DscScript < Chef::Resource
- provides :dsc_script, :on_platforms => ["windows"]
+ provides :dsc_script, platform: "windows"
def initialize(name, run_context=nil)
super
@allowed_actions.push(:run)
@action = :run
- @provider = Chef::Provider::DscScript
@resource_name = :dsc_script
end
diff --git a/lib/chef/resource/easy_install_package.rb b/lib/chef/resource/easy_install_package.rb
index f25e1ac22f..5286e9a289 100644
--- a/lib/chef/resource/easy_install_package.rb
+++ b/lib/chef/resource/easy_install_package.rb
@@ -22,10 +22,11 @@ class Chef
class Resource
class EasyInstallPackage < Chef::Resource::Package
+ provides :easy_install_package
+
def initialize(name, run_context=nil)
super
@resource_name = :easy_install_package
- @provider = Chef::Provider::Package::EasyInstall
end
def easy_install_binary(arg=nil)
diff --git a/lib/chef/resource/erl_call.rb b/lib/chef/resource/erl_call.rb
index 959856af66..24009d51c7 100644
--- a/lib/chef/resource/erl_call.rb
+++ b/lib/chef/resource/erl_call.rb
@@ -18,6 +18,7 @@
#
require 'chef/resource'
+require 'chef/provider/erl_call'
class Chef
class Resource
diff --git a/lib/chef/resource/execute.rb b/lib/chef/resource/execute.rb
index ae118b1c9e..980035b079 100644
--- a/lib/chef/resource/execute.rb
+++ b/lib/chef/resource/execute.rb
@@ -18,6 +18,7 @@
#
require 'chef/resource'
+require 'chef/provider/execute'
class Chef
class Resource
diff --git a/lib/chef/resource/file.rb b/lib/chef/resource/file.rb
index 3c1f4785ef..16491f9bc8 100644
--- a/lib/chef/resource/file.rb
+++ b/lib/chef/resource/file.rb
@@ -19,7 +19,6 @@
require 'chef/resource'
require 'chef/platform/query_helpers'
-require 'chef/provider/file'
require 'chef/mixin/securable'
class Chef
@@ -38,7 +37,7 @@ class Chef
attr_writer :checksum
- provides :file, :on_platforms => :all
+ provides :file
def initialize(name, run_context=nil)
super
@@ -47,7 +46,6 @@ class Chef
@backup = 5
@action = "create"
@allowed_actions.push(:create, :delete, :touch, :create_if_missing)
- @provider = Chef::Provider::File
@atomic_update = Chef::Config[:file_atomic_update]
@force_unlink = false
@manage_symlink_source = nil
diff --git a/lib/chef/resource/freebsd_package.rb b/lib/chef/resource/freebsd_package.rb
index 957c25caf1..9c8db506f8 100644
--- a/lib/chef/resource/freebsd_package.rb
+++ b/lib/chef/resource/freebsd_package.rb
@@ -29,7 +29,7 @@ class Chef
class FreebsdPackage < Chef::Resource::Package
include Chef::Mixin::ShellOut
- provides :package, :on_platforms => ["freebsd"]
+ provides :package, platform: "freebsd"
def initialize(name, run_context=nil)
super
diff --git a/lib/chef/resource/gem_package.rb b/lib/chef/resource/gem_package.rb
index 6def7b6653..631aa13f56 100644
--- a/lib/chef/resource/gem_package.rb
+++ b/lib/chef/resource/gem_package.rb
@@ -22,10 +22,11 @@ class Chef
class Resource
class GemPackage < Chef::Resource::Package
+ provides :gem_package
+
def initialize(name, run_context=nil)
super
@resource_name = :gem_package
- @provider = Chef::Provider::Package::Rubygems
end
def source(arg=nil)
diff --git a/lib/chef/resource/git.rb b/lib/chef/resource/git.rb
index 774bb24f24..7156873315 100644
--- a/lib/chef/resource/git.rb
+++ b/lib/chef/resource/git.rb
@@ -22,10 +22,11 @@ class Chef
class Resource
class Git < Chef::Resource::Scm
+ provides :git
+
def initialize(name, run_context=nil)
super
@resource_name = :git
- @provider = Chef::Provider::Git
@additional_remotes = Hash[]
end
diff --git a/lib/chef/resource/homebrew_package.rb b/lib/chef/resource/homebrew_package.rb
index e1d50c1739..952552e3a8 100644
--- a/lib/chef/resource/homebrew_package.rb
+++ b/lib/chef/resource/homebrew_package.rb
@@ -25,10 +25,11 @@ class Chef
class Resource
class HomebrewPackage < Chef::Resource::Package
+ provides :homebrew_package, os: "mac_os_x"
+
def initialize(name, run_context=nil)
super
@resource_name = :homebrew_package
- @provider = Chef::Provider::Package::Homebrew
@homebrew_user = nil
end
diff --git a/lib/chef/resource/http_request.rb b/lib/chef/resource/http_request.rb
index 47f6286fb4..ccb0a26629 100644
--- a/lib/chef/resource/http_request.rb
+++ b/lib/chef/resource/http_request.rb
@@ -18,6 +18,7 @@
#
require 'chef/resource'
+require 'chef/provider/http_request'
class Chef
class Resource
diff --git a/lib/chef/resource/ips_package.rb b/lib/chef/resource/ips_package.rb
index 88c6e9a538..77b3387946 100644
--- a/lib/chef/resource/ips_package.rb
+++ b/lib/chef/resource/ips_package.rb
@@ -22,10 +22,12 @@ require 'chef/provider/package/ips'
class Chef
class Resource
class IpsPackage < ::Chef::Resource::Package
+
+ provides :ips_package, os: "solaris2"
+
def initialize(name, run_context = nil)
super(name, run_context)
@resource_name = :ips_package
- @provider = Chef::Provider::Package::Ips
@allowed_actions = [ :install, :remove, :upgrade ]
@accept_license = false
end
diff --git a/lib/chef/resource/link.rb b/lib/chef/resource/link.rb
index e53b386a74..8726eded1d 100644
--- a/lib/chef/resource/link.rb
+++ b/lib/chef/resource/link.rb
@@ -25,7 +25,7 @@ class Chef
class Link < Chef::Resource
include Chef::Mixin::Securable
- provides :link, :on_platform => :all
+ provides :link
identity_attr :target_file
@@ -40,7 +40,6 @@ class Chef
@link_type = :symbolic
@target_file = name
@allowed_actions.push(:create, :delete)
- @provider = Chef::Provider::Link
end
def to(arg=nil)
diff --git a/lib/chef/resource/log.rb b/lib/chef/resource/log.rb
index 391c3b5393..7f970a87a4 100644
--- a/lib/chef/resource/log.rb
+++ b/lib/chef/resource/log.rb
@@ -16,6 +16,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+
+require 'chef/resource'
+require 'chef/provider/log'
+
class Chef
class Resource
class Log < Chef::Resource
diff --git a/lib/chef/resource/macports_package.rb b/lib/chef/resource/macports_package.rb
index c9434c9e69..bdc8698155 100644
--- a/lib/chef/resource/macports_package.rb
+++ b/lib/chef/resource/macports_package.rb
@@ -19,10 +19,12 @@
class Chef
class Resource
class MacportsPackage < Chef::Resource::Package
+
+ provides :macports_package, os: "mac_os_x"
+
def initialize(name, run_context=nil)
super
@resource_name = :macports_package
- @provider = Chef::Provider::Package::Macports
end
end
end
diff --git a/lib/chef/resource/pacman_package.rb b/lib/chef/resource/pacman_package.rb
index 2894e415ac..4c45dd004f 100644
--- a/lib/chef/resource/pacman_package.rb
+++ b/lib/chef/resource/pacman_package.rb
@@ -22,10 +22,11 @@ class Chef
class Resource
class PacmanPackage < Chef::Resource::Package
+ provides :pacman_package, os: "linux"
+
def initialize(name, run_context=nil)
super
@resource_name = :pacman_package
- @provider = Chef::Provider::Package::Pacman
end
end
diff --git a/lib/chef/resource/paludis_package.rb b/lib/chef/resource/paludis_package.rb
index fde25e69b3..7eddf8690b 100644
--- a/lib/chef/resource/paludis_package.rb
+++ b/lib/chef/resource/paludis_package.rb
@@ -22,10 +22,12 @@ require 'chef/provider/package/paludis'
class Chef
class Resource
class PaludisPackage < Chef::Resource::Package
+
+ provides :paludis_package, os: "linux"
+
def initialize(name, run_context=nil)
super(name, run_context)
@resource_name = :paludis_package
- @provider = Chef::Provider::Package::Paludis
@allowed_actions = [ :install, :remove, :upgrade ]
@timeout = 3600
end
diff --git a/lib/chef/resource/perl.rb b/lib/chef/resource/perl.rb
index 546f639e1f..c4bdb6e130 100644
--- a/lib/chef/resource/perl.rb
+++ b/lib/chef/resource/perl.rb
@@ -17,6 +17,7 @@
#
require 'chef/resource/script'
+require 'chef/provider/script'
class Chef
class Resource
diff --git a/lib/chef/resource/python.rb b/lib/chef/resource/python.rb
index f340afdb39..b1f23d13ce 100644
--- a/lib/chef/resource/python.rb
+++ b/lib/chef/resource/python.rb
@@ -1,4 +1,3 @@
-#
# Author:: Adam Jacob (<adam@opscode.com>)
# Copyright:: Copyright (c) 2008 Opscode, Inc.
# License:: Apache License, Version 2.0
@@ -17,6 +16,7 @@
#
require 'chef/resource/script'
+require 'chef/provider/script'
class Chef
class Resource
diff --git a/lib/chef/resource/remote_directory.rb b/lib/chef/resource/remote_directory.rb
index 0f7e0eb5de..d4108da47a 100644
--- a/lib/chef/resource/remote_directory.rb
+++ b/lib/chef/resource/remote_directory.rb
@@ -26,7 +26,7 @@ class Chef
class RemoteDirectory < Chef::Resource::Directory
include Chef::Mixin::Securable
- provides :remote_directory, :on_platforms => :all
+ provides :remote_directory
identity_attr :path
@@ -48,7 +48,6 @@ class Chef
@overwrite = true
@allowed_actions.push(:create, :create_if_missing, :delete)
@cookbook = nil
- @provider = Chef::Provider::RemoteDirectory
end
if Chef::Platform.windows?
diff --git a/lib/chef/resource/remote_file.rb b/lib/chef/resource/remote_file.rb
index 6334b1bf44..46516fd3fb 100644
--- a/lib/chef/resource/remote_file.rb
+++ b/lib/chef/resource/remote_file.rb
@@ -26,7 +26,7 @@ class Chef
class RemoteFile < Chef::Resource::File
include Chef::Mixin::Securable
- provides :remote_file, :on_platforms => :all
+ provides :remote_file
def initialize(name, run_context=nil)
super
diff --git a/lib/chef/resource/rpm_package.rb b/lib/chef/resource/rpm_package.rb
index 200a9633ce..8634f1e25d 100644
--- a/lib/chef/resource/rpm_package.rb
+++ b/lib/chef/resource/rpm_package.rb
@@ -23,10 +23,11 @@ class Chef
class Resource
class RpmPackage < Chef::Resource::Package
+ provides :rpm_package, os: [ "linux", "aix" ]
+
def initialize(name, run_context=nil)
super
@resource_name = :rpm_package
- @provider = Chef::Provider::Package::Rpm
end
end
diff --git a/lib/chef/resource/ruby.rb b/lib/chef/resource/ruby.rb
index 605d27b00d..2b2aa0249d 100644
--- a/lib/chef/resource/ruby.rb
+++ b/lib/chef/resource/ruby.rb
@@ -17,6 +17,7 @@
#
require 'chef/resource/script'
+require 'chef/provider/script'
class Chef
class Resource
diff --git a/lib/chef/resource/ruby_block.rb b/lib/chef/resource/ruby_block.rb
index d9b8954a90..a9cbf234cf 100644
--- a/lib/chef/resource/ruby_block.rb
+++ b/lib/chef/resource/ruby_block.rb
@@ -17,6 +17,9 @@
# limitations under the License.
#
+require 'chef/resource'
+require 'chef/provider/ruby_block'
+
class Chef
class Resource
class RubyBlock < Chef::Resource
diff --git a/lib/chef/resource/script.rb b/lib/chef/resource/script.rb
index ff7d23f075..479295922c 100644
--- a/lib/chef/resource/script.rb
+++ b/lib/chef/resource/script.rb
@@ -18,6 +18,7 @@
#
require 'chef/resource/execute'
+require 'chef/provider/script'
class Chef
class Resource
diff --git a/lib/chef/resource/service.rb b/lib/chef/resource/service.rb
index 4d64c3e3f4..36df7c859a 100644
--- a/lib/chef/resource/service.rb
+++ b/lib/chef/resource/service.rb
@@ -46,10 +46,6 @@ class Chef
@action = "nothing"
@supports = { :restart => false, :reload => false, :status => false }
@allowed_actions.push(:enable, :disable, :start, :stop, :restart, :reload)
-
- if(run_context && run_context.node[:init_package] == "systemd")
- @provider = Chef::Provider::Service::Systemd
- end
end
def service_name(arg=nil)
diff --git a/lib/chef/resource/smartos_package.rb b/lib/chef/resource/smartos_package.rb
index 0f4f6d8b0a..99b3b953b0 100644
--- a/lib/chef/resource/smartos_package.rb
+++ b/lib/chef/resource/smartos_package.rb
@@ -23,16 +23,15 @@ class Chef
class Resource
class SmartosPackage < Chef::Resource::Package
+ provides :smartos_package
+ provides :package, os: "solaris2", platform_family: "smartos"
+
def initialize(name, run_context=nil)
super
@resource_name = :smartos_package
- @provider = Chef::Provider::Package::SmartOS
end
end
end
end
-# Backwards compatability
-# @todo remove in Chef 12
-Chef::Resource::SmartOSPackage = Chef::Resource::SmartosPackage
diff --git a/lib/chef/resource/solaris_package.rb b/lib/chef/resource/solaris_package.rb
index 3513703076..94be4693b6 100644
--- a/lib/chef/resource/solaris_package.rb
+++ b/lib/chef/resource/solaris_package.rb
@@ -24,10 +24,16 @@ class Chef
class Resource
class SolarisPackage < Chef::Resource::Package
+ provides :solaris_package
+ provides :package, os: "solaris2", platform_family: "nexentacore"
+ provides :package, os: "solaris2", platform_family: "solaris2" do |node|
+ # on >= Solaris 11 we default to IPS packages instead
+ node[:platform_version].to_f <= 5.10
+ end
+
def initialize(name, run_context=nil)
super
@resource_name = :solaris_package
- @provider = Chef::Provider::Package::Solaris
end
end
diff --git a/lib/chef/resource/subversion.rb b/lib/chef/resource/subversion.rb
index 44158cb080..3afbe0baaf 100644
--- a/lib/chef/resource/subversion.rb
+++ b/lib/chef/resource/subversion.rb
@@ -28,7 +28,6 @@ class Chef
@svn_arguments = '--no-auth-cache'
@svn_info_args = '--no-auth-cache'
@resource_name = :subversion
- @provider = Chef::Provider::Subversion
allowed_actions << :force_export
end
diff --git a/lib/chef/resource/template.rb b/lib/chef/resource/template.rb
index 8473f5b677..8c9607ee07 100644
--- a/lib/chef/resource/template.rb
+++ b/lib/chef/resource/template.rb
@@ -27,7 +27,7 @@ class Chef
class Template < Chef::Resource::File
include Chef::Mixin::Securable
- provides :template, :on_platforms => :all
+ provides :template
attr_reader :inline_helper_blocks
attr_reader :inline_helper_modules
@@ -40,7 +40,6 @@ class Chef
@cookbook = nil
@local = false
@variables = Hash.new
- @provider = Chef::Provider::Template
@inline_helper_blocks = {}
@inline_helper_modules = []
@helper_modules = []
diff --git a/lib/chef/resource/timestamped_deploy.rb b/lib/chef/resource/timestamped_deploy.rb
index 4032ae9854..b2109db85c 100644
--- a/lib/chef/resource/timestamped_deploy.rb
+++ b/lib/chef/resource/timestamped_deploy.rb
@@ -18,13 +18,12 @@
class Chef
class Resource
-
# Convenience class for using the deploy resource with the timestamped
# deployment strategy (provider)
class TimestampedDeploy < Chef::Resource::Deploy
+ provides :timestamped_deploy
def initialize(*args, &block)
super(*args, &block)
- @provider = Chef::Provider::Deploy::Timestamped
end
end
end
diff --git a/lib/chef/resource/whyrun_safe_ruby_block.rb b/lib/chef/resource/whyrun_safe_ruby_block.rb
index ddb9d91dc3..6fa5383f5d 100644
--- a/lib/chef/resource/whyrun_safe_ruby_block.rb
+++ b/lib/chef/resource/whyrun_safe_ruby_block.rb
@@ -23,7 +23,6 @@ class Chef
def initialize(name, run_context=nil)
super
@resource_name = :whyrun_safe_ruby_block
- @provider = Chef::Provider::WhyrunSafeRubyBlock
end
end
diff --git a/lib/chef/resource/windows_package.rb b/lib/chef/resource/windows_package.rb
index 8bd41e0cb7..c563ba5fdc 100644
--- a/lib/chef/resource/windows_package.rb
+++ b/lib/chef/resource/windows_package.rb
@@ -24,12 +24,11 @@ class Chef
class Resource
class WindowsPackage < Chef::Resource::Package
- provides :package, :on_platforms => ["windows"]
+ provides :package, platform: "windows"
def initialize(name, run_context=nil)
super
@allowed_actions = [ :install, :remove ]
- @provider = Chef::Provider::Package::Windows
@resource_name = :windows_package
@source ||= source(@package_name)
@@ -76,4 +75,3 @@ class Chef
end
end
end
-
diff --git a/lib/chef/resource/windows_service.rb b/lib/chef/resource/windows_service.rb
index 5ed8e76cbd..49495117ee 100644
--- a/lib/chef/resource/windows_service.rb
+++ b/lib/chef/resource/windows_service.rb
@@ -25,7 +25,7 @@ class Chef
# Until #1773 is resolved, you need to manually specify the windows_service resource
# to use action :configure_startup and attribute startup_type
- # provides :service, :on_platforms => ["windows"]
+ provides :service, platform: "windows"
identity_attr :service_name
@@ -34,7 +34,6 @@ class Chef
def initialize(name, run_context=nil)
super
@resource_name = :windows_service
- @provider = Chef::Provider::Service::Windows
@allowed_actions.push(:configure_startup)
@startup_type = :automatic
end
diff --git a/lib/chef/resource/yum_package.rb b/lib/chef/resource/yum_package.rb
index dff70bcf62..8fbca9b097 100644
--- a/lib/chef/resource/yum_package.rb
+++ b/lib/chef/resource/yum_package.rb
@@ -23,10 +23,12 @@ class Chef
class Resource
class YumPackage < Chef::Resource::Package
+ provides :yum_package
+ provides :package, os: "linux", platform_family: [ "rhel", "fedora" ]
+
def initialize(name, run_context=nil)
super
@resource_name = :yum_package
- @provider = Chef::Provider::Package::Yum
@flush_cache = { :before => false, :after => false }
@allow_downgrade = false
end
diff --git a/lib/chef/resource_platform_map.rb b/lib/chef/resource_platform_map.rb
deleted file mode 100644
index a678f5be4b..0000000000
--- a/lib/chef/resource_platform_map.rb
+++ /dev/null
@@ -1,151 +0,0 @@
-#
-# Author:: Seth Chisamore (<schisamo@opscode.com>)
-# 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 'chef/mixin/params_validate'
-require 'chef/mixin/convert_to_class_name'
-
-class Chef
- class Resource
- class PlatformMap
-
- include Chef::Mixin::ParamsValidate
- include Chef::Mixin::ConvertToClassName
-
- attr_reader :map
-
- def initialize(map={:default => {}})
- @map = map
- end
-
- def filter(platform, version)
- resource_map = map[:default].clone
- platform_sym = platform
- if platform.kind_of?(String)
- platform.downcase!
- platform.gsub!(/\s/, "_")
- platform_sym = platform.to_sym
- end
-
- if map.has_key?(platform_sym)
- if map[platform_sym].has_key?(version)
- if map[platform_sym].has_key?(:default)
- resource_map.merge!(map[platform_sym][:default])
- end
- resource_map.merge!(map[platform_sym][version])
- elsif map[platform_sym].has_key?(:default)
- resource_map.merge!(map[platform_sym][:default])
- end
- end
- resource_map
- end
-
- def set(args)
- validate(
- args,
- {
- :platform => {
- :kind_of => Symbol,
- :required => false
- },
- :version => {
- :kind_of => String,
- :required => false
- },
- :short_name => {
- :kind_of => Symbol,
- :required => true
- },
- :resource => {
- :kind_of => [ String, Symbol, Class ],
- :required => true
- }
- }
- )
- if args.has_key?(:platform)
- if args.has_key?(:version)
- if map.has_key?(args[:platform])
- if map[args[:platform]].has_key?(args[:version])
- map[args[:platform]][args[:version]][args[:short_name].to_sym] = args[:resource]
- else
- map[args[:platform]][args[:version]] = {
- args[:short_name].to_sym => args[:resource]
- }
- end
- else
- map[args[:platform]] = {
- args[:version] => {
- args[:short_name].to_sym => args[:resource]
- }
- }
- end
- else
- if map.has_key?(args[:platform])
- if map[args[:platform]].has_key?(:default)
- map[args[:platform]][:default][args[:short_name].to_sym] = args[:resource]
- else
- map[args[:platform]] = { :default => { args[:short_name].to_sym => args[:resource] } }
- end
- else
- map[args[:platform]] = {
- :default => {
- args[:short_name].to_sym => args[:resource]
- }
- }
- end
- end
- else
- if map.has_key?(:default)
- map[:default][args[:short_name].to_sym] = args[:resource]
- else
- map[:default] = {
- args[:short_name].to_sym => args[:resource]
- }
- end
- end
- end
-
- def get(short_name, platform=nil, version=nil)
- resource_klass = platform_resource(short_name, platform, version) ||
- resource_matching_short_name(short_name)
-
- raise Exceptions::NoSuchResourceType, "Cannot find a resource for #{short_name} on #{platform} version #{version}" if resource_klass.nil?
-
- resource_klass
- end
-
- private
-
- def platform_resource(short_name, platform, version)
- pmap = filter(platform, version)
- rtkey = short_name.kind_of?(Chef::Resource) ? short_name.resource_name.to_sym : short_name
-
- pmap.has_key?(rtkey) ? pmap[rtkey] : nil
- end
-
- def resource_matching_short_name(short_name)
- begin
- rname = convert_to_class_name(short_name.to_s)
- Chef::Resource.const_get(rname)
- rescue NameError
- nil
- end
- end
-
- end
- end
-end
diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb
index 3564be62ff..18d353ac61 100644
--- a/lib/chef/run_context.rb
+++ b/lib/chef/run_context.rb
@@ -51,7 +51,8 @@ class Chef
# recipes, which is triggered by #load. (See also: CookbookCompiler)
attr_accessor :resource_collection
- attr_reader :provider_resolver
+ # Chef::ProviderResolver for this run
+ attr_accessor :provider_resolver
# A Hash containing the immediate notifications triggered by resources
# during the converge phase of the chef run.
@@ -94,7 +95,6 @@ class Chef
def load(run_list_expansion)
@cookbook_compiler = CookbookCompiler.new(self, run_list_expansion, events)
@cookbook_compiler.compile
- @provider_resolver.load
end
# Adds an immediate notification to the
diff --git a/lib/chef/runner.rb b/lib/chef/runner.rb
index 3467cfe717..6125fe59e1 100644
--- a/lib/chef/runner.rb
+++ b/lib/chef/runner.rb
@@ -43,10 +43,6 @@ class Chef
@run_context.events
end
- def provider_resolver
- @run_context.provider_resolver
- end
-
# Determine the appropriate provider for the given resource, then
# execute it.
def run_action(resource, action, notification_type=nil, notifying_resource=nil)
@@ -82,7 +78,6 @@ class Chef
# Execute each resource.
run_context.resource_collection.execute_each_resource do |resource|
- provider_resolver.resolve(resource)
Array(resource.action).each {|action| run_action(resource, action)}
end