lib/chef/mixin/language.rb in chef-0.9.6 vs lib/chef/mixin/language.rb in chef-0.9.8.beta.1
- old
+ new
@@ -22,42 +22,83 @@
class Chef
module Mixin
module Language
+ # Implementation class for determining platform dependent values
+ class PlatformDependentValue
+
+ # Create a platform dependent value object.
+ # === Arguments
+ # platform_hash (Hash) a hash of the same structure as Chef::Platform,
+ # like this:
+ # {
+ # :debian => {:default => 'the value for all debian'}
+ # [:centos, :redhat, :fedora] => {:default => "value for all EL variants"}
+ # :ubuntu => { :default => "default for ubuntu", '10.04' => "value for 10.04 only"},
+ # :default => "the default when nothing else matches"
+ # }
+ # * platforms can be specified as Symbols or Strings
+ # * multiple platforms can be grouped by using an Array as the key
+ # * values for platforms need to be Hashes of the form:
+ # {platform_version => value_for_that_version}
+ # * the exception to the above is the default value, which is given as
+ # :default => default_value
+ def initialize(platform_hash)
+ @values = {}
+ platform_hash.each { |platforms, value| set(platforms, value)}
+ end
+
+ def value_for_node(node)
+ platform, version = node[:platform].to_s, node[:platform_version].to_s
+ if @values.key?(platform) && @values[platform].key?(version)
+ @values[platform][version]
+ elsif @values.key?(platform) && @values[platform].key?("default")
+ @values[platform]["default"]
+ elsif @values.key?("default")
+ @values["default"]
+ else
+ nil
+ end
+ end
+
+ private
+
+ def set(platforms, value)
+ if platforms.to_s == 'default'
+ @values["default"] = value
+ else
+ assert_valid_platform_values!(platforms, value)
+ Array(platforms).each { |platform| @values[platform.to_s] = format_values(value)}
+ value
+ end
+ end
+
+ def format_values(hash)
+ formatted_array = hash.map { |key, value| [key.to_s, value]}.flatten
+ Hash[*formatted_array]
+ end
+
+ def assert_valid_platform_values!(platforms, value)
+ unless value.kind_of?(Hash)
+ msg = "platform dependent values must be specified in the format :platform => {:version => value} "
+ msg << "you gave a value #{value.inspect} for platform(s) #{platforms}"
+ raise ArgumentError, msg
+ end
+ end
+ end
+
# Given a hash similar to the one we use for Platforms, select a value from the hash. Supports
# per platform defaults, along with a single base default. Arrays may be passed as hash keys and
# will be expanded.
#
# === Parameters
# platform_hash:: A platform-style hash.
#
# === Returns
# value:: Whatever the most specific value of the hash is.
def value_for_platform(platform_hash)
- result = nil
-
- platform_hash.each_pair do |key, value|
- if key.is_a?(Array)
- key.each { |array_key| platform_hash[array_key] = value }
- platform_hash.delete(key)
- end
- end
- if platform_hash.has_key?(node[:platform])
- if platform_hash[node[:platform]].has_key?(node[:platform_version])
- result = platform_hash[node[:platform]][node[:platform_version]]
- elsif platform_hash[node[:platform]].has_key?("default")
- result = platform_hash[node[:platform]]["default"]
- end
- end
-
- unless result
- if platform_hash.has_key?("default")
- result = platform_hash["default"]
- end
- end
-
- result
+ PlatformDependentValue.new(platform_hash).value_for_node(node)
end
# Given a list of platforms, returns true if the current recipe is being run on a node with
# that platform, false otherwise.
#