summaryrefslogtreecommitdiff
path: root/spec/integration/client/exit_code_spec.rb
blob: 18f44a3e346bec566c5f09354503affa5302a365 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

require "support/shared/integration/integration_helper"
require "chef/mixin/shell_out"
require "tiny_server"
require "tmpdir"
require "chef/platform"

describe "chef-client" do

  include IntegrationSupport
  include Chef::Mixin::ShellOut

  let(:chef_dir) { File.join(File.dirname(__FILE__), "..", "..", "..", "bin") }

  # Invoke `chef-client` as `ruby PATH/TO/chef-client`. This ensures the
  # following constraints are satisfied:
  # * Windows: windows can only run batch scripts as bare executables. Rubygems
  # creates batch wrappers for installed gems, but we don't have batch wrappers
  # in the source tree.
  # * Other `chef-client` in PATH: A common case is running the tests on a
  # machine that has omnibus chef installed. In that case we need to ensure
  # we're running `chef-client` from the source tree and not the external one.
  # cf. CHEF-4914
  let(:chef_client) { "bundle exec #{Chef::Dist::CLIENT} --no-fork --minimal-ohai" }

  let(:critical_env_vars) { %w{PATH RUBYOPT BUNDLE_GEMFILE GEM_PATH}.map { |o| "#{o}=#{ENV[o]}" } .join(" ") }

  when_the_repository "uses RFC 062 defined exit codes" do

    def setup_client_rb
      file "config/client.rb", <<~EOM
        local_mode true
        cookbook_path "#{path_to("cookbooks")}"
      EOM
    end

    def run_chef_client_and_expect_exit_code(exit_code)
      shell_out!("#{chef_client} -c \"#{path_to("config/client.rb")}\" -o 'x::default'",
        cwd: chef_dir,
        returns: [exit_code])
    end

    context "has a cookbook" do
      context "with a library" do
        context "which cannot be loaded" do
          before do
            file "cookbooks/x/recipes/default.rb", ""
            file "cookbooks/x/libraries/error.rb", "require 'does/not/exist'"
          end

          it "exits with GENERIC_FAILURE, 1" do
            setup_client_rb
            run_chef_client_and_expect_exit_code 1
          end
        end
      end

      context "with a recipe" do
        context "which throws an error" do
          before do file "cookbooks/x/recipes/default.rb", "raise 'BOOM'" end

          it "exits with GENERIC_FAILURE, 1" do
            setup_client_rb
            run_chef_client_and_expect_exit_code 1
          end
        end

        context "with a recipe which calls Chef::Application.fatal with a non-RFC exit code" do
          before do file "cookbooks/x/recipes/default.rb", "Chef::Application.fatal!('BOOM', 123)" end

          it "exits with the GENERIC_FAILURE exit code, 1" do
            setup_client_rb
            run_chef_client_and_expect_exit_code 1
          end
        end

        context "with a recipe which calls Chef::Application.exit with a non-RFC exit code" do
          before do file "cookbooks/x/recipes/default.rb", "Chef::Application.exit!('BOOM', 231)" end

          it "exits with the GENERIC_FAILURE exit code, 1" do
            setup_client_rb
            run_chef_client_and_expect_exit_code 1
          end
        end

        context "when a reboot exception is raised (like from the reboot resource)" do
          before do
            file "cookbooks/x/recipes/default.rb", <<~EOM
              raise Chef::Exceptions::Reboot.new
            EOM
          end

          it "exits with REBOOT_SCHEDULED, 35" do
            setup_client_rb
            run_chef_client_and_expect_exit_code 35
          end
        end

        context "when an attempt to reboot fails (like from the reboot resource)" do
          before do
            file "cookbooks/x/recipes/default.rb", <<~EOM
              raise Chef::Exceptions::RebootFailed.new
            EOM
          end

          it "exits with REBOOT_FAILED, 41" do
            setup_client_rb
            run_chef_client_and_expect_exit_code 41
          end
        end
      end
    end
  end
end