summaryrefslogtreecommitdiff
path: root/spec/integration/solo/solo_spec.rb
blob: 0d08bf57ccfeb9a43418a9aea85754780fb8842a (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
require 'support/shared/integration/integration_helper'
require 'chef/mixin/shell_out'
require 'chef/run_lock'
require 'chef/config'
require 'timeout'
require 'fileutils'

describe "chef-solo" do
  extend IntegrationSupport
  include Chef::Mixin::ShellOut

  when_the_repository "has a cookbook with a no-op recipe" do
    file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
    file 'cookbooks/x/recipes/default.rb', ''

    it "should complete with success" do
      file 'config/solo.rb', <<EOM
cookbook_path "#{path_to('cookbooks')}"
file_cache_path "#{path_to('config/cache')}"
EOM
      chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..")
      result = shell_out("bundle exec chef-solo -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug", :cwd => chef_dir)
      result.error!
    end
  end

  when_the_repository "has a cookbook with a recipe with sleep" do
    directory 'logs'
    file 'logs/runs.log', ''
    file 'cookbooks/x/metadata.rb', 'version "1.0.0"'
    file 'cookbooks/x/recipes/default.rb', <<EOM
ruby_block "sleeping" do
  block do
    sleep 5
  end
end
EOM
    # Ruby 1.8.7 doesn't have Process.spawn :(
    it "while running solo concurrently", :ruby_gte_19_only => true do
      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.
      lambda {
        Timeout.timeout(120) do
          chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..")

          # Instantiate the first chef-solo run
          s1 = Process.spawn("bundle exec chef-solo -c \"#{path_to('config/solo.rb')}\" -o 'x::default' \
-l debug -L #{path_to('logs/runs.log')}", :chdir => chef_dir)

          # Give it some time to progress
          sleep 1

          # Instantiate the second chef-solo run
          s2 = Process.spawn("bundle exec 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)
          Process.waitpid(s2)
        end
      }.should_not raise_error(Timeout::Error)

      # Unfortunately file / directory helpers in integration tests
      # are implemented using before(:each) so we need to do all below
      # checks in one example.
      run_log = File.read(path_to('logs/runs.log'))

      # both of the runs should succeed
      run_log.lines.reject {|l| !l.include? "INFO: Chef Run complete in"}.length.should == 2

      # second run should have a message which indicates it's waiting for the first run
      pid_lines = run_log.lines.reject {|l| !l.include? "Chef-client pid:"}
      pid_lines.length.should == 2
      pids = pid_lines.map {|l| l.split(" ").last}
      run_log.should include("Chef client #{pids[0]} is running, will wait for it to finish and then run.")

      # second run should start after first run ends
      starts = [ ]
      ends = [ ]
      run_log.lines.each_with_index do |line, index|
        if line.include? "Chef-client pid:"
          starts << index
        elsif line.include? "INFO: Chef Run complete in"
          ends << index
        end
      end
      starts[1].should > ends[0]
    end

  end
end