diff options
author | Lamont Granquist <454857+lamont-granquist@users.noreply.github.com> | 2021-07-06 10:57:07 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-06 10:57:07 -0700 |
commit | 35ccb4048aba082193acf404027b090934f9b544 (patch) | |
tree | 4c436ee033e8d01a595205534ce075839c4488a6 | |
parent | aed0f264dc104e3976b34788209c61767765e781 (diff) | |
parent | 18be6b87551174018628ad8f190c3e20add29ec7 (diff) | |
download | chef-35ccb4048aba082193acf404027b090934f9b544.tar.gz |
Merge pull request #11741 from chef/lcg/policyfile-override
Support override run_lists in policyfiles
-rw-r--r-- | lib/chef/policy_builder/policyfile.rb | 82 | ||||
-rw-r--r-- | spec/unit/policy_builder/dynamic_spec.rb | 5 | ||||
-rw-r--r-- | spec/unit/policy_builder/policyfile_spec.rb | 33 |
3 files changed, 71 insertions, 49 deletions
diff --git a/lib/chef/policy_builder/policyfile.rb b/lib/chef/policy_builder/policyfile.rb index 35282bf915..ec2082d159 100644 --- a/lib/chef/policy_builder/policyfile.rb +++ b/lib/chef/policy_builder/policyfile.rb @@ -81,10 +81,12 @@ class Chef attr_reader :ohai_data attr_reader :json_attribs attr_reader :run_context + attr_reader :override_runlist def initialize(node_name, ohai_data, json_attribs, override_runlist, events) @node_name = node_name @ohai_data = ohai_data + @override_runlist = override_runlist @json_attribs = json_attribs @events = events @@ -94,10 +96,6 @@ class Chef raise UnsupportedFeature, "Policyfile does not support chef-solo. Use #{ChefUtils::Dist::Infra::CLIENT} local mode instead." end - if override_runlist - raise UnsupportedFeature, "Policyfile does not support override run lists. Use named run_lists instead." - end - if json_attribs && json_attribs.key?("run_list") raise UnsupportedFeature, "Policyfile does not support setting the run_list in json data." end @@ -107,19 +105,6 @@ class Chef end end - ## API Compat ## - # Methods related to unsupported features - - # Override run_list is not supported. - def original_runlist - nil - end - - # Override run_list is not supported. - def override_runlist - nil - end - # Policyfile gives you the run_list already expanded, but users of this # class may expect to get a run_list expansion compatible object by # calling this method. @@ -152,13 +137,15 @@ class Chef node.consume_external_attrs(ohai_data, json_attribs) + setup_run_list_override + expand_run_list apply_policyfile_attributes Chef::Log.info("Run List is [#{run_list}]") - Chef::Log.info("Run List expands to [#{run_list_with_versions_for_display.join(", ")}]") + Chef::Log.info("Run List expands to [#{run_list_with_versions_for_display(run_list).join(", ")}]") - events.node_load_completed(node, run_list_with_versions_for_display, Chef::Config) + events.node_load_completed(node, run_list_with_versions_for_display(run_list), Chef::Config) events.run_list_expanded(run_list_expansion_ish) # we must do this after `node.consume_external_attrs` @@ -194,6 +181,11 @@ class Chef events.cookbook_compilation_start(run_context) run_context.load(run_list_expansion_ish) + if specific_recipes + specific_recipes.each do |recipe_file| + run_context.load_recipe_file(recipe_file) + end + end events.cookbook_compilation_complete(run_context) @@ -231,21 +223,13 @@ class Chef cookbooks_to_sync end - # Whether or not this is a temporary policy. Since PolicyBuilder doesn't - # support override_runlist, this is always false. - # - # @return [false] - def temporary_policy? - false - end - ## Internal Public API ## # @api private # # Generates an array of strings with recipe names including version and # identifier info. - def run_list_with_versions_for_display + def run_list_with_versions_for_display(run_list) run_list.map do |recipe_spec| cookbook, recipe = parse_recipe_spec(recipe_spec) lock_data = cookbook_lock_for(cookbook) @@ -287,7 +271,7 @@ class Chef # @api private def parse_recipe_spec(recipe_spec) - rmatch = recipe_spec.match(/recipe\[([^:]+)::([^:]+)\]/) + rmatch = recipe_spec.to_s.match(/recipe\[([^:]+)::([^:]+)\]/) if rmatch.nil? raise PolicyfileError, "invalid recipe specification #{recipe_spec} in Policyfile from #{policyfile_location}" else @@ -301,7 +285,10 @@ class Chef end # @api private + # @return [Array<String>] def run_list + return override_runlist.map(&:to_s) if override_runlist + if named_run_list_requested? named_run_list || raise(ConfigurationError, "Policy '#{retrieved_policy_name}' revision '#{revision_id}' does not have named_run_list '#{named_run_list_name}'" + @@ -458,7 +445,7 @@ class Chef # should be reduced to a single call. def cookbooks_to_sync @cookbook_to_sync ||= begin - events.cookbook_resolution_start(run_list_with_versions_for_display) + events.cookbook_resolution_start(run_list_with_versions_for_display(policy["run_list"])) cookbook_versions_by_name = cookbook_locks.inject({}) do |cb_map, (name, lock_data)| cb_map[name] = manifest_for(name, lock_data) @@ -470,7 +457,7 @@ class Chef end rescue Exception => e # TODO: wrap/munge exception to provide helpful error output - events.cookbook_resolution_failed(run_list_with_versions_for_display, e) + events.cookbook_resolution_failed(run_list_with_versions_for_display(policy["run_list"]), e) raise end @@ -509,6 +496,13 @@ class Chef Chef::Config end + # Indicates whether the policy is temporary, which means an + # override_runlist was provided. Chef::Client uses this to decide whether + # to do the final node save at the end of the run or not. + def temporary_policy? + node.override_runlist_set? + end + private # This method injects the run_context and into the Chef class. @@ -567,6 +561,32 @@ class Chef Chef::CookbookVersion.from_cb_artifact_data(raw_manifest) end + def setup_run_list_override + unless override_runlist.nil? + runlist_override_sanity_check! + node.override_runlist = override_runlist + Chef::Log.warn "Run List override has been provided." + Chef::Log.warn "Original Run List: [#{node.primary_runlist}]" + Chef::Log.warn "Overridden Run List: [#{node.run_list}]" + end + end + + # Ensures runlist override contains RunListItem instances + def runlist_override_sanity_check! + # Convert to array and remove whitespace + if override_runlist.is_a?(String) + @override_runlist = override_runlist.split(",").map(&:strip) + end + @override_runlist = [override_runlist].flatten.compact + override_runlist.map! do |item| + if item.is_a?(Chef::RunList::RunListItem) + item + else + Chef::RunList::RunListItem.new(item) + end + end + end + end end end diff --git a/spec/unit/policy_builder/dynamic_spec.rb b/spec/unit/policy_builder/dynamic_spec.rb index d61dec4bc8..c886f5d5e7 100644 --- a/spec/unit/policy_builder/dynamic_spec.rb +++ b/spec/unit/policy_builder/dynamic_spec.rb @@ -55,11 +55,6 @@ describe Chef::PolicyBuilder::Dynamic do expect(policy_builder).to respond_to(:load_node) end - it "forwards #original_runlist" do - expect(implementation).to receive(:original_runlist) - policy_builder.original_runlist - end - it "forwards #run_context" do expect(implementation).to receive(:run_context) policy_builder.run_context diff --git a/spec/unit/policy_builder/policyfile_spec.rb b/spec/unit/policy_builder/policyfile_spec.rb index 6be0da8f4d..0f19bca070 100644 --- a/spec/unit/policy_builder/policyfile_spec.rb +++ b/spec/unit/policy_builder/policyfile_spec.rb @@ -146,10 +146,6 @@ describe Chef::PolicyBuilder::Policyfile do Chef::PolicyBuilder::Policyfile.new(node_name, ohai_data, json_attribs, override_runlist, events) end - it "always gives `false` for #temporary_policy?" do - expect(initialize_pb.temporary_policy?).to be_falsey - end - context "chef-solo" do before { Chef::Config[:solo_legacy_mode] = true } @@ -161,8 +157,8 @@ describe Chef::PolicyBuilder::Policyfile do context "when given an override run_list" do let(:override_runlist) { "recipe[foo],recipe[bar]" } - it "errors on create" do - expect { initialize_pb }.to raise_error(err_namespace::UnsupportedFeature) + it "does not error" do + expect { initialize_pb }.not_to raise_error end end @@ -323,7 +319,7 @@ describe Chef::PolicyBuilder::Policyfile do "example2::server@4.2.0 (feab40e)", ] - expect(policy_builder.run_list_with_versions_for_display).to eq(expected) + expect(policy_builder.run_list_with_versions_for_display(policy_builder.run_list)).to eq(expected) end it "generates a RunListExpansion-alike object for feeding to the CookbookCompiler" do @@ -577,11 +573,9 @@ describe Chef::PolicyBuilder::Policyfile do expect(node.automatic_attrs[:policy_name]).to eq("policy_name_from_node_json") expect(node.automatic_attrs[:policy_group]).to eq("policy_group_from_node_json") expect(node.automatic_attrs[:chef_environment]).to eq("policy_group_from_node_json") - end end - end it "resets default and override data" do @@ -664,7 +658,7 @@ describe Chef::PolicyBuilder::Policyfile do expect(policy_builder.run_list).to eq([ "recipe[example1::default]" ]) expected_expansion = Chef::PolicyBuilder::Policyfile::RunListExpansionIsh.new([ "example1::default" ], []) expect(policy_builder.run_list_expansion).to eq(expected_expansion) - expect(policy_builder.run_list_with_versions_for_display).to eq(["example1::default@2.3.5 (168d210)"]) + expect(policy_builder.run_list_with_versions_for_display(policy_builder.run_list)).to eq(["example1::default@2.3.5 (168d210)"]) expect(node.run_list).to eq([ Chef::RunList::RunListItem.new("recipe[example1::default]") ]) expect(node[:roles]).to eq( [] ) expect(node[:recipes]).to eq( ["example1::default"] ) @@ -675,7 +669,22 @@ describe Chef::PolicyBuilder::Policyfile do end end + end + + context "when an override run_list is given" do + let(:override_runlist) { [ "recipe[example2::server]" ] } + before do + policy_builder.build_node + end + + it "gives `true` for #temporary_policy?" do + expect(policy_builder.temporary_policy?).to be true + end + + it "returns the override_runlist for the run_list" do + expect(policy_builder.run_list).to eql override_runlist + end end describe "hoisting attribute values" do @@ -826,6 +835,7 @@ describe Chef::PolicyBuilder::Policyfile do end include_examples "fetching cookbooks when they exist" + end end @@ -863,10 +873,7 @@ describe Chef::PolicyBuilder::Policyfile do end end - end end - end - end |