diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2018-02-26 13:44:30 -0800 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2018-02-26 13:44:30 -0800 |
commit | 2173e31a10e668b8a5c6e088c8d3359333ec13b4 (patch) | |
tree | e06ea3f31dfce814aa017f65fe613a797762741f | |
parent | b3a9add86336ebc4101fdecb52caa99bc219466b (diff) | |
download | chef-2173e31a10e668b8a5c6e088c8d3359333ec13b4.tar.gz |
Don't use supervisor process for one-shot / command-line runs
without --interval we default to --no-fork, with --interval we default
to running --fork. --once and --daemonize are handled before this code
so they will also DTRT.
Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
-rw-r--r-- | chef-config/lib/chef-config/config.rb | 4 | ||||
-rw-r--r-- | lib/chef/application/client.rb | 10 | ||||
-rw-r--r-- | spec/integration/client/client_spec.rb | 98 | ||||
-rw-r--r-- | spec/unit/application/client_spec.rb | 48 |
4 files changed, 142 insertions, 18 deletions
diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb index d5badcc58f..9d11ba9dc4 100644 --- a/chef-config/lib/chef-config/config.rb +++ b/chef-config/lib/chef-config/config.rb @@ -4,7 +4,7 @@ # Author:: AJ Christensen (<aj@chef.io>) # Author:: Mark Mzyk (<mmzyk@chef.io>) # Author:: Kyle Goodwin (<kgoodwin@primerevenue.com>) -# Copyright:: Copyright 2008-2017, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -440,7 +440,7 @@ module ChefConfig default :splay, nil default :why_run, false default :color, false - default :client_fork, true + default :client_fork, nil default :ez, false default :enable_reporting, true default :enable_reporting_url_fatals, false diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb index 0834e5f037..706ba93ca0 100644 --- a/lib/chef/application/client.rb +++ b/lib/chef/application/client.rb @@ -2,7 +2,7 @@ # Author:: AJ Christensen (<aj@chef.io) # Author:: Christopher Brown (<cb@chef.io>) # Author:: Mark Mzyk (mmzyk@chef.io) -# Copyright:: Copyright 2008-2016, Chef Software, Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -228,8 +228,7 @@ class Chef::Application::Client < Chef::Application option :client_fork, :short => "-f", :long => "--[no-]fork", - :description => "Fork client", - :boolean => true + :description => "Fork client" option :recipe_url, :long => "--recipe-url=RECIPE_URL", @@ -362,6 +361,11 @@ class Chef::Application::Client < Chef::Application Chef::Config[:splay] = nil end + # supervisor processes are enabled by default for interval-running processes but not for one-shot runs + if Chef::Config[:client_fork].nil? + Chef::Config[:client_fork] = !!Chef::Config[:interval] + end + if !Chef::Config[:client_fork] && Chef::Config[:interval] && !Chef::Platform.windows? Chef::Application.fatal!(unforked_interval_error_message) end diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb index de12b8ba8e..730e304bd5 100644 --- a/spec/integration/client/client_spec.rb +++ b/spec/integration/client/client_spec.rb @@ -624,4 +624,102 @@ EOM expect(command.stdout).not_to include("INFO") end end + + when_the_repository "has a cookbook that knows if we're running forked" do + before do + file "cookbooks/x/recipes/default.rb", <<~EOM + puts Chef::Config[:client_fork] ? "WITHFORK" : "NOFORK" +EOM + file "config/client.rb", <<EOM +local_mode true +cookbook_path "#{path_to('cookbooks')}" +EOM + end + + it "chef-client runs by default with no supervisor" do + command = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default'", :cwd => chef_dir) + command.error! + expect(command.stdout).to include("NOFORK") + end + + it "chef-solo runs by default with no supervisor" do + command = shell_out("#{chef_solo} -c \"#{path_to('config/client.rb')}\" -o 'x::default'", :cwd => chef_dir) + command.error! + expect(command.stdout).to include("NOFORK") + end + + it "chef-client --no-fork does not fork" do + command = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork", :cwd => chef_dir) + command.error! + expect(command.stdout).to include("NOFORK") + end + + it "chef-solo --no-fork does not fork" do + command = shell_out("#{chef_solo} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --no-fork", :cwd => chef_dir) + command.error! + expect(command.stdout).to include("NOFORK") + end + + it "chef-client with --fork uses a supervisor" do + command = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --fork", :cwd => chef_dir) + command.error! + expect(command.stdout).to include("WITHFORK") + end + + it "chef-solo with --fork uses a supervisor" do + command = shell_out("#{chef_solo} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --fork", :cwd => chef_dir) + command.error! + expect(command.stdout).to include("WITHFORK") + end + end + + when_the_repository "has a cookbook that knows if we're running forked, and configures forking in config.rb" do + before do + file "cookbooks/x/recipes/default.rb", <<~EOM + puts Chef::Config[:client_fork] ? "WITHFORK" : "NOFORK" +EOM + file "config/client.rb", <<EOM +local_mode true +cookbook_path "#{path_to('cookbooks')}" +client_fork true +EOM + end + + it "chef-client uses a supervisor" do + command = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default'", :cwd => chef_dir) + command.error! + expect(command.stdout).to include("WITHFORK") + end + + it "chef-solo uses a supervisor" do + command = shell_out("#{chef_solo} -c \"#{path_to('config/client.rb')}\" -o 'x::default'", :cwd => chef_dir) + command.error! + expect(command.stdout).to include("WITHFORK") + end + end + + when_the_repository "has a cookbook that knows if we're running forked, and configures no-forking in config.rb" do + before do + file "cookbooks/x/recipes/default.rb", <<~EOM + puts Chef::Config[:client_fork] ? "WITHFORK" : "NOFORK" +EOM + file "config/client.rb", <<EOM +local_mode true +cookbook_path "#{path_to('cookbooks')}" +client_fork false +EOM + end + + it "chef-client uses a supervisor" do + command = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default'", :cwd => chef_dir) + command.error! + expect(command.stdout).to include("NOFORK") + end + + it "chef-solo uses a supervisor" do + command = shell_out("#{chef_solo} -c \"#{path_to('config/client.rb')}\" -o 'x::default'", :cwd => chef_dir) + command.error! + expect(command.stdout).to include("NOFORK") + end + end end diff --git a/spec/unit/application/client_spec.rb b/spec/unit/application/client_spec.rb index 825a4e7aac..1d9819ffa7 100644 --- a/spec/unit/application/client_spec.rb +++ b/spec/unit/application/client_spec.rb @@ -1,6 +1,6 @@ # # Author:: AJ Christensen (<aj@junglist.gen.nz>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright 2008-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -107,6 +107,7 @@ describe Chef::Application::Client, "reconfigure" do shared_examples "sets the configuration" do |cli_arguments, expected_config| describe cli_arguments do before do + cli_arguments ||= "" ARGV.replace(cli_arguments.split) app.reconfigure end @@ -144,6 +145,32 @@ describe Chef::Application::Client, "reconfigure" do end end + describe "--[no]-fork" do + before do + Chef::Config[:interval] = nil # FIXME: we're overriding the before block setting this + end + + context "by default" do + it_behaves_like "sets the configuration", "", client_fork: false + end + + context "with --fork" do + it_behaves_like "sets the configuration", "--fork", client_fork: true + end + + context "with --no-fork" do + it_behaves_like "sets the configuration", "--no-fork", client_fork: false + end + + context "with an interval" do + it_behaves_like "sets the configuration", "--interval 1800", client_fork: true + end + + context "with daemonize" do + it_behaves_like "sets the configuration", "--daemonize", client_fork: true + end + end + describe "--config-option" do context "with a single value" do it_behaves_like "sets the configuration", "--config-option chef_server_url=http://example", @@ -186,21 +213,16 @@ describe Chef::Application::Client, "reconfigure" do Chef::Config[:splay] = nil end - context "when interval is given" do - before do - Chef::Config[:interval] = 600 - allow(ChefConfig).to receive(:windows?).and_return(false) - end - - it "should terminate with message" do - expect(Chef::Application).to receive(:fatal!).with( -"Unforked chef-client interval runs are disabled in Chef 12. + it "should terminal with message when interval is given" do + Chef::Config[:interval] = 600 + allow(ChefConfig).to receive(:windows?).and_return(false) + expect(Chef::Application).to receive(:fatal!).with( + "Unforked chef-client interval runs are disabled in Chef 12. Configuration settings: interval = 600 seconds Enable chef-client interval runs by setting `:client_fork = true` in your config file or adding `--fork` to your command line options." - ) - app.reconfigure - end + ) + app.reconfigure end context "when interval is given on windows" do |