class Chef::CookbookLoader

Attributes

cookbook_paths[R]
cookbooks_by_name[R]
merged_cookbooks[R]
metadata[R]

Public Class Methods

new(*repo_paths) click to toggle source
# File lib/chef/cookbook_loader.rb, line 41
def initialize(*repo_paths)
  repo_paths = repo_paths.flatten
  raise ArgumentError, "You must specify at least one cookbook repo path" if repo_paths.empty?
  @cookbooks_by_name = Mash.new
  @loaded_cookbooks = {}
  @metadata = Mash.new
  @cookbooks_paths = Hash.new { |h, k| h[k] = [] } # for deprecation warnings
  @chefignores = {}
  @repo_paths = repo_paths.map do |repo_path|
    File.expand_path(repo_path)
  end

  @preloaded_cookbooks = false
  @loaders_by_name = {}

  # Used to track which cookbooks appear in multiple places in the cookbook repos
  # and are merged in to a single cookbook by file shadowing. This behavior is
  # deprecated, so users of this class may issue warnings to the user by checking
  # this variable
  @merged_cookbooks = []
end

Public Instance Methods

[](cookbook) click to toggle source
# File lib/chef/cookbook_loader.rb, line 123
def [](cookbook)
  if @cookbooks_by_name.has_key?(cookbook.to_sym) || load_cookbook(cookbook.to_sym)
    @cookbooks_by_name[cookbook.to_sym]
  else
    raise Exceptions::CookbookNotFoundInRepo, "Cannot find a cookbook named #{cookbook}; did you forget to add metadata to a cookbook? (https://docs.chef.io/config_rb_metadata.html)"
  end
end
Also aliased as: fetch
cookbook_exists?(cookbook_name)
Alias for: has_key?
cookbook_names() click to toggle source
# File lib/chef/cookbook_loader.rb, line 153
def cookbook_names
  @cookbooks_by_name.keys.sort
end
cookbooks()
Alias for: values
each() { |cname, cookbooks_by_name| ... } click to toggle source
# File lib/chef/cookbook_loader.rb, line 139
def each
  @cookbooks_by_name.keys.sort_by(&:to_s).each do |cname|
    yield(cname, @cookbooks_by_name[cname])
  end
end
each_key(&block) click to toggle source
# File lib/chef/cookbook_loader.rb, line 145
def each_key(&block)
  cookbook_names.each(&block)
end
each_value(&block) click to toggle source
# File lib/chef/cookbook_loader.rb, line 149
def each_value(&block)
  values.each(&block)
end
fetch(cookbook)
Alias for: []
has_key?(cookbook_name) click to toggle source
# File lib/chef/cookbook_loader.rb, line 133
def has_key?(cookbook_name)
  not self[cookbook_name.to_sym].nil?
end
Also aliased as: cookbook_exists?, key?
key?(cookbook_name)
Alias for: has_key?
load_cookbook(cookbook_name) click to toggle source
# File lib/chef/cookbook_loader.rb, line 93
def load_cookbook(cookbook_name)
  preload_cookbooks

  return @cookbooks_by_name[cookbook_name] if @cookbooks_by_name.has_key?(cookbook_name)

  return nil unless @loaders_by_name.key?(cookbook_name.to_s)

  cookbook_loaders_for(cookbook_name).each do |loader|
    loader.load

    next if loader.empty?

    @cookbooks_paths[cookbook_name] << loader.cookbook_path # for deprecation warnings

    if @loaded_cookbooks.key?(cookbook_name)
      @merged_cookbooks << cookbook_name # for deprecation warnings
      @loaded_cookbooks[cookbook_name].merge!(loader)
    else
      @loaded_cookbooks[cookbook_name] = loader
    end
  end

  if @loaded_cookbooks.has_key?(cookbook_name)
    cookbook_version = @loaded_cookbooks[cookbook_name].cookbook_version
    @cookbooks_by_name[cookbook_name] = cookbook_version
    @metadata[cookbook_name] = cookbook_version.metadata
  end
  @cookbooks_by_name[cookbook_name]
end
load_cookbooks() click to toggle source
# File lib/chef/cookbook_loader.rb, line 87
def load_cookbooks
  ret = load_cookbooks_without_shadow_warning
  warn_about_cookbook_shadowing
  ret
end
load_cookbooks_without_shadow_warning() click to toggle source

Will be removed when cookbook shadowing is removed, do NOT create new consumers of this API.

@api private

# File lib/chef/cookbook_loader.rb, line 79
def load_cookbooks_without_shadow_warning
  preload_cookbooks
  @loaders_by_name.each_key do |cookbook_name|
    load_cookbook(cookbook_name)
  end
  @cookbooks_by_name
end
merged_cookbook_paths() click to toggle source
# File lib/chef/cookbook_loader.rb, line 63
def merged_cookbook_paths # for deprecation warnings
  merged_cookbook_paths = {}
  @merged_cookbooks.each { |c| merged_cookbook_paths[c] = @cookbooks_paths[c] }
  merged_cookbook_paths
end
values() click to toggle source
# File lib/chef/cookbook_loader.rb, line 157
def values
  @cookbooks_by_name.values
end
Also aliased as: cookbooks
warn_about_cookbook_shadowing() click to toggle source
# File lib/chef/cookbook_loader.rb, line 69
def warn_about_cookbook_shadowing
  unless merged_cookbooks.empty?
    Chef::Log.deprecation "The cookbook(s): #{merged_cookbooks.join(', ')} exist in multiple places in your cookbook_path. " +
      "A composite version has been compiled.  This has been deprecated since 0.10.4, in Chef 13 this behavior will be REMOVED."
  end
end

Private Instance Methods

add_cookbook_loader(loader) click to toggle source
# File lib/chef/cookbook_loader.rb, line 195
def add_cookbook_loader(loader)
  cookbook_name = loader.cookbook_name

  @loaders_by_name[cookbook_name.to_s] ||= []
  @loaders_by_name[cookbook_name.to_s] << loader
  loader
end
all_directories_in_repo_paths() click to toggle source
# File lib/chef/cookbook_loader.rb, line 181
def all_directories_in_repo_paths
  @all_directories_in_repo_paths ||=
    all_files_in_repo_paths.select { |path| File.directory?(path) }
end
all_files_in_repo_paths() click to toggle source
# File lib/chef/cookbook_loader.rb, line 186
def all_files_in_repo_paths
  @all_files_in_repo_paths ||=
    begin
      @repo_paths.inject([]) do |all_children, repo_path|
        all_children + Dir[File.join(Chef::Util::PathHelper.escape_glob_dir(repo_path), "*")]
      end
    end
end
cookbook_loaders_for(cookbook_name) click to toggle source
# File lib/chef/cookbook_loader.rb, line 203
def cookbook_loaders_for(cookbook_name)
  @loaders_by_name[cookbook_name.to_s]
end
preload_cookbook(cookbook_path) click to toggle source
# File lib/chef/cookbook_loader.rb, line 174
def preload_cookbook(cookbook_path)
  repo_path = File.dirname(cookbook_path)
  @chefignores[repo_path] ||= Cookbook::Chefignore.new(repo_path)
  loader = Cookbook::CookbookVersionLoader.new(cookbook_path, @chefignores[repo_path])
  add_cookbook_loader(loader)
end
preload_cookbooks() click to toggle source
# File lib/chef/cookbook_loader.rb, line 164
def preload_cookbooks
  return false if @preloaded_cookbooks

  all_directories_in_repo_paths.each do |cookbook_path|
    preload_cookbook(cookbook_path)
  end
  @preloaded_cookbooks = true
  true
end