summaryrefslogtreecommitdiff
path: root/lib/chef/client.rb
diff options
context:
space:
mode:
authorsdelano <stephen@opscode.com>2017-04-06 09:21:46 -0700
committersdelano <stephen@opscode.com>2017-04-06 10:00:35 -0700
commitadb0a55cb63f394ed23450e41f8a93cd017d225a (patch)
tree0aff07ce4b93eac5d5a31641596ea20653867bcd /lib/chef/client.rb
parentc36bf3013e7c1f54efc6635145a5fb28daf17c7a (diff)
downloadchef-adb0a55cb63f394ed23450e41f8a93cd017d225a.tar.gz
server enforced required recipe
when the chef-server is configured to serve a requried recipe, chef-client shall load the recipe into the run context and execute it as part of the converge phase. if the chef-server is NOT configured, it will return a 404 and chef-client will continue normally. Signed-off-by: Stephen Delano <stephen@chef.io>
Diffstat (limited to 'lib/chef/client.rb')
-rw-r--r--lib/chef/client.rb47
1 files changed, 47 insertions, 0 deletions
diff --git a/lib/chef/client.rb b/lib/chef/client.rb
index c3eaa02bed..8dea2afecf 100644
--- a/lib/chef/client.rb
+++ b/lib/chef/client.rb
@@ -280,6 +280,8 @@ class Chef
run_context = setup_run_context
+ load_required_recipe(@rest, run_context) unless Chef::Config[:solo_legacy_mode]
+
if Chef::Config[:audit_mode] != :audit_only
converge_error = converge_and_save(run_context)
end
@@ -515,6 +517,51 @@ class Chef
end
#
+ # Adds a required recipe as specified by the Chef Server
+ #
+ # @return The modified run context
+ #
+ # @api private
+ #
+ # TODO: @rest doesn't appear to be used anywhere outside
+ # of client.register except for here. If it's common practice
+ # to create your own rest client, perhaps we should do that
+ # here but it seems more appropriate to reuse one that we
+ # know is already created. for ease of testing, we'll pass
+ # the existing rest client in as a parameter
+ #
+ def load_required_recipe(rest, run_context)
+ begin
+ required_recipe_contents = rest.get("required_recipe")
+ Chef::FileCache.store("required_recipe", required_recipe_contents)
+ required_recipe_file = Chef::FileCache.load("required_recipe", false)
+
+ # TODO: add integration tests with resource reporting turned on
+ # (presumably requires changes to chef-zero)
+ #
+ # Chef::Recipe.new takes a cookbook name and a recipe name along
+ # with the run context. These names are eventually used in the
+ # resource reporter, and if the cookbook name cannot be found in the
+ # cookbook collection then we will fail with an exception. Cases where
+ # we currently also fail:
+ # - specific recipes
+ # - chef-apply would fail if resource reporting was enabled
+ #
+ recipe = Chef::Recipe.new(nil, nil, run_context)
+ recipe.from_file(required_recipe_file)
+ run_context
+ rescue Net::HTTPServerException => e
+ case e.response
+ when Net::HTTPNotFound
+ Chef::Log.info("Required Recipe not found")
+ else
+ raise
+ end
+ end
+
+ end
+
+ #
# The PolicyBuilder strategy for figuring out run list and cookbooks.
#
# @return [Chef::PolicyBuilder::Policyfile, Chef::PolicyBuilder::ExpandNodeObject]