summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2015-10-28 10:33:14 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2015-10-28 10:33:14 -0700
commit6a306c0847d2738dcc3656318ebccff5888fe25c (patch)
tree890ef90159b4d5262314d5111fe05e1c5afd088d
parentcc51b2f0504a32d7e55d2c445f22baf9ed30b031 (diff)
parenta75ce7ce4c5ee9565f536430244a37bc33cd4e59 (diff)
downloadchef-6a306c0847d2738dcc3656318ebccff5888fe25c.tar.gz
Merge pull request #4081 from chef/lcg/chef-version
RFC-037: add chef_version and ohai_version metadata
-rw-r--r--lib/chef/cookbook/cookbook_collection.rb15
-rw-r--r--lib/chef/cookbook/metadata.rb124
-rw-r--r--lib/chef/exceptions.rb16
-rw-r--r--lib/chef/policy_builder/expand_node_object.rb2
-rw-r--r--lib/chef/policy_builder/policyfile.rb1
-rw-r--r--spec/integration/client/client_spec.rb20
-rw-r--r--spec/integration/knife/upload_spec.rb29
-rw-r--r--spec/integration/solo/solo_spec.rb34
-rw-r--r--spec/unit/cookbook/metadata_spec.rb124
-rw-r--r--spec/unit/policy_builder/policyfile_spec.rb2
10 files changed, 353 insertions, 14 deletions
diff --git a/lib/chef/cookbook/cookbook_collection.rb b/lib/chef/cookbook/cookbook_collection.rb
index ae63abfc93..38784c22fa 100644
--- a/lib/chef/cookbook/cookbook_collection.rb
+++ b/lib/chef/cookbook/cookbook_collection.rb
@@ -1,7 +1,7 @@
#--
# Author:: Tim Hinderliter (<tim@opscode.com>)
# Author:: Christopher Walters (<cw@opscode.com>)
-# Copyright:: Copyright (c) 2010 Opscode, Inc.
+# Copyright:: Copyright (c) 2010-2015 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -41,5 +41,18 @@ class Chef
cookbook_versions.each{ |cookbook_name, cookbook_version| self[cookbook_name] = cookbook_version }
end
+ # Validates that the cookbook metadata allows it to run on this instance.
+ #
+ # Currently checks chef_version and ohai_version in the cookbook metadata
+ # against the running Chef::VERSION and Ohai::VERSION.
+ #
+ # @raises [Chef::Exceptions::CookbookChefVersionMismatch] if the Chef::VERSION fails validation
+ # @raises [Chef::Exceptions::CookbookOhaiVersionMismatch] if the Ohai::VERSION fails validation
+ def validate!
+ each do |cookbook_name, cookbook_version|
+ cookbook_version.metadata.validate_chef_version!
+ cookbook_version.metadata.validate_ohai_version!
+ end
+ end
end
end
diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb
index 9822920a7d..e9509be38c 100644
--- a/lib/chef/cookbook/metadata.rb
+++ b/lib/chef/cookbook/metadata.rb
@@ -2,7 +2,7 @@
# Author:: Adam Jacob (<adam@opscode.com>)
# Author:: AJ Christensen (<aj@opscode.com>)
# Author:: Seth Falcon (<seth@opscode.com>)
-# Copyright:: Copyright 2008-2010 Opscode, Inc.
+# Copyright:: Copyright 2008-2015 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -55,19 +55,23 @@ class Chef
SOURCE_URL = 'source_url'.freeze
ISSUES_URL = 'issues_url'.freeze
PRIVACY = 'privacy'.freeze
+ CHEF_VERSIONS = 'chef_versions'.freeze
+ OHAI_VERSIONS = 'ohai_versions'.freeze
COMPARISON_FIELDS = [ :name, :description, :long_description, :maintainer,
:maintainer_email, :license, :platforms, :dependencies,
:recommendations, :suggestions, :conflicting, :providing,
:replacing, :attributes, :groupings, :recipes, :version,
- :source_url, :issues_url, :privacy ]
+ :source_url, :issues_url, :privacy, :chef_versions, :ohai_versions ]
- VERSION_CONSTRAINTS = {:depends => DEPENDENCIES,
- :recommends => RECOMMENDATIONS,
- :suggests => SUGGESTIONS,
- :conflicts => CONFLICTING,
- :provides => PROVIDING,
- :replaces => REPLACING }
+ VERSION_CONSTRAINTS = {:depends => DEPENDENCIES,
+ :recommends => RECOMMENDATIONS,
+ :suggests => SUGGESTIONS,
+ :conflicts => CONFLICTING,
+ :provides => PROVIDING,
+ :replaces => REPLACING,
+ :chef_version => CHEF_VERSIONS,
+ :ohai_version => OHAI_VERSIONS }
include Chef::Mixin::ParamsValidate
include Chef::Mixin::FromFile
@@ -84,6 +88,11 @@ class Chef
attr_reader :recipes
attr_reader :version
+ # @return [Array<Gem::Dependency>] Array of supported Chef versions
+ attr_reader :chef_versions
+ # @return [Array<Gem::Dependency>] Array of supported Ohai versions
+ attr_reader :ohai_versions
+
# Builds a new Chef::Cookbook::Metadata object.
#
# === Parameters
@@ -118,6 +127,8 @@ class Chef
@source_url = ''
@issues_url = ''
@privacy = false
+ @chef_versions = []
+ @ohai_versions = []
@errors = []
end
@@ -386,6 +397,28 @@ class Chef
@replacing[cookbook]
end
+ # Metadata DSL to set a valid chef_version. May be declared multiple times
+ # with the result being 'OR'd such that if any statements match, the version
+ # is considered supported. Uses Gem::Requirement for its implementation.
+ #
+ # @param version_args [Array<String>] Version constraint in String form
+ # @return [Array<Gem::Dependency>] Current chef_versions array
+ def chef_version(*version_args)
+ @chef_versions << Gem::Dependency.new('chef', *version_args) unless version_args.empty?
+ @chef_versions
+ end
+
+ # Metadata DSL to set a valid ohai_version. May be declared multiple times
+ # with the result being 'OR'd such that if any statements match, the version
+ # is considered supported. Uses Gem::Requirement for its implementation.
+ #
+ # @param version_args [Array<String>] Version constraint in String form
+ # @return [Array<Gem::Dependency>] Current ohai_versions array
+ def ohai_version(*version_args)
+ @ohai_versions << Gem::Dependency.new('ohai', *version_args) unless version_args.empty?
+ @ohai_versions
+ end
+
# Adds a description for a recipe.
#
# === Parameters
@@ -481,6 +514,40 @@ class Chef
@groupings[name]
end
+ # Convert an Array of Gem::Dependency objects (chef_version/ohai_version) to an Array.
+ #
+ # Gem::Dependencey#to_s is not useful, and there is no #to_json defined on it or its component
+ # objets, so we have to write our own rendering method.
+ #
+ # [ Gem::Dependency.new(">= 12.5"), Gem::Dependency.new(">= 11.18.0", "< 12.0") ]
+ #
+ # results in:
+ #
+ # [ [ ">= 12.5" ], [ ">= 11.18.0", "< 12.0" ] ]
+ #
+ # @param deps [Array<Gem::Dependency>] Multiple Gem-style version constraints
+ # @return [Array<Array<String>]] Simple object representation of version constraints (for json)
+ def gem_requirements_to_array(*deps)
+ deps.map do |dep|
+ dep.requirement.requirements.map do |op, version|
+ "#{op} #{version}"
+ end.sort
+ end
+ end
+
+ # Convert an Array of Gem::Dependency objects (chef_version/ohai_version) to a hash.
+ #
+ # This is the inverse of #gem_requirements_to_array
+ #
+ # @param what [String] What version constraint we are constructing ('chef' or 'ohai' presently)
+ # @param array [Array<Array<String>]] Simple object representation of version constraints (from json)
+ # @return [Array<Gem::Dependency>] Multiple Gem-style version constraints
+ def gem_requirements_from_array(what, array)
+ array.map do |dep|
+ Gem::Dependency.new(what, *dep)
+ end
+ end
+
def to_hash
{
NAME => self.name,
@@ -502,7 +569,9 @@ class Chef
VERSION => self.version,
SOURCE_URL => self.source_url,
ISSUES_URL => self.issues_url,
- PRIVACY => self.privacy
+ PRIVACY => self.privacy,
+ CHEF_VERSIONS => gem_requirements_to_array(*self.chef_versions),
+ OHAI_VERSIONS => gem_requirements_to_array(*self.ohai_versions)
}
end
@@ -537,6 +606,8 @@ class Chef
@source_url = o[SOURCE_URL] if o.has_key?(SOURCE_URL)
@issues_url = o[ISSUES_URL] if o.has_key?(ISSUES_URL)
@privacy = o[PRIVACY] if o.has_key?(PRIVACY)
+ @chef_versions = gem_requirements_from_array("chef", o[CHEF_VERSIONS]) if o.has_key?(CHEF_VERSIONS)
+ @ohai_versions = gem_requirements_from_array("ohai", o[OHAI_VERSIONS]) if o.has_key?(OHAI_VERSIONS)
self
end
@@ -612,8 +683,43 @@ class Chef
)
end
+ # Validates that the Ohai::VERSION of the running chef-client matches one of the
+ # configured ohai_version statements in this cookbooks metadata.
+ #
+ # @raises [Chef::Exceptions::CookbookOhaiVersionMismatch] if the cookbook fails validation
+ def validate_ohai_version!
+ unless gem_dep_matches?("ohai", Gem::Version.new(Ohai::VERSION), *ohai_versions)
+ raise Exceptions::CookbookOhaiVersionMismatch.new(Ohai::VERSION, name, version, *ohai_versions)
+ end
+ end
+
+ # Validates that the Chef::VERSION of the running chef-client matches one of the
+ # configured chef_version statements in this cookbooks metadata.
+ #
+ # @raises [Chef::Exceptions::CookbookChefVersionMismatch] if the cookbook fails validation
+ def validate_chef_version!
+ unless gem_dep_matches?("chef", Gem::Version.new(Chef::VERSION), *chef_versions)
+ raise Exceptions::CookbookChefVersionMismatch.new(Chef::VERSION, name, version, *chef_versions)
+ end
+ end
+
private
+ # Helper to match a gem style version (ohai_version/chef_version) against a set of
+ # Gem::Dependency version constraints. If none are present, it always matches. if
+ # multiple are present, one must match. Returns false if none matches.
+ #
+ # @param what [String] the name of the constraint (e.g. 'chef' or 'ohai')
+ # @param version [String] the version to compare against the constraints
+ # @param deps [Array<Gem::Dependency>] Multiple Gem-style version constraints
+ # @return [Boolean] true if no constraints or a match, false if no match
+ def gem_dep_matches?(what, version, *deps)
+ # always match if we have no chef_version at all
+ return true unless deps.length > 0
+ # match if we match any of the chef_version lines
+ deps.any? { |dep| dep.match?(what, version) }
+ end
+
def run_validation
if name.nil?
@errors = ["The `name' attribute is required in cookbook metadata"]
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb
index 855c86d9cc..8172311dd6 100644
--- a/lib/chef/exceptions.rb
+++ b/lib/chef/exceptions.rb
@@ -2,7 +2,7 @@
# Author:: Adam Jacob (<adam@opscode.com>)
# Author:: Seth Falcon (<seth@opscode.com>)
# Author:: Kyle Goodwin (<kgoodwin@primerevenue.com>)
-# Copyright:: Copyright 2008-2010 Opscode, Inc.
+# Copyright:: Copyright 2008-2015 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -482,6 +482,20 @@ class Chef
end
end
+ class CookbookChefVersionMismatch < RuntimeError
+ def initialize(chef_version, cookbook_name, cookbook_version, *constraints)
+ constraint_str = constraints.map { |c| c.requirement.as_list.to_s }.join(', ')
+ super "Cookbook '#{cookbook_name}' version '#{cookbook_version}' depends on chef version #{constraint_str}, but the running chef version is #{chef_version}"
+ end
+ end
+
+ class CookbookOhaiVersionMismatch < RuntimeError
+ def initialize(ohai_version, cookbook_name, cookbook_version, *constraints)
+ constraint_str = constraints.map { |c| c.requirement.as_list.to_s }.join(', ')
+ super "Cookbook '#{cookbook_name}' version '#{cookbook_version}' depends on ohai version #{constraint_str}, but the running ohai version is #{ohai_version}"
+ end
+ end
+
class MultipleDscResourcesFound < RuntimeError
attr_reader :resources_found
def initialize(resources_found)
diff --git a/lib/chef/policy_builder/expand_node_object.rb b/lib/chef/policy_builder/expand_node_object.rb
index 2c6d644e42..848dd00684 100644
--- a/lib/chef/policy_builder/expand_node_object.rb
+++ b/lib/chef/policy_builder/expand_node_object.rb
@@ -74,11 +74,13 @@ class Chef
cl = Chef::CookbookLoader.new(Chef::Config[:cookbook_path])
cl.load_cookbooks
cookbook_collection = Chef::CookbookCollection.new(cl)
+ cookbook_collection.validate!
run_context = Chef::RunContext.new(node, cookbook_collection, @events)
else
Chef::Cookbook::FileVendor.fetch_from_remote(api_service)
cookbook_hash = sync_cookbooks
cookbook_collection = Chef::CookbookCollection.new(cookbook_hash)
+ cookbook_collection.validate!
run_context = Chef::RunContext.new(node, cookbook_collection, @events)
end
diff --git a/lib/chef/policy_builder/policyfile.rb b/lib/chef/policy_builder/policyfile.rb
index d6dcdf67b2..3633110d6c 100644
--- a/lib/chef/policy_builder/policyfile.rb
+++ b/lib/chef/policy_builder/policyfile.rb
@@ -153,6 +153,7 @@ class Chef
Chef::Cookbook::FileVendor.fetch_from_remote(http_api)
sync_cookbooks
cookbook_collection = Chef::CookbookCollection.new(cookbooks_to_sync)
+ cookbook_collection.validate!
run_context = Chef::RunContext.new(node, cookbook_collection, events)
setup_chef_class(run_context)
diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb
index 314a9310be..41645adb9e 100644
--- a/spec/integration/client/client_spec.rb
+++ b/spec/integration/client/client_spec.rb
@@ -320,6 +320,26 @@ EOM
end
end
+ when_the_repository "has a cookbook that should fail chef_version checks" do
+ before do
+ file 'cookbooks/x/recipes/default.rb', ''
+ file 'cookbooks/x/metadata.rb', <<EOM
+name 'x'
+version '0.0.1'
+chef_version '~> 999.99'
+EOM
+ file 'config/client.rb', <<EOM
+local_mode true
+cookbook_path "#{path_to('cookbooks')}"
+EOM
+ end
+ it "should fail the chef client run" do
+ command = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork", :cwd => chef_dir)
+ expect(command.exitstatus).to eql(1)
+ expect(command.stdout).to match(/Chef::Exceptions::CookbookChefVersionMismatch/)
+ end
+ end
+
when_the_repository "has a cookbook that generates deprecation warnings" do
before do
file 'cookbooks/x/recipes/default.rb', <<-EOM
diff --git a/spec/integration/knife/upload_spec.rb b/spec/integration/knife/upload_spec.rb
index 6ca8c3d8ce..d72cbb82f5 100644
--- a/spec/integration/knife/upload_spec.rb
+++ b/spec/integration/knife/upload_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: John Keiser (<jkeiser@opscode.com>)
-# Copyright:: Copyright (c) 2013 Opscode, Inc.
+# Copyright:: Copyright (c) 2013-2015 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -699,6 +699,19 @@ EOH
end
end
end
+ when_the_chef_server "is empty" do
+ when_the_repository 'has a cookbook with an invalid chef_version constraint in it' do
+ before do
+ file 'cookbooks/x/metadata.rb', cb_metadata('x', '1.0.0', "\nchef_version '~> 999.0'")
+ end
+ it 'knife upload succeeds' do
+ knife('upload /cookbooks/x').should_succeed <<EOM
+Created /cookbooks/x
+EOM
+ knife('diff --name-status /cookbooks').should_succeed ''
+ end
+ end
+ end
end # without versioned cookbooks
with_versioned_cookbooks do
@@ -1219,6 +1232,20 @@ EOM
end
end
end
+
+ when_the_chef_server "is empty" do
+ when_the_repository 'has a cookbook with an invalid chef_version constraint in it' do
+ before do
+ file 'cookbooks/x-1.0.0/metadata.rb', cb_metadata('x', '1.0.0', "\nchef_version '~> 999.0'")
+ end
+ it 'knife upload succeeds' do
+ knife('upload /cookbooks/x-1.0.0').should_succeed <<EOM
+Created /cookbooks/x-1.0.0
+EOM
+ knife('diff --name-status /cookbooks').should_succeed ''
+ end
+ end
+ end
end # with versioned cookbooks
when_the_chef_server 'has a user' do
diff --git a/spec/integration/solo/solo_spec.rb b/spec/integration/solo/solo_spec.rb
index f45933c799..6240a38144 100644
--- a/spec/integration/solo/solo_spec.rb
+++ b/spec/integration/solo/solo_spec.rb
@@ -70,6 +70,40 @@ EOM
end
end
+ when_the_repository "has a cookbook with an incompatible chef_version" do
+ before do
+ file 'cookbooks/x/metadata.rb', cb_metadata('x', '1.0.0', "\nchef_version '~> 999.0'")
+ file 'cookbooks/x/recipes/default.rb', 'puts "ITWORKS"'
+ file 'config/solo.rb', <<EOM
+cookbook_path "#{path_to('cookbooks')}"
+file_cache_path "#{path_to('config/cache')}"
+EOM
+ end
+
+ it "should exit with an error" do
+ result = shell_out("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug", :cwd => chef_dir)
+ expect(result.exitstatus).to eq(1)
+ expect(result.stdout).to include("Chef::Exceptions::CookbookChefVersionMismatch")
+ end
+ end
+
+ when_the_repository "has a cookbook with an incompatible ohai_version" do
+ before do
+ file 'cookbooks/x/metadata.rb', cb_metadata('x', '1.0.0', "\nohai_version '~> 999.0'")
+ file 'cookbooks/x/recipes/default.rb', 'puts "ITWORKS"'
+ file 'config/solo.rb', <<EOM
+cookbook_path "#{path_to('cookbooks')}"
+file_cache_path "#{path_to('config/cache')}"
+EOM
+ end
+
+ it "should exit with an error" do
+ result = shell_out("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug", :cwd => chef_dir)
+ expect(result.exitstatus).to eq(1)
+ expect(result.stdout).to include("Chef::Exceptions::CookbookOhaiVersionMismatch")
+ end
+ end
+
when_the_repository "has a cookbook with a recipe with sleep" do
before do
diff --git a/spec/unit/cookbook/metadata_spec.rb b/spec/unit/cookbook/metadata_spec.rb
index 1b30286f51..f8e96ad475 100644
--- a/spec/unit/cookbook/metadata_spec.rb
+++ b/spec/unit/cookbook/metadata_spec.rb
@@ -1,7 +1,7 @@
#
# Author:: Adam Jacob (<adam@opscode.com>)
# Author:: Seth Falcon (<seth@opscode.com>)
-# Copyright:: Copyright 2008-2010 Opscode, Inc.
+# Copyright:: Copyright 2008-2015 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,7 +30,7 @@ describe Chef::Cookbook::Metadata do
:maintainer_email, :license, :platforms, :dependencies,
:recommendations, :suggestions, :conflicting, :providing,
:replacing, :attributes, :groupings, :recipes, :version,
- :source_url, :issues_url, :privacy ]
+ :source_url, :issues_url, :privacy, :ohai_versions, :chef_versions ]
end
it "does not depend on object identity for equality" do
@@ -326,6 +326,110 @@ describe Chef::Cookbook::Metadata do
end
end
+ describe "chef_version" do
+ def expect_chef_version_works(*args)
+ ret = []
+ args.each do |arg|
+ metadata.send(:chef_version, *arg)
+ ret << Gem::Dependency.new("chef", *arg)
+ end
+ expect(metadata.send(:chef_versions)).to eql(ret)
+ end
+
+ it "should work with a single simple constraint" do
+ expect_chef_version_works(["~> 12"])
+ end
+
+ it "should work with a single complex constraint" do
+ expect_chef_version_works([">= 12.0.1", "< 12.5.1"])
+ end
+
+ it "should work with multiple simple constraints" do
+ expect_chef_version_works(["~> 12.5.1"],["~> 11.18.10"])
+ end
+
+ it "should work with multiple complex constraints" do
+ expect_chef_version_works([">= 11.14.2", "< 11.18.10"],[">= 12.2.1", "< 12.5.1"])
+ end
+
+ it "should fail validation on a simple pessimistic constraint" do
+ expect_chef_version_works(["~> 999.0"])
+ expect { metadata.validate_chef_version! }.to raise_error(Chef::Exceptions::CookbookChefVersionMismatch)
+ end
+
+ it "should fail validation when that valid chef versions are too big" do
+ expect_chef_version_works([">= 999.0", "< 999.9"])
+ expect { metadata.validate_chef_version! }.to raise_error(Chef::Exceptions::CookbookChefVersionMismatch)
+ end
+
+ it "should fail validation when that valid chef versions are too small" do
+ expect_chef_version_works([">= 0.0.1", "< 0.0.9"])
+ expect { metadata.validate_chef_version! }.to raise_error(Chef::Exceptions::CookbookChefVersionMismatch)
+ end
+
+ it "should fail validation when all ranges fail" do
+ expect_chef_version_works([">= 999.0", "< 999.9"],[">= 0.0.1", "< 0.0.9"])
+ expect { metadata.validate_chef_version! }.to raise_error(Chef::Exceptions::CookbookChefVersionMismatch)
+ end
+
+ it "should pass validation when one constraint passes" do
+ expect_chef_version_works([">= 999.0", "< 999.9"],["= #{Chef::VERSION}"])
+ expect { metadata.validate_chef_version! }.not_to raise_error
+ end
+ end
+
+ describe "ohai_version" do
+ def expect_ohai_version_works(*args)
+ ret = []
+ args.each do |arg|
+ metadata.send(:ohai_version, *arg)
+ ret << Gem::Dependency.new("ohai", *arg)
+ end
+ expect(metadata.send(:ohai_versions)).to eql(ret)
+ end
+
+ it "should work with a single simple constraint" do
+ expect_ohai_version_works(["~> 12"])
+ end
+
+ it "should work with a single complex constraint" do
+ expect_ohai_version_works([">= 12.0.1", "< 12.5.1"])
+ end
+
+ it "should work with multiple simple constraints" do
+ expect_ohai_version_works(["~> 12.5.1"],["~> 11.18.10"])
+ end
+
+ it "should work with multiple complex constraints" do
+ expect_ohai_version_works([">= 11.14.2", "< 11.18.10"],[">= 12.2.1", "< 12.5.1"])
+ end
+
+ it "should fail validation on a simple pessimistic constraint" do
+ expect_ohai_version_works(["~> 999.0"])
+ expect { metadata.validate_ohai_version! }.to raise_error(Chef::Exceptions::CookbookOhaiVersionMismatch)
+ end
+
+ it "should fail validation when that valid chef versions are too big" do
+ expect_ohai_version_works([">= 999.0", "< 999.9"])
+ expect { metadata.validate_ohai_version! }.to raise_error(Chef::Exceptions::CookbookOhaiVersionMismatch)
+ end
+
+ it "should fail validation when that valid chef versions are too small" do
+ expect_ohai_version_works([">= 0.0.1", "< 0.0.9"])
+ expect { metadata.validate_ohai_version! }.to raise_error(Chef::Exceptions::CookbookOhaiVersionMismatch)
+ end
+
+ it "should fail validation when all ranges fail" do
+ expect_ohai_version_works([">= 999.0", "< 999.9"],[">= 0.0.1", "< 0.0.9"])
+ expect { metadata.validate_ohai_version! }.to raise_error(Chef::Exceptions::CookbookOhaiVersionMismatch)
+ end
+
+ it "should pass validation when one constraint passes" do
+ expect_ohai_version_works([">= 999.0", "< 999.9"],["= #{Ohai::VERSION}"])
+ expect { metadata.validate_ohai_version! }.not_to raise_error
+ end
+ end
+
describe "attribute groupings" do
it "should allow you set a grouping" do
group = {
@@ -684,9 +788,14 @@ describe Chef::Cookbook::Metadata do
metadata.attribute "bizspark/has_login",
:display_name => "You have nothing"
metadata.version "1.2.3"
+ metadata.chef_version ">= 11.14.2", "< 11.18.10"
+ metadata.chef_version ">= 12.2.1", "< 12.5.1"
+ metadata.ohai_version ">= 7.1.0", "< 7.5.0"
+ metadata.ohai_version ">= 8.0.1", "< 8.6.0"
end
it "should produce the same output from to_json and Chef::JSONCompat" do
+ # XXX: fairly certain this is testing ruby method dispatch
expect(metadata.to_json).to eq(Chef::JSONCompat.to_json(metadata))
end
@@ -723,6 +832,15 @@ describe Chef::Cookbook::Metadata do
expect(deserialized_metadata[t]).to eq(metadata.send(t.to_sym))
end
end
+
+ %w{
+ ohai_versions
+ chef_versions
+ }.each do |t|
+ it "should include '#{t}'" do
+ expect(deserialized_metadata[t]).to eq(metadata.gem_requirements_to_array(*metadata.send(t.to_sym)))
+ end
+ end
end
describe "deserialize" do
@@ -754,6 +872,8 @@ describe Chef::Cookbook::Metadata do
source_url
issues_url
privacy
+ chef_versions
+ ohai_versions
}.each do |t|
it "should match '#{t}'" do
expect(deserialized_metadata.send(t.to_sym)).to eq(metadata.send(t.to_sym))
diff --git a/spec/unit/policy_builder/policyfile_spec.rb b/spec/unit/policy_builder/policyfile_spec.rb
index b656a66ec3..ed893260c2 100644
--- a/spec/unit/policy_builder/policyfile_spec.rb
+++ b/spec/unit/policy_builder/policyfile_spec.rb
@@ -662,6 +662,7 @@ describe Chef::PolicyBuilder::Policyfile do
it "builds a run context" do
expect(cookbook_synchronizer).to receive(:sync_cookbooks)
expect_any_instance_of(Chef::RunContext).to receive(:load).with(policy_builder.run_list_expansion_ish)
+ expect_any_instance_of(Chef::CookbookCollection).to receive(:validate!)
run_context = policy_builder.setup_run_context
expect(run_context.node).to eq(node)
expect(run_context.cookbook_collection.keys).to match_array(["example1", "example2"])
@@ -670,6 +671,7 @@ describe Chef::PolicyBuilder::Policyfile do
it "makes the run context available via static method on Chef" do
expect(cookbook_synchronizer).to receive(:sync_cookbooks)
expect_any_instance_of(Chef::RunContext).to receive(:load).with(policy_builder.run_list_expansion_ish)
+ expect_any_instance_of(Chef::CookbookCollection).to receive(:validate!)
run_context = policy_builder.setup_run_context
expect(Chef.run_context).to eq(run_context)
end