diff options
author | danielsdeleo <dan@getchef.com> | 2015-02-05 15:55:18 -0800 |
---|---|---|
committer | danielsdeleo <dan@getchef.com> | 2015-02-11 10:52:49 -0800 |
commit | e3e9f1996131f287f0e6d8b344e658062003efe7 (patch) | |
tree | acc56cfcc02c3daf084a7f226e111e4f526bd3b9 /lib/chef/cookbook_version.rb | |
parent | e36664c40c02c5dca2a77509e1a6d63689cb79fe (diff) | |
download | chef-e3e9f1996131f287f0e6d8b344e658062003efe7.tar.gz |
Move CookbookManifest to its own file
Diffstat (limited to 'lib/chef/cookbook_version.rb')
-rw-r--r-- | lib/chef/cookbook_version.rb | 202 |
1 files changed, 1 insertions, 201 deletions
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb index b2d98e7b8f..025828beb5 100644 --- a/lib/chef/cookbook_version.rb +++ b/lib/chef/cookbook_version.rb @@ -23,211 +23,11 @@ require 'chef/log' require 'chef/cookbook/file_vendor' require 'chef/cookbook/metadata' require 'chef/version_class' -require 'pathname' require 'chef/digester' - -require 'forwardable' +require 'chef/cookbook_manifest' class Chef - # Handles the details of representing a cookbook in JSON form for uploading - # to a Chef Server. - class CookbookManifest - - # TODO: duplicates the same constant in CookbookVersion - COOKBOOK_SEGMENTS = [ :resources, :providers, :recipes, :definitions, :libraries, :attributes, :files, :templates, :root_files ].freeze - - extend Forwardable - - attr_reader :cookbook_version - - def_delegator :@cookbook_version, :root_paths - def_delegator :@cookbook_version, :segment_filenames - def_delegator :@cookbook_version, :name - def_delegator :@cookbook_version, :metadata - def_delegator :@cookbook_version, :full_name - - def initialize(cookbook_version) - @cookbook_version = cookbook_version - - reset! - end - - # Resets all lazily computed values. - def reset! - @manifest = nil - @checksums = nil - @manifest_records_by_path = nil - true - end - - # Returns a 'manifest' data structure that can be uploaded to a Chef - # Server. - # - # The format is as follows: - # - # { - # :cookbook_name => name, # String - # :metadata => metadata, # Chef::Cookbook::Metadata - # :version => version, # Chef::Version - # :name => full_name, # String of "#{name}-#{version}" - # - # :recipes => Array<FileSpec>, - # :definitions => Array<FileSpec>, - # :libraries => Array<FileSpec>, - # :attributes => Array<FileSpec>, - # :files => Array<FileSpec>, - # :templates => Array<FileSpec>, - # :resources => Array<FileSpec>, - # :providers => Array<FileSpec>, - # :root_files => Array<FileSpec> - # } - # - # Where a `FileSpec` is a Hash of the form: - # - # { - # :name => file_name, - # :path => path, - # :checksum => csum, - # :specificity => specificity - # } - # - def manifest - @manifest || generate_manifest - @manifest - end - - def checksums - @manifest || generate_manifest - @checksums - end - - def manifest_records_by_path - @manifest || generate_manifest - @manifest_records_by_path - end - - # See #manifest for a description of the manifest return value. - # See #preferred_manifest_record for a description an individual manifest record. - def generate_manifest - manifest = Mash.new({ - :recipes => Array.new, - :definitions => Array.new, - :libraries => Array.new, - :attributes => Array.new, - :files => Array.new, - :templates => Array.new, - :resources => Array.new, - :providers => Array.new, - :root_files => Array.new - }) - @checksums = {} - - if !root_paths || root_paths.size == 0 - Chef::Log.error("Cookbook #{name} does not have root_paths! Cannot generate manifest.") - raise "Cookbook #{name} does not have root_paths! Cannot generate manifest." - end - - COOKBOOK_SEGMENTS.each do |segment| - segment_filenames(segment).each do |segment_file| - next if File.directory?(segment_file) - - path, specificity = parse_segment_file_from_root_paths(segment, segment_file) - file_name = File.basename(path) - - csum = checksum_cookbook_file(segment_file) - @checksums[csum] = segment_file - rs = Mash.new({ - :name => file_name, - :path => path, - :checksum => csum, - :specificity => specificity - }) - - manifest[segment] << rs - end - end - - manifest[:cookbook_name] = name.to_s - manifest[:metadata] = metadata - manifest[:version] = metadata.version - manifest[:name] = full_name - - @manifest_records_by_path = extract_manifest_records_by_path(manifest) - @manifest = manifest - end - - # TODO: This is kind of terrible. investigate removing it - def update_from(new_manifest) - @manifest = Mash.new new_manifest - @checksums = extract_checksums_from_manifest(@manifest) - @manifest_records_by_path = extract_manifest_records_by_path(@manifest) - - # TODO: this part of this method is "feature envious" it only deals with - # mutating the CookbookVersion object. - COOKBOOK_SEGMENTS.each do |segment| - next unless @manifest.has_key?(segment) - filenames = @manifest[segment].map{|manifest_record| manifest_record['name']} - - cookbook_version.replace_segment_filenames(segment, filenames) - end - end - - private - - def parse_segment_file_from_root_paths(segment, segment_file) - root_paths.each do |root_path| - pathname = Chef::Util::PathHelper.relative_path_from(root_path, segment_file) - - parts = pathname.each_filename.take(2) - # Check if path is actually under root_path - next if parts[0] == '..' - if segment == :templates || segment == :files - # Check if pathname looks like files/foo or templates/foo (unscoped) - if pathname.each_filename.to_a.length == 2 - # Use root_default in case the same path exists at root_default and default - return [ pathname.to_s, 'root_default' ] - else - return [ pathname.to_s, parts[1] ] - end - else - return [ pathname.to_s, 'default' ] - end - end - Chef::Log.error("Cookbook file #{segment_file} not under cookbook root paths #{root_paths.inspect}.") - raise "Cookbook file #{segment_file} not under cookbook root paths #{root_paths.inspect}." - end - - def extract_checksums_from_manifest(manifest) - checksums = {} - COOKBOOK_SEGMENTS.each do |segment| - next unless manifest.has_key?(segment) - manifest[segment].each do |manifest_record| - checksums[manifest_record[:checksum]] = nil - end - end - checksums - end - - # TODO: delegating to a class method like this is ugly. We should be able - # to fix this by moving logic into a class in a way that will make it easy - # to add support for SHA-2 - def checksum_cookbook_file(filepath) - CookbookVersion.checksum_cookbook_file(filepath) - end - - def extract_manifest_records_by_path(manifest) - manifest_records_by_path = {} - COOKBOOK_SEGMENTS.each do |segment| - next unless manifest.has_key?(segment) - manifest[segment].each do |manifest_record| - manifest_records_by_path[manifest_record[:path]] = manifest_record - end - end - manifest_records_by_path - end - end - # == Chef::CookbookVersion # CookbookVersion is a model object encapsulating the data about a Chef # cookbook. Chef supports maintaining multiple versions of a cookbook on a |