From 8660bf4c410cc60b4028fc1f44a1fe67e71b8648 Mon Sep 17 00:00:00 2001 From: danielsdeleo Date: Thu, 29 Nov 2012 12:55:18 -0800 Subject: [CHEF-3376] Load all filetypes in run_list order * Extract file loading for non-recipe types to implementation class. * Load libraries, LWRPs, Resource Definitions in approximate run_list order * Should not be a breaking change on chef-client, since the order is essentially random right now. On chef-solo, files from cookbooks that don't appear in the expanded run_list plus dependency graph will not be loaded, which is a change from the previous behavior. --- spec/unit/run_context_spec.rb | 116 +++++++++++++++++++++++++++++++++++------- 1 file changed, 99 insertions(+), 17 deletions(-) (limited to 'spec/unit/run_context_spec.rb') diff --git a/spec/unit/run_context_spec.rb b/spec/unit/run_context_spec.rb index b742a2f1c7..48f26fbf5c 100644 --- a/spec/unit/run_context_spec.rb +++ b/spec/unit/run_context_spec.rb @@ -22,6 +22,23 @@ require 'spec_helper' Chef::Log.level = :debug +# Keeps track of what file got loaded in what order. +module LibraryLoadOrder + extend self + + def load_order + @load_order ||= [] + end + + def reset! + @load_order = nil + end + + def record(file) + load_order << file + end +end + describe Chef::RunContext do before(:each) do @chef_repo_path = File.expand_path(File.join(CHEF_SPEC_DATA, "run_context", "cookbooks")) @@ -48,18 +65,19 @@ describe Chef::RunContext do # This test relies on fixture data in spec/data/run_context/cookbooks. # The behaviors described in these examples are affected by the metadata.rb - # files in those cookbooks. + # files and attributes files in those cookbooks. + # + # Attribute files in the fixture data will append their + # "cookbook_name::attribute_file_name" to the node's `:attr_load_order` + # attribute when loaded. describe "loading attribute files" do it "loads default.rb first, then other files in sort order" do @node.run_list("dependency1::default") @expansion = (@node.run_list.expand('_default')) - @run_context.should_receive(:load_attribute_file).with("dependency1", fixture_cb_path("dependency1/attributes/default.rb")).ordered - @run_context.should_receive(:load_attribute_file).with("dependency1", fixture_cb_path("dependency1/attributes/aa_first.rb")).ordered - @run_context.should_receive(:load_attribute_file).with("dependency1", fixture_cb_path("dependency1/attributes/zz_last.rb")).ordered - @run_context.load_attributes_in_run_list_order(@expansion) + @node[:attr_load_order].should == ["dependency1::default", "dependency1::aa_first", "dependency1::zz_last"] end it "loads dependencies before loading the depending cookbook's attributes" do @@ -68,14 +86,14 @@ describe Chef::RunContext do @node.run_list("test-with-deps::default", "test-with-deps::server") @expansion = (@node.run_list.expand('_default')) - # dependencies are stored in a hash so therefore unordered, but they should be loaded in sort order - @run_context.should_receive(:load_attribute_file).with("dependency1", fixture_cb_path("dependency1/attributes/default.rb")).ordered - @run_context.should_receive(:load_attribute_file).with("dependency1", fixture_cb_path("dependency1/attributes/aa_first.rb")).ordered - @run_context.should_receive(:load_attribute_file).with("dependency1", fixture_cb_path("dependency1/attributes/zz_last.rb")).ordered - @run_context.should_receive(:load_attribute_file).with("dependency2", fixture_cb_path("dependency2/attributes/default.rb")).ordered - @run_context.should_receive(:load_attribute_file).with("test-with-deps", fixture_cb_path("test-with-deps/attributes/default.rb")).ordered - @run_context.load_attributes_in_run_list_order(@expansion) + + # dependencies are stored in a hash so therefore unordered, but they should be loaded in sort order + @node[:attr_load_order].should == ["dependency1::default", + "dependency1::aa_first", + "dependency1::zz_last", + "dependency2::default", + "test-with-deps::default"] end it "does not follow infinite dependency loops" do @@ -83,22 +101,86 @@ describe Chef::RunContext do @expansion = (@node.run_list.expand('_default')) # Circular deps should not cause infinite loops - @run_context.should_receive(:load_attribute_file).with("circular-dep2", fixture_cb_path("circular-dep2/attributes/default.rb")).ordered - @run_context.should_receive(:load_attribute_file).with("circular-dep1", fixture_cb_path("circular-dep1/attributes/default.rb")).ordered - @run_context.should_receive(:load_attribute_file).with("test-with-circular-deps", fixture_cb_path("test-with-circular-deps/attributes/default.rb")).ordered - @run_context.load_attributes_in_run_list_order(@expansion) + + @node[:attr_load_order].should == ["circular-dep2::default", "circular-dep1::default", "test-with-circular-deps::default"] end it "loads attributes from cookbooks that don't have a default.rb attribute file" do @node.run_list("no-default-attr::default.rb") @expansion = (@node.run_list.expand('_default')) - @run_context.should_receive(:load_attribute_file).with("no-default-attr", fixture_cb_path("no-default-attr/attributes/server.rb")) + #@run_context.should_receive(:load_attribute_file).with("no-default-attr", fixture_cb_path("no-default-attr/attributes/server.rb")) @run_context.load_attributes_in_run_list_order(@expansion) + + @node[:attr_load_order].should == ["no-default-attr::server"] + end + end + + describe "loading libraries" do + before do + LibraryLoadOrder.reset! + end + + # One big test for everything. Individual behaviors are tested by the attribute code above. + it "loads libraries in run list order" do + @node.run_list("test-with-deps::default", "test-with-circular-deps::default") + @expansion = (@node.run_list.expand('_default')) + + @run_context.load_libraries_in_run_list_order(@expansion) + LibraryLoadOrder.load_order.should == ["dependency1", "dependency2", "test-with-deps", "circular-dep2", "circular-dep1", "test-with-circular-deps"] + end + end + + describe "loading LWRPs" do + before do + LibraryLoadOrder.reset! + end + + # One big test for everything. Individual behaviors are tested by the attribute code above. + it "loads LWRPs in run list order" do + @node.run_list("test-with-deps::default", "test-with-circular-deps::default") + @expansion = (@node.run_list.expand('_default')) + + @run_context.load_lwrps_in_run_list_order(@expansion) + LibraryLoadOrder.load_order.should == ["dependency1-provider", + "dependency1-resource", + "dependency2-provider", + "dependency2-resource", + "test-with-deps-provider", + "test-with-deps-resource", + "circular-dep2-provider", + "circular-dep2-resource", + "circular-dep1-provider", + "circular-dep1-resource", + "test-with-circular-deps-provider", + "test-with-circular-deps-resource"] end end + describe "loading resource definitions" do + before do + LibraryLoadOrder.reset! + end + + # One big test for all load order concerns. Individual behaviors are tested + # by the attribute code above. + it "loads resource definitions in run list order" do + @node.run_list("test-with-deps::default", "test-with-circular-deps::default") + @expansion = (@node.run_list.expand('_default')) + + @run_context.load_resource_definitions_in_run_list_order(@expansion) + LibraryLoadOrder.load_order.should == ["dependency1-definition", + "dependency2-definition", + "test-with-deps-definition", + "circular-dep2-definition", + "circular-dep1-definition", + "test-with-circular-deps-definition"] + end + + end + + describe "after loading the cookbooks" do before do @run_context.load(@node.run_list.expand('_default')) -- cgit v1.2.1