summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlamont-granquist <lamont@scriptkiddie.org>2014-08-21 16:06:10 -0700
committerlamont-granquist <lamont@scriptkiddie.org>2014-08-21 16:06:10 -0700
commitd77298ca37bcab1628ba0818c48293b4156a2e6a (patch)
treea54cce4ebc26097cc49cddccd018e67dcf5bfc18
parent68c13b136a49b4e66cfe9d8aa2b5a85167b5bf9b (diff)
parent68ca480473ab4bcb302d003d40b9a76e39410268 (diff)
downloadchef-d77298ca37bcab1628ba0818c48293b4156a2e6a.tar.gz
Merge pull request #1884 from opscode/lcg/1726
Lcg/1726
-rw-r--r--CHANGELOG.md2
-rw-r--r--DOC_CHANGES.md24
-rw-r--r--RELEASE_NOTES.md17
-rw-r--r--lib/chef/dsl/platform_introspection.rb42
-rw-r--r--spec/support/shared/unit/platform_introspector.rb22
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"