class Ridley::Chef::Cookbook::Metadata
Borrowed and modified from: {raw.github.com/opscode/chef/11.4.0/lib/chef/cookbook/metadata.rb}
- Copyright
-
Copyright 2008-2010 Opscode, Inc.
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Chef::Cookbook::Metadata
¶ ↑
Chef::Cookbook::Metadata
provides a convenient DSL for declaring metadata about Chef
Cookbooks.
Constants
- ATTRIBUTES
- CHEF_VERSIONS
- COMPARISON_FIELDS
- COMPILED_FILE_NAME
- CONFLICTING
- DEPENDENCIES
- DESCRIPTION
- GEMS
- GROUPINGS
- ISSUES_URL
- LICENSE
- LONG_DESCRIPTION
- MAINTAINER
- MAINTAINER_EMAIL
- NAME
- OHAI_VERSIONS
- PLATFORMS
- PRIVACY
- PROVIDING
- RAW_FILE_NAME
- RECIPES
- RECOMMENDATIONS
- REPLACING
- SOURCE_URL
- SUGGESTIONS
- VERSION
Attributes
@return [Array<Gem::Dependency>] Array of supported Chef
versions
@return [Array<Array>] Array of gems to install with *args as an Array
@return [Array<Gem::Dependency>] Array of supported Ohai versions
Public Class Methods
# File lib/ridley/chef/cookbook/metadata.rb, line 24 def from_hash(hash) new.from_hash(hash) end
# File lib/ridley/chef/cookbook/metadata.rb, line 28 def from_json(json) new.from_json(json) end
Builds a new Chef::Cookbook::Metadata
object.
Parameters¶ ↑
- cookbook<String>
-
An optional cookbook object
- maintainer<String>
-
An optional maintainer
maintainer_email
<String>-
An optional maintainer email
license<String>::An optional license. Default is Apache v2.0
Returns¶ ↑
metadata<Chef::Cookbook::Metadata>
# File lib/ridley/chef/cookbook/metadata.rb, line 101 def initialize(cookbook = nil, maintainer = 'YOUR_COMPANY_NAME', maintainer_email = 'YOUR_EMAIL', license = 'none') @cookbook = cookbook @name = cookbook ? cookbook.name : "" @long_description = "" self.maintainer(maintainer) self.maintainer_email(maintainer_email) self.license(license) self.description('A fabulous new cookbook') @platforms = Hashie::Mash.new @dependencies = Hashie::Mash.new @recommendations = Hashie::Mash.new @suggestions = Hashie::Mash.new @conflicting = Hashie::Mash.new @providing = Hashie::Mash.new @replacing = Hashie::Mash.new @attributes = Hashie::Mash.new @groupings = Hashie::Mash.new @recipes = Hashie::Mash.new @version = Semverse::Version.new("0.0.0") @source_url = '' @issues_url = '' @privacy = false @chef_versions = [] @ohai_versions = [] @gems = [] if cookbook @recipes = cookbook.fully_qualified_recipe_names.inject({}) do |r, e| e = self.name if e =~ /::default$/ r[e] = "" self.provides e r end end end
Public Instance Methods
# File lib/ridley/chef/cookbook/metadata.rb, line 137 def ==(other) COMPARISON_FIELDS.inject(true) do |equal_so_far, field| equal_so_far && other.respond_to?(field) && (other.send(field) == send(field)) end end
Adds an attribute )hat a user needs to configure for this cookbook. Takes a name (with the / notation for a nested attribute), followed by any of these options
display_name<String>:: What a UI should show for this attribute description<String>:: A hint as to what this attr is for choice<Array>:: An array of choices to present to the user. calculated<Boolean>:: If true, the default value is calculated by the recipe and cannot be displayed. type<String>:: "string" or "array" - default is "string" ("hash" is supported for backwards compatibility) required<String>:: Whether this attr is 'required', 'recommended' or 'optional' - default 'optional' (true/false values also supported for backwards compatibility) recipes<Array>:: An array of recipes which need this attr set. default<String>,<Array>,<Hash>:: The default value
Parameters¶ ↑
- name<String>
-
The name of the attribute ('foo', or 'apache2/log_dir')
- options<Hash>
-
The description of the options
Returns¶ ↑
- options<Hash>
-
Returns the current options hash
# File lib/ridley/chef/cookbook/metadata.rb, line 434 def attribute(name, options) validate( options, { :display_name => { :kind_of => String }, :description => { :kind_of => String }, :choice => { :kind_of => [ Array ], :default => [] }, :calculated => { :equal_to => [ true, false ], :default => false }, :type => { :equal_to => [ "string", "array", "hash", "symbol", "boolean", "numeric" ], :default => "string" }, :required => { :equal_to => [ "required", "recommended", "optional", true, false ], :default => "optional" }, :recipes => { :kind_of => [ Array ], :default => [] }, :default => { :kind_of => [ String, Array, Hash, Symbol, Numeric, TrueClass, FalseClass ] }, :source_url => { :kind_of => String }, :issues_url => { :kind_of => String }, :privacy => { :kind_of => [ TrueClass, FalseClass ] }, } ) options[:required] = remap_required_attribute(options[:required]) unless options[:required].nil? validate_choice_array(options) validate_calculated_default_rule(options) validate_choice_default_rule(options) @attributes[name] = options @attributes[name] 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
# File lib/ridley/chef/cookbook/metadata.rb, line 376 def chef_version(*version_args) @chef_versions << Gem::Dependency.new("chef", *version_args) unless version_args.empty? @chef_versions end
Adds a conflict for another cookbook, with version checking strings.
Parameters¶ ↑
- cookbook<String>
-
The cookbook
- version<String>
-
A version constraint of the form “OP VERSION”,
where OP is one of < <= = > >= ~> and VERSION
has the form x.y.z or x.y.
Returns¶ ↑
- versions<Array>
-
Returns the list of versions for the platform
# File lib/ridley/chef/cookbook/metadata.rb, line 329 def conflicts(cookbook, *version_args) version = version_args.first @conflicting[cookbook] = Semverse::Constraint.new(version).to_s @conflicting[cookbook] end
Adds a dependency on another cookbook, with version checking strings.
Parameters¶ ↑
- cookbook<String>
-
The cookbook
- version<String>
-
A version constraint of the form “OP VERSION”,
where OP is one of < <= = > >= ~> and VERSION
has the form x.y.z or x.y.
Returns¶ ↑
- versions<Array>
-
Returns the list of versions for the platform
# File lib/ridley/chef/cookbook/metadata.rb, line 281 def depends(cookbook, *version_args) version = version_args.first @dependencies[cookbook] = Semverse::Constraint.new(version).to_s @dependencies[cookbook] end
Sets the current description, or returns it. Should be short - one line only!
Parameters¶ ↑
- description<String>
-
The new description
Returns¶ ↑
- description<String>
-
Returns the description
# File lib/ridley/chef/cookbook/metadata.rb, line 201 def description(arg = nil) set_or_return( :description, arg, :kind_of => [ String ] ) end
# File lib/ridley/chef/cookbook/metadata.rb, line 542 def from_hash(o) @name = o[NAME] if o.has_key?(NAME) @description = o[DESCRIPTION] if o.has_key?(DESCRIPTION) @long_description = o[LONG_DESCRIPTION] if o.has_key?(LONG_DESCRIPTION) @maintainer = o[MAINTAINER] if o.has_key?(MAINTAINER) @maintainer_email = o[MAINTAINER_EMAIL] if o.has_key?(MAINTAINER_EMAIL) @license = o[LICENSE] if o.has_key?(LICENSE) @platforms = handle_deprecated_constraints(o[PLATFORMS]) if o.has_key?(PLATFORMS) @dependencies = handle_deprecated_constraints(o[DEPENDENCIES]) if o.has_key?(DEPENDENCIES) @recommendations = handle_deprecated_constraints(o[RECOMMENDATIONS]) if o.has_key?(RECOMMENDATIONS) @suggestions = handle_deprecated_constraints(o[SUGGESTIONS]) if o.has_key?(SUGGESTIONS) @conflicting = handle_deprecated_constraints(o[CONFLICTING]) if o.has_key?(CONFLICTING) @providing = o[PROVIDING] if o.has_key?(PROVIDING) @replacing = handle_deprecated_constraints(o[REPLACING]) if o.has_key?(REPLACING) @attributes = o[ATTRIBUTES] if o.has_key?(ATTRIBUTES) @groupings = o[GROUPINGS] if o.has_key?(GROUPINGS) @recipes = o[RECIPES] if o.has_key?(RECIPES) @version = o[VERSION] if o.has_key?(VERSION) @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) @gems = o[GEMS] if o.has_key?(GEMS) self end
# File lib/ridley/chef/cookbook/metadata.rb, line 569 def from_json(json) from_hash JSON.parse(json) end
Metadata
DSL to set a gem to install from the cookbook metadata. May be declared multiple times. All the gems from all the cookbooks are combined into one Gemfile and depsolved together. Uses Bundler's DSL for its implementation.
@param args [Array<String>] Gem name and options to pass to Bundler's DSL @return [Array<Array>] Array of gem statements as args
# File lib/ridley/chef/cookbook/metadata.rb, line 398 def gem(*args) @gems << args unless args.empty? @gems 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
# File lib/ridley/chef/cookbook/metadata.rb, line 500 def gem_requirements_from_array(what, array) array.map do |dep| Gem::Dependency.new(what, *dep) end 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)
# File lib/ridley/chef/cookbook/metadata.rb, line 485 def gem_requirements_to_array(*deps) deps.map do |dep| dep.requirement.requirements.map do |op, version| "#{op} #{version}" end.sort end end
# File lib/ridley/chef/cookbook/metadata.rb, line 460 def grouping(name, options) validate( options, { :title => { :kind_of => String }, :description => { :kind_of => String } } ) @groupings[name] = options @groupings[name] end
Sets the cookbook's issues URL, or returns it.
Parameters¶ ↑
issues_url
<String>-
The issues URL
Returns¶ ↑
issues_url
<String>-
Returns the current issues URL.
# File lib/ridley/chef/cookbook/metadata.rb, line 595 def issues_url(arg = nil) set_or_return( :issues_url, arg, :kind_of => [ String ] ) end
Sets the current long description, or returns it. Might come from a README, say.
Parameters¶ ↑
long_description
<String>-
The new long description
Returns¶ ↑
long_description
<String>-
Returns the long description
# File lib/ridley/chef/cookbook/metadata.rb, line 216 def long_description(arg = nil) set_or_return( :long_description, arg, :kind_of => [ String ] ) end
Sets the cookbooks maintainer, or returns it.
Parameters¶ ↑
- maintainer<String>
-
The maintainers name
Returns¶ ↑
- maintainer<String>
-
Returns the current maintainer.
# File lib/ridley/chef/cookbook/metadata.rb, line 156 def maintainer(arg = nil) set_or_return( :maintainer, arg, :kind_of => [ String ] ) end
Sets the maintainers email address, or returns it.
Parameters¶ ↑
maintainer_email
<String>-
The maintainers email address
Returns¶ ↑
maintainer_email
<String>-
Returns the current maintainer email.
# File lib/ridley/chef/cookbook/metadata.rb, line 171 def maintainer_email(arg = nil) set_or_return( :maintainer_email, arg, :kind_of => [ String ] ) 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
# File lib/ridley/chef/cookbook/metadata.rb, line 387 def ohai_version(*version_args) @ohai_versions << Gem::Dependency.new("ohai", *version_args) unless version_args.empty? @ohai_versions end
Sets the cookbook's privacy flag, or returns it.
Parameters¶ ↑
- privacy<TrueClass,FalseClass>
-
Whether this cookbook is private or not
Returns¶ ↑
- privacy<TrueClass,FalseClass>
-
Whether this cookbook is private or not
# File lib/ridley/chef/cookbook/metadata.rb, line 612 def privacy(arg = nil) set_or_return( :privacy, arg, :kind_of => [ TrueClass, FalseClass ], ) end
Adds a recipe, definition, or resource provided by this cookbook.
Recipes are specified as normal Definitions are followed by (), and can include :params for prototyping Resources are the stringified version (service)
Parameters¶ ↑
- recipe, definition, resource<String>
-
The thing we provide
- version<String>
-
A version constraint of the form “OP VERSION”,
where OP is one of < <= = > >= ~> and VERSION
has the form x.y.z or x.y.
Returns¶ ↑
- versions<Array>
-
Returns the list of versions for the platform
# File lib/ridley/chef/cookbook/metadata.rb, line 349 def provides(cookbook, *version_args) version = version_args.first @providing[cookbook] = Semverse::Constraint.new(version).to_s @providing[cookbook] end
Adds a description for a recipe.
Parameters¶ ↑
- recipe<String>
-
The recipe
- description<String>
-
The description of the recipe
Returns¶ ↑
- description<String>
-
Returns the current description
# File lib/ridley/chef/cookbook/metadata.rb, line 411 def recipe(name, description) @recipes[name] = description end
Adds a recommendation for another cookbook, with version checking strings.
Parameters¶ ↑
- cookbook<String>
-
The cookbook
- version<String>
-
A version constraint of the form “OP VERSION”,
where OP is one of < <= = > >= ~> and VERSION
has the form x.y.z or x.y.
Returns¶ ↑
- versions<Array>
-
Returns the list of versions for the platform
# File lib/ridley/chef/cookbook/metadata.rb, line 297 def recommends(cookbook, *version_args) version = version_args.first @recommendations[cookbook] = Semverse::Constraint.new(version).to_s @recommendations[cookbook] end
Adds a cookbook that is replaced by this one, with version checking strings.
Parameters¶ ↑
- cookbook<String>
-
The cookbook we replace
- version<String>
-
A version constraint of the form “OP VERSION”,
where OP is one of < <= = > >= ~> and VERSION
has the form x.y.z or x.y.
Returns¶ ↑
- versions<Array>
-
Returns the list of versions for the platform
# File lib/ridley/chef/cookbook/metadata.rb, line 364 def replaces(cookbook, *version_args) version = version_args.first @replacing[cookbook] = Semverse::Constraint.new(version).to_s @replacing[cookbook] end
Sets the cookbook's source URL, or returns it.
Parameters¶ ↑
- maintainer<String>
-
The source URL
Returns¶ ↑
source_url
<String>-
Returns the current source URL.
# File lib/ridley/chef/cookbook/metadata.rb, line 580 def source_url(arg = nil) set_or_return( :source_url, arg, :kind_of => [ String ] ) end
Adds a suggestion for another cookbook, with version checking strings.
Parameters¶ ↑
- cookbook<String>
-
The cookbook
- version<String>
-
A version constraint of the form “OP VERSION”,
where OP is one of < <= = > >= ~> and VERSION
has the formx.y.z or x.y.
Returns¶ ↑
- versions<Array>
-
Returns the list of versions for the platform
# File lib/ridley/chef/cookbook/metadata.rb, line 313 def suggests(cookbook, *version_args) version = version_args.first @suggestions[cookbook] = Semverse::Constraint.new(version).to_s @suggestions[cookbook] end
Adds a supported platform, with version checking strings.
Parameters¶ ↑
- platform<String>,<Symbol>
-
The platform (like :ubuntu or :mac_os_x)
- version<String>
-
A version constraint of the form “OP VERSION”,
where OP is one of < <= = > >= ~> and VERSION
has the form x.y.z or x.y.
Returns¶ ↑
- versions<Array>
-
Returns the list of versions for the platform
# File lib/ridley/chef/cookbook/metadata.rb, line 265 def supports(platform, *version_args) version = version_args.first @platforms[platform] = Semverse::Constraint.new(version).to_s @platforms[platform] end
# File lib/ridley/chef/cookbook/metadata.rb, line 506 def to_hash { NAME => self.name, DESCRIPTION => self.description, LONG_DESCRIPTION => self.long_description, MAINTAINER => self.maintainer, MAINTAINER_EMAIL => self.maintainer_email, LICENSE => self.license, PLATFORMS => self.platforms, DEPENDENCIES => self.dependencies, RECOMMENDATIONS => self.recommendations, SUGGESTIONS => self.suggestions, CONFLICTING => self.conflicting, PROVIDING => self.providing, REPLACING => self.replacing, ATTRIBUTES => self.attributes, GROUPINGS => self.groupings, RECIPES => self.recipes, VERSION => self.version, SOURCE_URL => self.source_url, ISSUES_URL => self.issues_url, PRIVACY => self.privacy, CHEF_VERSIONS => gem_requirements_to_array(*self.chef_versions), OHAI_VERSIONS => gem_requirements_to_array(*self.ohai_versions), GEMS => self.gems, } end
@return [String]
# File lib/ridley/chef/cookbook/metadata.rb, line 535 def to_json # Switched from fast to pretty generate here # to match `knife cookbook metadata from file` format # See https://github.com/RiotGames/ridley/pull/287 JSON.pretty_generate(to_hash) end
Private Instance Methods
This method translates version constraint strings from cookbooks with the old format.
Before we began respecting version constraints, we allowed multiple constraints to be placed on cookbooks, as well as the << and >> operators, which are now just < and >. For specifications with more than one constraint, this method switches to the default constraint from SemVerse. If there is only one constraint, we are replacing the old << and >> with the new < and >.
# File lib/ridley/chef/cookbook/metadata.rb, line 714 def handle_deprecated_constraints(specification) specification.inject(Hashie::Mash.new) do |acc, (cb, constraints)| constraints = Array(constraints) acc[cb] = if constraints.size == 1 constraints.first.gsub(/>>/, '>').gsub(/<</, '<') else Semverse::DEFAULT_CONSTRAINT.to_s end acc end end
For backwards compatibility, remap Boolean values to String
true is mapped to "required" false is mapped to "optional"
Parameters¶ ↑
- required_attr<String><Boolean>
-
The value of options
Returns¶ ↑
- required_attr<String>
-
“required”, “recommended”, or “optional”
# File lib/ridley/chef/cookbook/metadata.rb, line 673 def remap_required_attribute(value) case value when true value = "required" when false value = "optional" end value end
# File lib/ridley/chef/cookbook/metadata.rb, line 683 def validate_calculated_default_rule(options) calculated_conflict = ((options[:default].is_a?(Array) && !options[:default].empty?) || (options[:default].is_a?(String) && !options[:default] != "")) && options[:calculated] == true raise ArgumentError, "Default cannot be specified if calculated is true!" if calculated_conflict end
Validate the choice of the options hash
Raise an exception if the members of the array do not match the defaults
Parameters¶ ↑
- opts<Hash>
-
The options hash
# File lib/ridley/chef/cookbook/metadata.rb, line 641 def validate_choice_array(opts) if opts[:choice].kind_of?(Array) case opts[:type] when "string" validator = [ String ] when "array" validator = [ Array ] when "hash" validator = [ Hash ] when "symbol" validator = [ Symbol ] when "boolean" validator = [ TrueClass, FalseClass ] when "numeric" validator = [ Numeric ] end opts[:choice].each do |choice| validate( {:choice => choice}, {:choice => {:kind_of => validator}} ) end end end
# File lib/ridley/chef/cookbook/metadata.rb, line 690 def validate_choice_default_rule(options) return if !options[:choice].is_a?(Array) || options[:choice].empty? if options[:default].is_a?(String) && options[:default] != "" raise ArgumentError, "Default must be one of your choice values!" if options[:choice].index(options[:default]) == nil end if options[:default].is_a?(Array) && !options[:default].empty? options[:default].each do |val| raise ArgumentError, "Default values must be a subset of your choice values!" if options[:choice].index(val) == nil end end end
Verify that the given array is an array of strings
Raise an exception if the members of the array are not Strings
Parameters¶ ↑
- arry<Array>
-
An array to be validated
# File lib/ridley/chef/cookbook/metadata.rb, line 628 def validate_string_array(arry) if arry.kind_of?(Array) arry.each do |choice| validate( {:choice => choice}, {:choice => {:kind_of => String}} ) end end end