diff options
-rw-r--r-- | lib/chef/cookbook/cookbook_collection.rb | 6 | ||||
-rw-r--r-- | lib/chef/cookbook/metadata.rb | 67 | ||||
-rw-r--r-- | spec/unit/cookbook/metadata_spec.rb | 2 |
3 files changed, 64 insertions, 11 deletions
diff --git a/lib/chef/cookbook/cookbook_collection.rb b/lib/chef/cookbook/cookbook_collection.rb index 325142ce0b..af8bbd15b9 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,6 +41,10 @@ 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. def validate! each do |cookbook_name, cookbook_version| cookbook_version.metadata.validate_chef_version! diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb index ed55c30258..4604a28e83 100644 --- a/lib/chef/cookbook/metadata.rb +++ b/lib/chef/cookbook/metadata.rb @@ -87,7 +87,10 @@ class Chef attr_reader :groupings 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. @@ -394,13 +397,23 @@ class Chef @replacing[cookbook] end - # FIXME + # 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) @chef_versions end - # FIXME + # 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) @ohai_versions @@ -501,7 +514,20 @@ class Chef @groupings[name] end - def gem_requirements_to_hash(*deps) + # 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}" @@ -509,8 +535,15 @@ class Chef end end - def gem_requirements_from_hash(what, hash) - hash.map do |dep| + # 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 @@ -537,8 +570,8 @@ class Chef SOURCE_URL => self.source_url, ISSUES_URL => self.issues_url, PRIVACY => self.privacy, - CHEF_VERSIONS => gem_requirements_to_hash(*self.chef_versions), - OHAI_VERSIONS => gem_requirements_to_hash(*self.ohai_versions) + CHEF_VERSIONS => gem_requirements_to_array(*self.chef_versions), + OHAI_VERSIONS => gem_requirements_to_array(*self.ohai_versions) } end @@ -573,8 +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_hash("chef", o[CHEF_VERSIONS]) if o.has_key?(CHEF_VERSIONS) - @ohai_versions = gem_requirements_from_hash("ohai", o[OHAI_VERSIONS]) if o.has_key?(OHAI_VERSIONS) + @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 @@ -650,12 +683,20 @@ 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) @@ -664,6 +705,14 @@ class Chef 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 diff --git a/spec/unit/cookbook/metadata_spec.rb b/spec/unit/cookbook/metadata_spec.rb index d91b84d9f2..f8e96ad475 100644 --- a/spec/unit/cookbook/metadata_spec.rb +++ b/spec/unit/cookbook/metadata_spec.rb @@ -838,7 +838,7 @@ describe Chef::Cookbook::Metadata do chef_versions }.each do |t| it "should include '#{t}'" do - expect(deserialized_metadata[t]).to eq(metadata.gem_requirements_to_hash(*metadata.send(t.to_sym))) + expect(deserialized_metadata[t]).to eq(metadata.gem_requirements_to_array(*metadata.send(t.to_sym))) end end end |