diff options
author | danielsdeleo <dan@opscode.com> | 2012-11-29 15:45:55 -0800 |
---|---|---|
committer | danielsdeleo <dan@opscode.com> | 2012-11-30 14:51:47 -0800 |
commit | 20fd1383020261c3756b54c26f4c2ea9e652d43c (patch) | |
tree | bd00bd9fa4a0e0e18b81a27ca337afc64f1fc287 /lib/chef/run_context.rb | |
parent | b213ae8e8c7aac472332298f0f455d36d122a7b5 (diff) | |
download | chef-20fd1383020261c3756b54c26f4c2ea9e652d43c.tar.gz |
[CHEF-3376] give CookbookCompiler its own file
Diffstat (limited to 'lib/chef/run_context.rb')
-rw-r--r-- | lib/chef/run_context.rb | 227 |
1 files changed, 3 insertions, 224 deletions
diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb index 6d5f001aac..e41b6603fb 100644 --- a/lib/chef/run_context.rb +++ b/lib/chef/run_context.rb @@ -22,236 +22,15 @@ require 'chef/cookbook_version' require 'chef/node' require 'chef/role' require 'chef/log' +require 'chef/recipe' +require 'chef/run_context/cookbook_compiler' class Chef + # == Chef::RunContext # Value object that loads and tracks the context of a Chef run class RunContext - # Implements the compile phase of the chef run by loading/eval-ing files - # from cookbooks in the correct order and in the correct context. - class CookbookCompiler - attr_reader :node - attr_reader :events - attr_reader :run_list_expansion - attr_reader :cookbook_collection - - # Resource Definitions from the compiled cookbooks. This is populated by - # calling #compile_resource_definitions (which is called by #compile) - attr_reader :definitions - - def initialize(node, cookbook_collection, run_list_expansion, events) - @node = node - @events = events - @run_list_expansion = run_list_expansion - @cookbook_collection = cookbook_collection - - # @resource_collection = Chef::ResourceCollection.new - # @immediate_notification_collection = Hash.new {|h,k| h[k] = []} - # @delayed_notification_collection = Hash.new {|h,k| h[k] = []} - # @loaded_recipes = {} - # @loaded_attributes = {} - # - - @definitions = Hash.new - @cookbook_order = nil - end - - # Run the compile phase of the chef run. Loads files in the following order: - # * Libraries - # * Attributes - # * LWRPs - # * Resource Definitions - # * Recipes - # - # Recipes are loaded in precisely the order specified by the expanded run_list. - # - # Other files are loaded in an order derived from the expanded run_list - # and the dependencies declared by cookbooks' metadata. See - # #cookbook_order for more information. - def compile - compile_libraries - compile_attributes - compile_lwrps - compile_resource_definitions - #compile_recipes - end - - # Extracts the cookbook names from the expanded run list, then iterates - # over the list, recursing through dependencies to give a run_list - # ordered array of cookbook names with no duplicates. Dependencies appear - # before the cookbook they depend on. - def cookbook_order - @cookbook_order ||= begin - ordered_cookbooks = [] - seen_cookbooks = {} - run_list_expansion.recipes.each do |recipe| - cookbook = Chef::Recipe.parse_recipe_name(recipe).first - add_cookbook_with_deps(ordered_cookbooks, seen_cookbooks, cookbook) - end - ordered_cookbooks - end - end - - # Loads library files from cookbooks according to #cookbook_order. - def compile_libraries - @events.library_load_start(count_files_by_segment(:libraries)) - cookbook_order.each do |cookbook| - load_libraries_from_cookbook(cookbook) - end - @events.library_load_complete - end - - # Loads attributes files from cookbooks. Attributes files are loaded - # according to #cookbook_order; within a cookbook, +default.rb+ is loaded - # first, then the remaining attributes files in lexical sort order. - def compile_attributes - @events.attribute_load_start(count_files_by_segment(:attributes)) - cookbook_order.each do |cookbook| - load_attributes_from_cookbook(cookbook) - end - @events.attribute_load_complete - end - - # Loads LWRPs according to #cookbook_order. Providers are loaded before - # resources on a cookbook-wise basis. - def compile_lwrps - lwrp_file_count = count_files_by_segment(:providers) + count_files_by_segment(:resources) - @events.lwrp_load_start(lwrp_file_count) - cookbook_order.each do |cookbook| - load_lwrps_from_cookbook(cookbook) - end - @events.lwrp_load_complete - end - - def compile_resource_definitions - @events.definition_load_start(count_files_by_segment(:definitions)) - cookbook_order.each do |cookbook| - load_resource_definitions_from_cookbook(cookbook) - end - @events.definition_load_complete - end - - - private - - def load_attributes_from_cookbook(cookbook_name) - list_of_attr_files = files_in_cookbook_by_segment(cookbook_name, :attributes).dup - if default_file = list_of_attr_files.find {|path| File.basename(path) == "default.rb" } - list_of_attr_files.delete(default_file) - load_attribute_file(cookbook_name.to_s, default_file) - end - - list_of_attr_files.each do |filename| - load_attribute_file(cookbook_name.to_s, filename) - end - end - - def load_attribute_file(cookbook_name, filename) - Chef::Log.debug("Node #{@node.name} loading cookbook #{cookbook_name}'s attribute file #{filename}") - attr_file_basename = ::File.basename(filename, ".rb") - @node.include_attribute("#{cookbook_name}::#{attr_file_basename}") - rescue Exception => e - @events.attribute_file_load_failed(filename, e) - raise - end - - def load_libraries_from_cookbook(cookbook_name) - files_in_cookbook_by_segment(cookbook_name, :libraries).each do |filename| - begin - Chef::Log.debug("Loading cookbook #{cookbook_name}'s library file: #{filename}") - Kernel.load(filename) - @events.library_file_loaded(filename) - rescue Exception => e - @events.library_file_load_failed(filename, e) - raise - end - end - end - - def load_lwrps_from_cookbook(cookbook_name) - files_in_cookbook_by_segment(cookbook_name, :providers).each do |filename| - load_lwrp_provider(cookbook_name, filename) - end - files_in_cookbook_by_segment(cookbook_name, :resources).each do |filename| - load_lwrp_resource(cookbook_name, filename) - end - end - - def load_lwrp_provider(cookbook_name, filename) - Chef::Log.debug("Loading cookbook #{cookbook_name}'s providers from #{filename}") - Chef::Provider.build_from_file(cookbook_name, filename, self) - @events.lwrp_file_loaded(filename) - rescue Exception => e - @events.lwrp_file_load_failed(filename, e) - raise - end - - def load_lwrp_resource(cookbook_name, filename) - Chef::Log.debug("Loading cookbook #{cookbook_name}'s resources from #{filename}") - Chef::Resource.build_from_file(cookbook_name, filename, self) - @events.lwrp_file_loaded(filename) - rescue Exception => e - @events.lwrp_file_load_failed(filename, e) - raise - end - - - def load_resource_definitions_from_cookbook(cookbook_name) - files_in_cookbook_by_segment(cookbook_name, :definitions).each do |filename| - begin - Chef::Log.debug("Loading cookbook #{cookbook_name}'s definitions from #{filename}") - resourcelist = Chef::ResourceDefinitionList.new - resourcelist.from_file(filename) - definitions.merge!(resourcelist.defines) do |key, oldval, newval| - Chef::Log.info("Overriding duplicate definition #{key}, new definition found in #{filename}") - newval - end - @events.definition_file_loaded(filename) - rescue Exception => e - @events.definition_file_load_failed(filename, e) - raise - end - end - end - - # Builds up the list of +ordered_cookbooks+ by first recursing through the - # dependencies of +cookbook+, and then adding +cookbook+ to the list of - # +ordered_cookbooks+. A cookbook is skipped if it appears in - # +seen_cookbooks+, otherwise it is added to the set of +seen_cookbooks+ - # before its dependencies are processed. - def add_cookbook_with_deps(ordered_cookbooks, seen_cookbooks, cookbook) - return false if seen_cookbooks.key?(cookbook) - - seen_cookbooks[cookbook] = true - each_cookbook_dep(cookbook) do |dependency| - add_cookbook_with_deps(ordered_cookbooks, seen_cookbooks, dependency) - end - ordered_cookbooks << cookbook - end - - - def count_files_by_segment(segment) - cookbook_collection.inject(0) do |count, ( cookbook_name, cookbook )| - count + cookbook.segment_filenames(segment).size - end - end - - # Lists the local paths to files in +cookbook+ of type +segment+ - # (attribute, recipe, etc.), sorted lexically. - def files_in_cookbook_by_segment(cookbook, segment) - cookbook_collection[cookbook].segment_filenames(segment).sort - end - - # Yields the name of each cookbook depended on by +cookbook_name+ in - # lexical sort order. - def each_cookbook_dep(cookbook_name, &block) - cookbook = cookbook_collection[cookbook_name] - cookbook.metadata.dependencies.keys.sort.each(&block) - end - - end - attr_reader :node, :cookbook_collection, :definitions # Needs to be settable so deploy can run a resource_collection independent |