diff options
Diffstat (limited to 'lib/chef/platform.rb')
-rw-r--r-- | lib/chef/platform.rb | 499 |
1 files changed, 499 insertions, 0 deletions
diff --git a/lib/chef/platform.rb b/lib/chef/platform.rb new file mode 100644 index 0000000000..2cb6690da1 --- /dev/null +++ b/lib/chef/platform.rb @@ -0,0 +1,499 @@ +# +# Author:: Adam Jacob (<adam@opscode.com>) +# Copyright:: Copyright (c) 2008 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/config' +require 'chef/log' +require 'chef/mixin/params_validate' + +# Actually, this file depends on nearly every provider in chef, but actually +# requiring them causes circular requires resulting in uninitialized constant +# errors. +require 'chef/provider' +require 'chef/provider/log' +require 'chef/provider/user' +require 'chef/provider/group' +require 'chef/provider/mount' +require 'chef/provider/service' +require 'chef/provider/package' + + +class Chef + class Platform + + class << self + attr_writer :platforms + + def platforms + @platforms ||= { + :mac_os_x => { + :default => { + :package => Chef::Provider::Package::Macports, + :service => Chef::Provider::Service::Macosx, + :user => Chef::Provider::User::Dscl, + :group => Chef::Provider::Group::Dscl + } + }, + :mac_os_x_server => { + :default => { + :package => Chef::Provider::Package::Macports, + :service => Chef::Provider::Service::Macosx, + :user => Chef::Provider::User::Dscl, + :group => Chef::Provider::Group::Dscl + } + }, + :freebsd => { + :default => { + :group => Chef::Provider::Group::Pw, + :package => Chef::Provider::Package::Freebsd, + :service => Chef::Provider::Service::Freebsd, + :user => Chef::Provider::User::Pw, + :cron => Chef::Provider::Cron + } + }, + :ubuntu => { + :default => { + :package => Chef::Provider::Package::Apt, + :service => Chef::Provider::Service::Debian, + :cron => Chef::Provider::Cron, + :mdadm => Chef::Provider::Mdadm + } + }, + :linaro => { + :default => { + :package => Chef::Provider::Package::Apt, + :service => Chef::Provider::Service::Debian, + :cron => Chef::Provider::Cron, + :mdadm => Chef::Provider::Mdadm + } + }, + :linuxmint => { + :default => { + :package => Chef::Provider::Package::Apt, + :service => Chef::Provider::Service::Upstart, + :cron => Chef::Provider::Cron, + :mdadm => Chef::Provider::Mdadm + } + }, + :debian => { + :default => { + :package => Chef::Provider::Package::Apt, + :service => Chef::Provider::Service::Debian, + :cron => Chef::Provider::Cron, + :mdadm => Chef::Provider::Mdadm + }, + "6.0" => { + :service => Chef::Provider::Service::Insserv + } + }, + :xenserver => { + :default => { + :service => Chef::Provider::Service::Redhat, + :cron => Chef::Provider::Cron, + :package => Chef::Provider::Package::Yum, + :mdadm => Chef::Provider::Mdadm + } + }, + :centos => { + :default => { + :service => Chef::Provider::Service::Redhat, + :cron => Chef::Provider::Cron, + :package => Chef::Provider::Package::Yum, + :mdadm => Chef::Provider::Mdadm + } + }, + :amazon => { + :default => { + :service => Chef::Provider::Service::Redhat, + :cron => Chef::Provider::Cron, + :package => Chef::Provider::Package::Yum, + :mdadm => Chef::Provider::Mdadm + } + }, + :scientific => { + :default => { + :service => Chef::Provider::Service::Redhat, + :cron => Chef::Provider::Cron, + :package => Chef::Provider::Package::Yum, + :mdadm => Chef::Provider::Mdadm + } + }, + :fedora => { + :default => { + :service => Chef::Provider::Service::Redhat, + :cron => Chef::Provider::Cron, + :package => Chef::Provider::Package::Yum, + :mdadm => Chef::Provider::Mdadm + } + }, + :suse => { + :default => { + :service => Chef::Provider::Service::Redhat, + :cron => Chef::Provider::Cron, + :package => Chef::Provider::Package::Zypper, + :group => Chef::Provider::Group::Suse + } + }, + :oracle => { + :default => { + :service => Chef::Provider::Service::Redhat, + :cron => Chef::Provider::Cron, + :package => Chef::Provider::Package::Yum, + :mdadm => Chef::Provider::Mdadm + } + }, + :redhat => { + :default => { + :service => Chef::Provider::Service::Redhat, + :cron => Chef::Provider::Cron, + :package => Chef::Provider::Package::Yum, + :mdadm => Chef::Provider::Mdadm + } + }, + :gentoo => { + :default => { + :package => Chef::Provider::Package::Portage, + :service => Chef::Provider::Service::Gentoo, + :cron => Chef::Provider::Cron, + :mdadm => Chef::Provider::Mdadm + } + }, + :arch => { + :default => { + :package => Chef::Provider::Package::Pacman, + :service => Chef::Provider::Service::Arch, + :cron => Chef::Provider::Cron, + :mdadm => Chef::Provider::Mdadm + } + }, + :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 + } + }, + :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 + } + }, + :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 + } + }, + :solaris => {}, + :openindiana => { + :default => { + :service => Chef::Provider::Service::Solaris, + :package => Chef::Provider::Package::Ips, + :cron => Chef::Provider::Cron::Solaris, + :group => Chef::Provider::Group::Usermod + } + }, + :opensolaris => { + :default => { + :service => Chef::Provider::Service::Solaris, + :package => Chef::Provider::Package::Ips, + :cron => Chef::Provider::Cron::Solaris, + :group => Chef::Provider::Group::Usermod + } + }, + :nexentacore => { + :default => { + :service => Chef::Provider::Service::Solaris, + :package => Chef::Provider::Package::Solaris, + :cron => Chef::Provider::Cron::Solaris, + :group => Chef::Provider::Group::Usermod + } + }, + :omnios => { + :default => { + :service => Chef::Provider::Service::Solaris, + :package => Chef::Provider::Package::Ips, + :cron => Chef::Provider::Cron::Solaris, + :group => Chef::Provider::Group::Usermod + } + }, + :solaris2 => { + :default => { + :service => Chef::Provider::Service::Solaris, + :package => Chef::Provider::Package::Ips, + :cron => Chef::Provider::Cron::Solaris, + :group => Chef::Provider::Group::Usermod + }, + "5.9" => { + :service => Chef::Provider::Service::Solaris, + :package => Chef::Provider::Package::Solaris, + :cron => Chef::Provider::Cron::Solaris, + :group => Chef::Provider::Group::Usermod + }, + "5.10" => { + :service => Chef::Provider::Service::Solaris, + :package => Chef::Provider::Package::Solaris, + :cron => Chef::Provider::Cron::Solaris, + :group => Chef::Provider::Group::Usermod + } + }, + :smartos => { + :default => { + :service => Chef::Provider::Service::Solaris, + :package => Chef::Provider::Package::SmartOS, + :cron => Chef::Provider::Cron::Solaris, + :group => Chef::Provider::Group::Usermod + } + }, + :netbsd => { + :default => { + :service => Chef::Provider::Service::Freebsd, + :group => Chef::Provider::Group::Groupmod + } + }, + :openbsd => { + :default => { + :group => Chef::Provider::Group::Usermod + } + }, + :hpux => { + :default => { + :group => Chef::Provider::Group::Usermod + } + }, + :aix => { + :default => { + :group => Chef::Provider::Group::Aix + } + }, + :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, + :erl_call => Chef::Provider::ErlCall, + :log => Chef::Provider::Log::ChefLog + } + } + end + + include Chef::Mixin::ParamsValidate + + def find(name, version) + provider_map = platforms[:default].clone + + name_sym = name + if name.kind_of?(String) + name.downcase! + name.gsub!(/\s/, "_") + name_sym = name.to_sym + end + + if platforms.has_key?(name_sym) + if platforms[name_sym].has_key?(version) + Chef::Log.debug("Platform #{name.to_s} version #{version} found") + if platforms[name_sym].has_key?(:default) + provider_map.merge!(platforms[name_sym][:default]) + end + provider_map.merge!(platforms[name_sym][version]) + elsif platforms[name_sym].has_key?(:default) + provider_map.merge!(platforms[name_sym][:default]) + end + else + Chef::Log.debug("Platform #{name} not found, using all defaults. (Unsupported platform?)") + end + provider_map + end + + def find_platform_and_version(node) + platform = nil + version = nil + + if node[:platform] + platform = node[:platform] + elsif node.attribute?("os") + platform = node[:os] + end + + raise ArgumentError, "Cannot find a platform for #{node}" unless platform + + if node[:platform_version] + version = node[:platform_version] + elsif node[:os_version] + version = node[:os_version] + elsif node[:os_release] + version = node[:os_release] + end + + raise ArgumentError, "Cannot find a version for #{node}" unless version + + return platform, version + end + + def provider_for_resource(resource, action=:nothing) + node = resource.run_context && resource.run_context.node + raise ArgumentError, "Cannot find the provider for a resource with no run context set" unless node + provider = find_provider_for_node(node, resource).new(resource, resource.run_context) + provider.action = action + provider + end + + def provider_for_node(node, resource_type) + raise NotImplementedError, "#{self.class.name} no longer supports #provider_for_node" + find_provider_for_node(node, resource_type).new(node, resource_type) + end + + def find_provider_for_node(node, resource_type) + platform, version = find_platform_and_version(node) + provider = find_provider(platform, version, resource_type) + end + + def set(args) + validate( + args, + { + :platform => { + :kind_of => Symbol, + :required => false, + }, + :version => { + :kind_of => String, + :required => false, + }, + :resource => { + :kind_of => Symbol, + }, + :provider => { + :kind_of => [ String, Symbol, Class ], + } + } + ) + if args.has_key?(:platform) + if args.has_key?(:version) + if platforms.has_key?(args[:platform]) + if platforms[args[:platform]].has_key?(args[:version]) + platforms[args[:platform]][args[:version]][args[:resource].to_sym] = args[:provider] + else + platforms[args[:platform]][args[:version]] = { + args[:resource].to_sym => args[:provider] + } + end + else + platforms[args[:platform]] = { + args[:version] => { + args[:resource].to_sym => args[:provider] + } + } + end + else + if platforms.has_key?(args[:platform]) + if platforms[args[:platform]].has_key?(:default) + platforms[args[:platform]][:default][args[:resource].to_sym] = args[:provider] + else + platforms[args[:platform]] = { :default => { args[:resource].to_sym => args[:provider] } } + end + else + platforms[args[:platform]] = { + :default => { + args[:resource].to_sym => args[:provider] + } + } + end + end + else + if platforms.has_key?(:default) + platforms[:default][args[:resource].to_sym] = args[:provider] + else + platforms[:default] = { + args[:resource].to_sym => args[:provider] + } + end + end + end + + def find_provider(platform, version, resource_type) + pmap = Chef::Platform.find(platform, version) + provider_klass = explicit_provider(platform, version, resource_type) || + platform_provider(platform, version, resource_type) || + resource_matching_provider(platform, version, resource_type) + + raise ArgumentError, "Cannot find a provider for #{resource_type} on #{platform} version #{version}" if provider_klass.nil? + + provider_klass + end + + def windows? + if RUBY_PLATFORM =~ /mswin|mingw|windows/ + true + else + false + end + end + + private + + def explicit_provider(platform, version, resource_type) + resource_type.kind_of?(Chef::Resource) ? resource_type.provider : nil + end + + def platform_provider(platform, version, resource_type) + pmap = Chef::Platform.find(platform, version) + rtkey = resource_type.kind_of?(Chef::Resource) ? resource_type.resource_name.to_sym : resource_type + pmap.has_key?(rtkey) ? pmap[rtkey] : nil + end + + def resource_matching_provider(platform, version, resource_type) + if resource_type.kind_of?(Chef::Resource) + begin + Chef::Provider.const_get(resource_type.class.to_s.split('::').last) + rescue NameError + nil + end + else + nil + end + end + + end + + end +end |