Skip to content

Commit dbe9f64

Browse files
Tim Hinderliterdanielsdeleo
authored andcommitted
CookbookFileVendor implemented
1 parent c5bda13 commit dbe9f64

1 file changed

Lines changed: 67 additions & 1 deletion

File tree

chef/lib/chef/cookbook_file_vendor.rb

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,75 @@
1717
# limitations under the License.
1818
#
1919

20+
21+
# This class handles fetching of cookbook files based on specificity. A local
22+
# filesystem cache is maintained based on the checksum of files retrieved.
2023
class Chef
2124
class CookbookFileVendor
22-
def get_file(node, cookbook, segment, filename)
25+
def initialize
26+
@cookbook_cache = Hash.new
27+
@checksum_cache = Chef::Cache::FileCacheByChecksum.new
28+
end
29+
30+
# Gets the full pathname for the given cookbook part, returned in specificity
31+
# preference order.
32+
def get_filename(node, cookbook_name, segment, filename)
33+
checksum = get_preferred_checksum(node, cookbook_name, segment, filename)
34+
raise Chef::Exceptions::FileNotFound, "missing file #{segment}/#{filename} for cookbook #{cookbook_name}" unless checksum
35+
36+
checksum_filename = @checksum_cache.get_path(checksum)
37+
unless checksum_filename
38+
# We don't have that checksum in the cache. Fetch it.
39+
# TODO: timh: 2010-4-7: Make this download streaming instead of loading it all in memory
40+
url = "/cookbooks/#{cookbook_name}/#{cookbook_version}/#{checksum}"
41+
42+
# Second argument is true, so we treat the result as raw, not JSON
43+
tempfile = rest.get_rest(url, true)
44+
checksum_filename = @checksum_cache.put(checksum, tempfile.path)
45+
tempfile.close
46+
end
47+
checksum_filename
48+
end
49+
50+
# Figure out the checksum for a given segment/filename based on finding
51+
# the most specific version of the file available.
52+
def get_preferred_checksum(node, cookbook_name, segment, filename)
53+
platform, version = Chef::Platform.find_platform_and_version(node)
54+
fqdn = node[:fqdn]
55+
56+
# Most specific to least specific places to find the filename
57+
preferences = [
58+
File.join("host-#{fqdn}", filename),
59+
File.join("#{platform}-#{version}", filename),
60+
File.join(platform, filename),
61+
File.join("default", filename)
62+
]
63+
64+
cookbook = get_cookbook(cookbook_name)
65+
66+
cookbook_checksum_by_filename = Hash.new
67+
[ :resources, :providers, :recipes, :definitions, :libraries, :attributes, :files, :templates, :root_files ].each do |segment|
68+
cookbook[segment].inject(cookbook_checksum_by_filename) do |memo, segment_file|
69+
checksum = segment_file['checksum']
70+
memo[segment_file.path] = checksum
71+
memo
72+
end
73+
end
74+
75+
# Walk most- to least-specific until we find the filename.
76+
preferences.find { |filename| cookbook_checksum_by_filename[filename] }
77+
end
78+
79+
# Get the cookbook from the cache or fetch if it's not yet in the
80+
# cache.
81+
def get_cookbook(cookbook_name)
82+
unless @cookbook_cache[cookbook_name]
83+
url = "/cookbooks/#{cookbook_name}"
84+
@cookbook_cache[cookbook_name] = rest.get_rest(url)
85+
end
86+
87+
@cookbook_cache[cookbook_name]
2388
end
89+
2490
end
2591
end

0 commit comments

Comments
 (0)