diff options
author | lamont-granquist <lamont@scriptkiddie.org> | 2014-08-21 16:06:10 -0700 |
---|---|---|
committer | lamont-granquist <lamont@scriptkiddie.org> | 2014-08-21 16:06:10 -0700 |
commit | d77298ca37bcab1628ba0818c48293b4156a2e6a (patch) | |
tree | a54cce4ebc26097cc49cddccd018e67dcf5bfc18 | |
parent | 68c13b136a49b4e66cfe9d8aa2b5a85167b5bf9b (diff) | |
parent | 68ca480473ab4bcb302d003d40b9a76e39410268 (diff) | |
download | chef-d77298ca37bcab1628ba0818c48293b4156a2e6a.tar.gz |
Merge pull request #1884 from opscode/lcg/1726
Lcg/1726
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | DOC_CHANGES.md | 24 | ||||
-rw-r--r-- | RELEASE_NOTES.md | 17 | ||||
-rw-r--r-- | lib/chef/dsl/platform_introspection.rb | 42 | ||||
-rw-r--r-- | spec/support/shared/unit/platform_introspector.rb | 22 |
5 files changed, 107 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 072cacad34..2a48ab7255 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased: 12.0.0 +* [**Jordan Evans**](https://github.com/jordane): + support version constraints in value_for_platform * [**Yukihiko Sawanobori**](https://github.com/sawanoboly): Add environment resource attribute to scm resources * added Chef::ResourceCollection#insert_at API to the ResourceCollection diff --git a/DOC_CHANGES.md b/DOC_CHANGES.md index 1a40d6730f..7ce531b3b5 100644 --- a/DOC_CHANGES.md +++ b/DOC_CHANGES.md @@ -6,6 +6,29 @@ Example Doc Change: Description of the required change. --> +### value_for_platform Method + +- where <code>"platform"</code> can be a comma-separated list, each specifying a platform, such as Red Hat, openSUSE, or Fedora, <code>version</code> specifies the version of that platform, and <code>value</code> specifies the value that will be used if the node's platform matches the <code>value_for_platform</code> method. If each value only has a single platform, then the syntax is like the following: ++ where <code>platform</code> can be a comma-separated list, each specifying a platform, such as Red Hat, openSUSE, or Fedora, <code>version</code> specifies either the exact version of that platform, or a constraint to match the platform's version against. The following rules apply to constraint matches: + ++ * Exact matches take precedence no matter what, and should never throw exceptions. ++ * Matching multiple constraints raises a <code>RuntimeError</code>. ++ * The following constraints are allowed: <code><,<=,>,>=,~></code>. ++ ++ The following is an example of using the method with constraints: ++ ++ ```ruby ++ value_for_platform( ++ "os1" => { ++ "< 1.0" => "less than 1.0", ++ "~> 2.0" => "version 2.x", ++ ">= 3.0" => "version 3.0", ++ "3.0.1" => "3.0.1 will always use this value" } ++ ) ++ ``` + ++ If each value only has a single platform, then the syntax is like the following: + ### environment attribute to git provider Similar to other environment options: @@ -29,6 +52,7 @@ Current documentation states: This is no longer correct as of 12.0. The `name` field is required; if it is not specified, an error will be raised if it is not specified. + ### chef-zero port ranges - to avoid crashes, by default, Chef will now scan a port range and take the first available port from 8889-9999. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index c098445e48..7cb51fad42 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,22 @@ # Chef Client Release Notes 12.0.0: +## Version Constraints in value_for_platform + +The `value_for_platform` helper can now take version constraints like `>=` and `~>`. This is particularly useful for users +of RHEL 7 where the version numbers now look like `7.0.<buildnumber>`, so that they can do: + +```ruby +value_for_platform( + "redhat" => { + "~> 7.0" => "version 7.x.y" + ">= 8.0" => "version 8.0.0 and greater" + } +} +``` + +Note that if two version constraints match it is considered ambiguous and will raise an Exception. An exact match, however, will +always take precedence over a version constraint. + ## Git SCM provider now support environment attribute You can now pass in a hash of environment variables into the git provider: diff --git a/lib/chef/dsl/platform_introspection.rb b/lib/chef/dsl/platform_introspection.rb index 33aa451f30..2a52010a70 100644 --- a/lib/chef/dsl/platform_introspection.rb +++ b/lib/chef/dsl/platform_introspection.rb @@ -50,8 +50,12 @@ class Chef def value_for_node(node) platform, version = node[:platform].to_s, node[:platform_version].to_s + # Check if we match a version constraint via Chef::VersionConstraint and Chef::Version::Platform + matched_value = match_versions(node) if @values.key?(platform) && @values[platform].key?(version) @values[platform][version] + elsif matched_value + matched_value elsif @values.key?(platform) && @values[platform].key?("default") @values[platform]["default"] elsif @values.key?("default") @@ -63,6 +67,44 @@ class Chef private + def match_versions(node) + begin + platform, version = node[:platform].to_s, node[:platform_version].to_s + return nil unless @values.key?(platform) + node_version = Chef::Version::Platform.new(version) + key_matches = [] + keys = @values[platform].keys + keys.each do |k| + begin + if Chef::VersionConstraint.new(k).include?(node_version) + key_matches << k + end + rescue Chef::Exceptions::InvalidVersionConstraint => e + Chef::Log.debug "Caught InvalidVersionConstraint. This means that a key in value_for_platform cannot be interpreted as a Chef::VersionConstraint." + Chef::Log.debug(e) + end + end + return @values[platform][version] if key_matches.include?(version) + case key_matches.length + when 0 + return nil + when 1 + return @values[platform][key_matches.first] + else + raise "Multiple matches detected for #{platform} with values #{@values}. The matches are: #{key_matches}" + end + rescue Chef::Exceptions::InvalidCookbookVersion => e + # Lets not break because someone passes a weird string like 'default' :) + Chef::Log.debug(e) + Chef::Log.debug "InvalidCookbookVersion exceptions are common and expected here: the generic constraint matcher attempted to match something which is not a constraint. Moving on to next version or constraint" + return nil + rescue Chef::Exceptions::InvalidPlatformVersion => e + Chef::Log.debug "Caught InvalidPlatformVersion, this means that Chef::Version::Platform does not know how to turn #{node_version} into an x.y.z format" + Chef::Log.debug(e) + return nil + end + end + def set(platforms, value) if platforms.to_s == 'default' @values["default"] = value diff --git a/spec/support/shared/unit/platform_introspector.rb b/spec/support/shared/unit/platform_introspector.rb index d596e2984e..f76ddbdf9e 100644 --- a/spec/support/shared/unit/platform_introspector.rb +++ b/spec/support/shared/unit/platform_introspector.rb @@ -29,6 +29,10 @@ shared_examples_for "a platform introspector" do end @platform_hash["debian"] = {["5", "6"] => "debian-5/6", "default" => "debian"} @platform_hash["default"] = "default" + # The following @platform_hash keys are used for testing version constraints + @platform_hash['exact_match'] = { '1.2.3' => 'exact', '>= 1.0' => 'not exact'} + @platform_hash['multiple_matches'] = { '~> 2.3.4' => 'matched ~> 2.3.4', '>= 2.3' => 'matched >=2.3' } + @platform_hash['successful_matches'] = { '< 3.0' => 'matched < 3.0', '>= 3.0' => 'matched >= 3.0' } @platform_family_hash = { "debian" => "debian value", @@ -79,6 +83,24 @@ shared_examples_for "a platform introspector" do platform_introspector.value_for_platform(@platform_hash).should == "openbsd" end + it 'returns the exact match' do + node.automatic_attrs[:platform] = 'exact_match' + node.automatic_attrs[:platform_version] = '1.2.3' + platform_introspector.value_for_platform(@platform_hash).should == 'exact' + end + + it 'raises RuntimeError' do + node.automatic_attrs[:platform] = 'multiple_matches' + node.automatic_attrs[:platform_version] = '2.3.4' + expect {platform_introspector.value_for_platform(@platform_hash)}.to raise_error(RuntimeError) + end + + it 'should return the value for that match' do + node.automatic_attrs[:platform] = 'successful_matches' + node.automatic_attrs[:platform_version] = '2.9' + platform_introspector.value_for_platform(@platform_hash).should == 'matched < 3.0' + end + describe "when platform versions is an array" do it "returns a version-specific value based on the current platform" do node.automatic_attrs[:platform] = "debian" |