Class: Chef::CookbookLoader

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/chef/cookbook_loader.rb

Overview

This class is used by knife, cheffs and legacy chef-solo modes. It is not used by the server mode of chef-client or zolo/zero modes.

This class implements orchestration around producing a single cookbook_version for a cookbook or loading a Mash of all cookbook_versions, using the cookbook_version_loader class, and doing lazy-access and memoization to only load each cookbook once on demand.

This implements a key-value style each which makes it appear to be a Hash of String => CookbookVersion pairs where the String is the cookbook name. The use of Enumerable combined with the Hash-style each is likely not entirely sane.

This object is also passed and injected into the CookbookCollection object where it is converted to a Mash that looks almost exactly like the cookbook_by_name Mash in this object.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*repo_paths) ⇒ CookbookLoader

Returns a new instance of CookbookLoader.

Parameters:

  • repo_paths (Array<String>)

    the array of repo paths containing cookbook dirs

Raises:

  • (ArgumentError)


53
54
55
56
57
# File 'lib/chef/cookbook_loader.rb', line 53

def initialize(*repo_paths)
  @tmp_working_dir_path = nil
  @repo_paths = repo_paths.flatten.compact.map { |p| File.expand_path(p) }
  raise ArgumentError, "You must specify at least one cookbook repo path" if @repo_paths.empty?
end

Instance Attribute Details

#repo_pathsArray<String> (readonly)

Returns the array of repo paths containing cookbook dirs.

Returns:

  • (Array<String>)

    the array of repo paths containing cookbook dirs



45
46
47
# File 'lib/chef/cookbook_loader.rb', line 45

def repo_paths
  @repo_paths
end

#tmp_working_dir_pathObject

Returns the value of attribute tmp_working_dir_path.



47
48
49
# File 'lib/chef/cookbook_loader.rb', line 47

def tmp_working_dir_path
  @tmp_working_dir_path
end

Class Method Details

.copy_to_tmp_dir_from_array(cookbooks) ⇒ Object

This method creates tmp directory and copies all cookbooks into it and creates cookbook loder object which points to tmp directory



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/chef/cookbook_loader.rb', line 142

def self.copy_to_tmp_dir_from_array(cookbooks)
  tmp_cookbook_file = Tempfile.new("tmp_working_dir_path")
  tmp_cookbook_file.close
  @tmp_working_dir_path = tmp_cookbook_file.path
  File.unlink(@tmp_working_dir_path)
  FileUtils.mkdir_p(@tmp_working_dir_path)
  cookbooks.each do |cookbook|
    checksums_to_on_disk_paths = cookbook.checksums
    cookbook.each_file do |manifest_record|
      path_in_cookbook = manifest_record[:path]
      on_disk_path = checksums_to_on_disk_paths[manifest_record[:checksum]]
      dest = File.join(@tmp_working_dir_path, cookbook.name.to_s, path_in_cookbook)
      FileUtils.mkdir_p(File.dirname(dest))
      FileUtils.cp_r(on_disk_path, dest)
    end
  end
  tmp_cookbook_loader ||= begin
    Chef::Cookbook::FileVendor.fetch_from_disk(@tmp_working_dir_path)
    CookbookLoader.new(@tmp_working_dir_path)
  end
  tmp_cookbook_loader.tmp_working_dir_path = @tmp_working_dir_path
  tmp_cookbook_loader
end

Instance Method Details

#[](cookbook) ⇒ Object Also known as: fetch



106
107
108
# File 'lib/chef/cookbook_loader.rb', line 106

def [](cookbook)
  load_cookbook(cookbook)
end

#compile_metadataObject

generates metadata.json adds it in the manifest



167
168
169
170
171
172
173
174
175
# File 'lib/chef/cookbook_loader.rb', line 167

def 
  each do |cookbook_name, cookbook|
     = cookbook.
    if 
      cookbook.all_files << 
      cookbook.cookbook_manifest.send(:generate_manifest)
    end
  end
end

#cookbook_namesObject



133
134
135
# File 'lib/chef/cookbook_loader.rb', line 133

def cookbook_names
  cookbooks_by_name.keys.sort
end

#cookbooks_by_nameMash<String, Chef::CookbookVersion>

The primary function of this class is to build this Mash mapping cookbook names as a string to the CookbookVersion objects for them. Callers must call “load_cookbooks” first.



63
64
65
# File 'lib/chef/cookbook_loader.rb', line 63

def cookbooks_by_name
  @cookbooks_by_name ||= Mash.new
end

#eachObject



119
120
121
122
123
# File 'lib/chef/cookbook_loader.rb', line 119

def each
  cookbooks_by_name.keys.sort_by(&:to_s).each do |cname|
    yield(cname, cookbooks_by_name[cname])
  end
end

#each_key(&block) ⇒ Object



125
126
127
# File 'lib/chef/cookbook_loader.rb', line 125

def each_key(&block)
  cookbook_names.each(&block)
end

#each_value(&block) ⇒ Object



129
130
131
# File 'lib/chef/cookbook_loader.rb', line 129

def each_value(&block)
  values.each(&block)
end

#freeze_versionsObject

freeze versions of all the cookbooks



178
179
180
181
182
# File 'lib/chef/cookbook_loader.rb', line 178

def freeze_versions
  each do |cookbook_name, cookbook|
    cookbook.freeze_version
  end
end

#has_key?(cookbook_name) ⇒ Boolean Also known as: cookbook_exists?, key?

Returns:

  • (Boolean)


112
113
114
# File 'lib/chef/cookbook_loader.rb', line 112

def has_key?(cookbook_name)
  not self[cookbook_name.to_sym].nil?
end

#load_cookbook(cookbook_name) ⇒ Chef::CookbookVersion

Loads a single cookbook by its name.

Parameters:

Returns:



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/chef/cookbook_loader.rb', line 89

def load_cookbook(cookbook_name)
  unless cookbook_version_loaders.key?(cookbook_name)
    raise Exceptions::CookbookNotFoundInRepo, "Cannot find a cookbook named #{cookbook_name}; did you forget to add metadata to a cookbook? (https://docs.chef.io/config_rb_metadata.html)"
  end

  return cookbooks_by_name[cookbook_name] if cookbooks_by_name.key?(cookbook_name)

  loader = cookbook_version_loaders[cookbook_name]

  loader.load!

  cookbook_version = loader.cookbook_version
  cookbooks_by_name[cookbook_name] = cookbook_version
  [cookbook_name] = cookbook_version. unless cookbook_version.nil?
  cookbook_version
end

#load_cookbooksMash<String, Chef::CookbookVersion>

Loads all cookbooks across all repo_paths

Returns:



78
79
80
81
82
83
# File 'lib/chef/cookbook_loader.rb', line 78

def load_cookbooks
  cookbook_version_loaders.each_key do |cookbook_name|
    load_cookbook(cookbook_name)
  end
  cookbooks_by_name
end

#metadataMash<String, Chef::Cookbook::Metadata>

This class also builds a mapping of cookbook names to their Metadata objects. Callers must call “load_cookbooks” first.



71
72
73
# File 'lib/chef/cookbook_loader.rb', line 71

def 
  @metadata ||= Mash.new
end

#unlink!Object

removes the tmp_dir_path



185
186
187
188
189
# File 'lib/chef/cookbook_loader.rb', line 185

def unlink!
  raise "Invalid directory path." if @tmp_working_dir_path.nil?

  FileUtils.rm_rf(@tmp_working_dir_path)
end

#valuesObject Also known as: cookbooks



137
138
139
# File 'lib/chef/cookbook_loader.rb', line 137

def values
  cookbooks_by_name.values
end