diff options
Diffstat (limited to 'spec/integration/solo/solo_spec.rb')
-rw-r--r-- | spec/integration/solo/solo_spec.rb | 154 |
1 files changed, 103 insertions, 51 deletions
diff --git a/spec/integration/solo/solo_spec.rb b/spec/integration/solo/solo_spec.rb index bfcb74b45c..12a49dade6 100644 --- a/spec/integration/solo/solo_spec.rb +++ b/spec/integration/solo/solo_spec.rb @@ -1,21 +1,73 @@ +require "spec_helper" require "support/shared/integration/integration_helper" require "chef/mixin/shell_out" require "chef/run_lock" require "chef/config" require "timeout" require "fileutils" +require "chef-utils" +require "chef/win32/security" if ChefUtils.windows? -describe "chef-solo" do +describe ChefUtils::Dist::Solo::EXEC do include IntegrationSupport include Chef::Mixin::ShellOut - let(:chef_dir) { File.join(File.dirname(__FILE__), "..", "..", "..") } + let(:chef_dir) { File.join(__dir__, "..", "..", "..") } let(:cookbook_x_100_metadata_rb) { cb_metadata("x", "1.0.0") } let(:cookbook_ancient_100_metadata_rb) { cb_metadata("ancient", "1.0.0") } - let(:chef_solo) { "ruby bin/chef-solo --legacy-mode --minimal-ohai" } + let(:chef_solo) { "bundle exec #{ChefUtils::Dist::Solo::EXEC} --legacy-mode --minimal-ohai" } + + when_the_repository "creates nodes" do + let(:nodes_dir) { File.join(@repository_dir, "nodes") } + let(:node_file) { Dir[File.join(nodes_dir, "*.json")][0] } + + before do + file "config/solo.rb", <<~EOM + chef_repo_path "#{@repository_dir}" + EOM + result = shell_out("bundle exec chef-solo -c \"#{path_to("config/solo.rb")}\" -l debug", cwd: chef_dir) + result.error! + end + + describe "on unix", :unix_only do + describe "the nodes directory" do + it "has the correct permissions" do + expect(File.stat(nodes_dir).mode.to_s(8)[-3..-1]).to eq("700") + end + end + + describe "the node file" do + it "has the correct permissions" do + expect(File.stat(node_file).mode.to_s(8)[-4..-1]).to eq("0600") + end + end + end + + describe "on windows", :windows_only do + let(:read_mask) { Chef::ReservedNames::Win32::API::Security::GENERIC_READ } + let(:write_mask) { Chef::ReservedNames::Win32::API::Security::GENERIC_WRITE } + let(:execute_mask) { Chef::ReservedNames::Win32::API::Security::GENERIC_EXECUTE } + + describe "the nodes directory" do + it "has the correct permissions" do + expect(Chef::ReservedNames::Win32::File.file_access_check(nodes_dir, read_mask)).to be(true) + expect(Chef::ReservedNames::Win32::File.file_access_check(nodes_dir, write_mask)).to be(true) + expect(Chef::ReservedNames::Win32::File.file_access_check(nodes_dir, execute_mask)).to be(true) + end + end + + describe "the node file" do + it "has the correct permissions" do + expect(Chef::ReservedNames::Win32::File.file_access_check(node_file, read_mask)).to be(true) + expect(Chef::ReservedNames::Win32::File.file_access_check(node_file, write_mask)).to be(true) + expect(Chef::ReservedNames::Win32::File.file_access_check(node_file, execute_mask)).to be(false) + end + end + end + end when_the_repository "has a cookbook with a basic recipe" do before do @@ -24,26 +76,26 @@ describe "chef-solo" do end it "should complete with success" do - file "config/solo.rb", <<EOM -cookbook_path "#{path_to('cookbooks')}" -file_cache_path "#{path_to('config/cache')}" -EOM - result = shell_out("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug", :cwd => chef_dir) + file "config/solo.rb", <<~EOM + cookbook_path "#{path_to("cookbooks")}" + file_cache_path "#{path_to("config/cache")}" + EOM + result = shell_out("#{chef_solo} -c \"#{path_to("config/solo.rb")}\" -o 'x::default' -l debug", cwd: chef_dir) result.error! expect(result.stdout).to include("ITWORKS") end it "should evaluate its node.json file" do - file "config/solo.rb", <<EOM -cookbook_path "#{path_to('cookbooks')}" -file_cache_path "#{path_to('config/cache')}" -EOM + file "config/solo.rb", <<~EOM + cookbook_path "#{path_to("cookbooks")}" + file_cache_path "#{path_to("config/cache")}" + EOM - file "config/node.json", <<-E -{"run_list":["x::default"]} -E + file "config/node.json", <<~E + {"run_list":["x::default"]} + E - result = shell_out("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -j '#{path_to('config/node.json')}' -l debug", :cwd => chef_dir) + result = shell_out("#{chef_solo} -c \"#{path_to("config/solo.rb")}\" -j '#{path_to("config/node.json")}' -l debug", cwd: chef_dir) result.error! expect(result.stdout).to include("ITWORKS") end @@ -60,11 +112,11 @@ E end it "should exit with an error" do - file "config/solo.rb", <<EOM -cookbook_path "#{path_to('cookbooks')}" -file_cache_path "#{path_to('config/cache')}" -EOM - result = shell_out("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug", :cwd => chef_dir) + file "config/solo.rb", <<~EOM + cookbook_path "#{path_to("cookbooks")}" + file_cache_path "#{path_to("config/cache")}" + EOM + result = shell_out("#{chef_solo} -c \"#{path_to("config/solo.rb")}\" -o 'x::default' -l debug", cwd: chef_dir) expect(result.exitstatus).to eq(0) # For CHEF-5120 this becomes 1 expect(result.stdout).to include("WARN: MissingCookbookDependency") end @@ -74,14 +126,14 @@ EOM before do file "cookbooks/x/metadata.rb", cb_metadata("x", "1.0.0", "\nchef_version '~> 999.0'") file "cookbooks/x/recipes/default.rb", 'puts "ITWORKS"' - file "config/solo.rb", <<EOM -cookbook_path "#{path_to('cookbooks')}" -file_cache_path "#{path_to('config/cache')}" -EOM + file "config/solo.rb", <<~EOM + cookbook_path "#{path_to("cookbooks")}" + file_cache_path "#{path_to("config/cache")}" + EOM end it "should exit with an error" do - result = shell_out("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug", :cwd => chef_dir) + result = shell_out("#{chef_solo} -c \"#{path_to("config/solo.rb")}\" -o 'x::default' -l debug", cwd: chef_dir) expect(result.exitstatus).to eq(1) expect(result.stdout).to include("Chef::Exceptions::CookbookChefVersionMismatch") end @@ -91,14 +143,14 @@ EOM before do file "cookbooks/x/metadata.rb", cb_metadata("x", "1.0.0", "\nohai_version '~> 999.0'") file "cookbooks/x/recipes/default.rb", 'puts "ITWORKS"' - file "config/solo.rb", <<EOM -cookbook_path "#{path_to('cookbooks')}" -file_cache_path "#{path_to('config/cache')}" -EOM + file "config/solo.rb", <<~EOM + cookbook_path "#{path_to("cookbooks")}" + file_cache_path "#{path_to("config/cache")}" + EOM end it "should exit with an error" do - result = shell_out("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug", :cwd => chef_dir) + result = shell_out("#{chef_solo} -c \"#{path_to("config/solo.rb")}\" -o 'x::default' -l debug", cwd: chef_dir) expect(result.exitstatus).to eq(1) expect(result.stdout).to include("Chef::Exceptions::CookbookOhaiVersionMismatch") end @@ -109,41 +161,41 @@ EOM directory "logs" file "logs/runs.log", "" file "cookbooks/x/metadata.rb", cookbook_x_100_metadata_rb - file "cookbooks/x/recipes/default.rb", <<EOM -ruby_block "sleeping" do - block do - retries = 200 - while IO.read(Chef::Config[:log_location]) !~ /Chef client [0-9]+ is running, will wait for it to finish and then run./ - sleep 0.1 - raise "we ran out of retries" if ( retries -= 1 ) <= 0 - end - end -end -EOM + file "cookbooks/x/recipes/default.rb", <<~EOM + ruby_block "sleeping" do + block do + retries = 200 + while IO.read(Chef::Config[:log_location][0]) !~ /.* is running, will wait for it to finish and then run./ + sleep 0.1 + raise "we ran out of retries" if ( retries -= 1 ) <= 0 + end + end + end + EOM end it "while running solo concurrently" do - file "config/solo.rb", <<EOM -cookbook_path "#{path_to('cookbooks')}" -file_cache_path "#{path_to('config/cache')}" -EOM + file "config/solo.rb", <<~EOM + cookbook_path "#{path_to("cookbooks")}" + file_cache_path "#{path_to("config/cache")}" + EOM # We have a timeout protection here so that if due to some bug # run_lock gets stuck we can discover it. expect do Timeout.timeout(120) do - chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..") + chef_dir = File.join(__dir__, "..", "..", "..") threads = [] # Instantiate the first chef-solo run threads << Thread.new do - s1 = Process.spawn("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug -L #{path_to('logs/runs.log')}", :chdir => chef_dir) + s1 = Process.spawn("#{chef_solo} -c \"#{path_to("config/solo.rb")}\" -o 'x::default' -l debug -L #{path_to("logs/runs.log")}", chdir: chef_dir) Process.waitpid(s1) end # Instantiate the second chef-solo run threads << Thread.new do - s2 = Process.spawn("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug -L #{path_to('logs/runs.log')}", :chdir => chef_dir) + s2 = Process.spawn("#{chef_solo} -c \"#{path_to("config/solo.rb")}\" -o 'x::default' -l debug -L #{path_to("logs/runs.log")}", chdir: chef_dir) Process.waitpid(s2) end @@ -157,10 +209,10 @@ EOM run_log = File.read(path_to("logs/runs.log")) # second run should have a message which indicates it's waiting for the first run - expect(run_log).to match(/Chef client [0-9]+ is running, will wait for it to finish and then run./) + expect(run_log).to match(/.* is running, will wait for it to finish and then run./) # both of the runs should succeed - expect(run_log.lines.reject { |l| !l.include? "INFO: Chef Run complete in" }.length).to eq(2) + expect(run_log.lines.reject { |l| !l.include? "Run complete in" }.length).to eq(2) end end |