summaryrefslogtreecommitdiff
path: root/spec/integration/recipes/unified_mode_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/integration/recipes/unified_mode_spec.rb')
-rw-r--r--spec/integration/recipes/unified_mode_spec.rb876
1 files changed, 876 insertions, 0 deletions
diff --git a/spec/integration/recipes/unified_mode_spec.rb b/spec/integration/recipes/unified_mode_spec.rb
new file mode 100644
index 0000000000..944319f7bf
--- /dev/null
+++ b/spec/integration/recipes/unified_mode_spec.rb
@@ -0,0 +1,876 @@
+require "support/shared/integration/integration_helper"
+require "chef/mixin/shell_out"
+
+describe "Unified Mode" do
+ include IntegrationSupport
+ include Chef::Mixin::ShellOut
+
+ let(:chef_dir) { File.expand_path("../../../../bin", __FILE__) }
+
+ let(:chef_client) { "bundle exec chef-client --minimal-ohai" }
+
+ when_the_repository "has a cookbook with a unified_mode resource with a delayed notification from the second block to the first block" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "first block" do
+ block do
+ puts "\nfirst: \#\{var\}"
+ end
+ action :nothing
+ end
+ var = "bar"
+ ruby_block "second block" do
+ block do
+ puts "\nsecond: \#\{var\}"
+ end
+ notifies :run, "ruby_block[first block]", :delayed
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ # the "second block" runs first after "bar" is set
+ expect(result.stdout).to include("second: bar")
+ # then the "first block" runs after "baz" in the delayed phase
+ expect(result.stdout).to include("first: baz")
+ # nothing else should fire
+ expect(result.stdout).not_to include("first: foo")
+ expect(result.stdout).not_to include("first: bar")
+ expect(result.stdout).not_to include("second: foo")
+ expect(result.stdout).not_to include("second: baz")
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with a unified_mode resource with a delayed notification from the first block to the second block" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "first block" do
+ block do
+ puts "\nfirst: \#\{var\}"
+ end
+ notifies :run, "ruby_block[second block]", :delayed
+ end
+ var = "bar"
+ ruby_block "second block" do
+ block do
+ puts "\nsecond: \#\{var\}"
+ end
+ action :nothing
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default' -l debug", cwd: chef_dir)
+ # the first block should fire first
+ expect(result.stdout).to include("first: foo")
+ # the second block should fire in delayed phase
+ expect(result.stdout).to include("second: baz")
+ # nothing else should fire
+ expect(result.stdout).not_to include("first: bar")
+ expect(result.stdout).not_to include("first: baz")
+ expect(result.stdout).not_to include("second: foo")
+ expect(result.stdout).not_to include("second: bar")
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with a unified_mode resource with an immediate notification from the second block to the first block" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "first block" do
+ block do
+ puts "\nfirst: \#\{var\}"
+ end
+ action :nothing
+ end
+ var = "bar"
+ ruby_block "second block" do
+ block do
+ puts "\nsecond: \#\{var\}"
+ end
+ notifies :run, "ruby_block[first block]", :immediate
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ # the second resource should fire first when it is parsed
+ expect(result.stdout).to include("second: bar")
+ # the first resource should then immediately fire
+ expect(result.stdout).to include("first: bar")
+ # no other resources should fire
+ expect(result.stdout).not_to include("second: baz")
+ expect(result.stdout).not_to include("second: foo")
+ expect(result.stdout).not_to include("first: foo")
+ expect(result.stdout).not_to include("first: baz")
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with a unified_mode resource with an immediate notification from the first block to the second block" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "first block" do
+ block do
+ puts "\nfirst: \#\{var\}"
+ end
+ notifies :run, "ruby_block[second block]", :immediate
+ end
+ var = "bar"
+ ruby_block "second block" do
+ block do
+ puts "\nsecond: \#\{var\}"
+ end
+ action :nothing
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default' -l debug", cwd: chef_dir)
+ # both blocks should run when they're declared
+ expect(result.stdout).to include("first: foo")
+ expect(result.stdout).to include("second: bar")
+ # nothing else should run
+ expect(result.stdout).not_to include("first: bar")
+ expect(result.stdout).not_to include("first: baz")
+ expect(result.stdout).not_to include("second: foo")
+ expect(result.stdout).not_to include("second: baz")
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with a unified_mode resource with an immediate notification from the first block to a block that does not exist" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "first block" do
+ block do
+ puts "\nfirst: \#\{var\}"
+ end
+ notifies :run, "ruby_block[second block]", :immediate
+ end
+ var = "bar"
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should fail the run" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ # both blocks should run when they're declared
+ expect(result.stdout).to include("first: foo")
+ # nothing else should run
+ expect(result.stdout).not_to include("second: bar")
+ expect(result.stdout).not_to include("first: bar")
+ expect(result.stdout).not_to include("first: baz")
+ expect(result.stdout).not_to include("second: foo")
+ expect(result.stdout).not_to include("second: baz")
+ expect(result.stdout).to include("Chef::Exceptions::ResourceNotFound")
+ expect(result.error?).to be true
+ end
+ end
+
+ when_the_repository "has a cookbook with a normal resource with an delayed notification with global resource unified mode on" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ resource_name :unified_mode
+ provides :unified_mode
+
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "second block" do
+ block do
+ puts "\nsecond: \#\{var\}"
+ end
+ action :nothing
+ end
+ var = "bar"
+ ruby_block "first block" do
+ block do
+ puts "\nfirst: \#\{var\}"
+ end
+ notifies :run, "ruby_block[second block]", :delayed
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<~EOM
+ resource_unified_mode_default true
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ # the "first block" resource runs before the assignment to baz in compile time
+ expect(result.stdout).to include("first: bar")
+ # we should not run the "first block" at compile time
+ expect(result.stdout).not_to include("first: baz")
+ # (and certainly should run it this early)
+ expect(result.stdout).not_to include("first: foo")
+ # the delayed notification should still fire and run after everything else
+ expect(result.stdout).to include("second: baz")
+ # the action :nothing should suppress any other running of the second block
+ expect(result.stdout).not_to include("second: foo")
+ expect(result.stdout).not_to include("second: bar")
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with a normal resource with an immediate notification with global resource unified mode on" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ resource_name :unified_mode
+ provides :unified_mode
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "second block" do
+ block do
+ puts "\nsecond: \#\{var\}"
+ end
+ action :nothing
+ end
+ var = "bar"
+ ruby_block "first block" do
+ block do
+ puts "\nfirst: \#\{var\}"
+ end
+ notifies :run, "ruby_block[second block]", :immediate
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<~EOM
+ resource_unified_mode_default true
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ # the "first block" resource runs before the assignment to baz in compile time
+ expect(result.stdout).to include("first: bar")
+ # we should not run the "first block" at compile time
+ expect(result.stdout).not_to include("first: baz")
+ # (and certainly should run it this early)
+ expect(result.stdout).not_to include("first: foo")
+ # the immediate notifiation fires immediately
+ expect(result.stdout).to include("second: bar")
+ # the action :nothing should suppress any other running of the second block
+ expect(result.stdout).not_to include("second: foo")
+ expect(result.stdout).not_to include("second: baz")
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with a unified resource with an immediate subscribes from the second resource to the first" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "first block" do
+ block do
+ puts "\nfirst: \#\{var\}"
+ end
+ end
+ var = "bar"
+ ruby_block "second block" do
+ block do
+ puts "\nsecond: \#\{var\}"
+ end
+ subscribes :run, "ruby_block[first block]", :immediate
+ action :nothing
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ # the first resource fires
+ expect(result.stdout).to include("first: foo")
+ # the second resource fires when it is parsed
+ expect(result.stdout).to include("second: bar")
+ # no other actions should run
+ expect(result.stdout).not_to include("first: bar")
+ expect(result.stdout).not_to include("first: baz")
+ expect(result.stdout).not_to include("second: foo")
+ expect(result.stdout).not_to include("second: baz")
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with a unified resource with an immediate subscribes from the first resource to the second" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "first block" do
+ block do
+ puts "\nfirst: \#\{var\}"
+ end
+ subscribes :run, "ruby_block[second block]", :immediate
+ action :nothing
+ end
+ var = "bar"
+ ruby_block "second block" do
+ block do
+ puts "\nsecond: \#\{var\}"
+ end
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ # the second resource fires first after bar is set
+ expect(result.stdout).to include("second: bar")
+ # the first resource then has its immediate subscribes fire at that location
+ expect(result.stdout).to include("first: bar")
+ # no other actions should run
+ expect(result.stdout).not_to include("first: baz")
+ expect(result.stdout).not_to include("first: foo")
+ expect(result.stdout).not_to include("second: foo")
+ expect(result.stdout).not_to include("second: baz")
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with a unified resource with an delayed subscribes from the second resource to the first" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "first block" do
+ block do
+ puts "\nfirst: \#\{var\}"
+ end
+ end
+ var = "bar"
+ ruby_block "second block" do
+ block do
+ puts "\nsecond: \#\{var\}"
+ end
+ subscribes :run, "ruby_block[first block]", :delayed
+ action :nothing
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ # the first resource fires as it is parsed
+ expect(result.stdout).to include("first: foo")
+ # the second resource then fires in the delayed notifications phase
+ expect(result.stdout).to include("second: baz")
+ # no other actions should run
+ expect(result.stdout).not_to include("first: bar")
+ expect(result.stdout).not_to include("first: baz")
+ expect(result.stdout).not_to include("second: foo")
+ expect(result.stdout).not_to include("second: bar")
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with a unified resource with an delayed subscribes from the first resource to the second" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "first block" do
+ block do
+ puts "\nfirst: \#\{var\}"
+ end
+ subscribes :run, "ruby_block[second block]", :delayed
+ action :nothing
+ end
+ var = "bar"
+ ruby_block "second block" do
+ block do
+ puts "\nsecond: \#\{var\}"
+ end
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ # the second resource fires first after bar is set
+ expect(result.stdout).to include("second: bar")
+ # the first resource then fires in the delayed notifications phase
+ expect(result.stdout).to include("first: baz")
+ # no other actions should run
+ expect(result.stdout).not_to include("first: foo")
+ expect(result.stdout).not_to include("first: bar")
+ expect(result.stdout).not_to include("second: foo")
+ expect(result.stdout).not_to include("second: baz")
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with a unified resource with a correct before notification" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "notified block" do
+ block do
+ puts "\nnotified: \#\{var\}"
+ end
+ action :nothing
+ end
+ var = "bar"
+ whyrun_safe_ruby_block "notifying block" do
+ block do
+ puts "\nnotifying: \#\{var\}"
+ end
+ notifies :run, "ruby_block[notified block]", :before
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ expect(result.stdout.scan(/notifying: bar/).length).to eql(2)
+ expect(result.stdout).to include("Would execute the whyrun_safe_ruby_block notifying block")
+ expect(result.stdout).to include("notified: bar")
+ # no other actions should run
+ expect(result.stdout).not_to include("notified: foo")
+ expect(result.stdout).not_to include("notified: baz")
+ expect(result.stdout).not_to include("notifying: foo")
+ expect(result.stdout).not_to include("notifying: baz")
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with a unified resource with a correct before subscribes" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ ruby_block "notified block" do
+ block do
+ puts "\nnotified: \#\{var\}"
+ end
+ subscribes :run, "whyrun_safe_ruby_block[notifying block]", :before
+ action :nothing
+ end
+ var = "bar"
+ whyrun_safe_ruby_block "notifying block" do
+ block do
+ puts "\nnotifying: \#\{var\}"
+ end
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should complete with success" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ expect(result.stdout.scan(/notifying: bar/).length).to eql(2)
+ expect(result.stdout).to include("Would execute the whyrun_safe_ruby_block notifying block")
+ expect(result.stdout).to include("notified: bar")
+ # no other actions should run
+ expect(result.stdout).not_to include("notified: foo")
+ expect(result.stdout).not_to include("notified: baz")
+ expect(result.stdout).not_to include("notifying: foo")
+ expect(result.stdout).not_to include("notifying: baz")
+ result.error!
+ end
+ end
+
+ when_the_repository "has a cookbook with a unified resource with a broken/reversed before notification" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ whyrun_safe_ruby_block "notifying block" do
+ block do
+ puts "\nnotifying: \#\{var\}"
+ end
+ notifies :run, "ruby_block[notified block]", :before
+ end
+ var = "bar"
+ ruby_block "notified block" do
+ block do
+ puts "\nnotified: \#\{var\}"
+ end
+ action :nothing
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should fail the run" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default' -l debug", cwd: chef_dir)
+ # this doesn't work and we can't tell the difference between it and if we were trying to do a correct :before notification but typo'd the name
+ # so Chef::Exceptions::ResourceNotFound is the best we can do
+ expect(result.stdout).to include("Chef::Exceptions::ResourceNotFound")
+ expect(result.error?).to be true
+ end
+ end
+
+ when_the_repository "has a cookbook with a unified resource with a broken/reversed before subscribes" do
+ before do
+ directory "cookbooks/x" do
+
+ file "resources/unified_mode.rb", <<-EOM
+ unified_mode true
+ resource_name :unified_mode
+ provides :unified_mode
+ action :doit do
+ klass = new_resource.class
+ var = "foo"
+ whyrun_safe_ruby_block "notifying block" do
+ block do
+ puts "\nnotifying: \#\{var\}"
+ end
+ end
+ var = "bar"
+ ruby_block "notified block" do
+ block do
+ puts "\nnotified: \#\{var\}"
+ end
+ subscribes :run, "whyrun_safe_ruby_block[notifying block]", :before
+ action :nothing
+ end
+ var = "baz"
+ end
+ EOM
+
+ file "recipes/default.rb", <<-EOM
+ unified_mode "whatever"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "should fail the run" do
+ file "config/client.rb", <<~EOM
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ # this fires first normally before the error
+ expect(result.stdout).to include("notifying: foo")
+ # everything else does not run
+ expect(result.stdout).not_to include("notified: foo")
+ expect(result.stdout).not_to include("notified: bar")
+ expect(result.stdout).not_to include("notified: baz")
+ expect(result.stdout).not_to include("notifying: bar")
+ expect(result.stdout).not_to include("notifying: baz")
+ expect(result.stdout).to include("Chef::Exceptions::UnifiedModeBeforeSubscriptionEarlierResource")
+ expect(result.error?).to be true
+ end
+ end
+
+ when_the_repository "has global resource unified mode on" do
+ before do
+ directory "cookbooks/x" do
+
+ file "recipes/default.rb", <<-EOM
+ var = "foo"
+ ruby_block "first block" do
+ block do
+ puts "\nfirst: \#\{var\}"
+ end
+ end
+ var = "bar"
+ EOM
+
+ end # directory 'cookbooks/x'
+ end
+
+ it "recipes should still have a compile/converge mode" do
+ file "config/client.rb", <<~EOM
+ resource_unified_mode_default true
+ local_mode true
+ cookbook_path "#{path_to("cookbooks")}"
+ log_level :warn
+ EOM
+
+ result = shell_out("#{chef_client} -c \"#{path_to("config/client.rb")}\" --no-color -F doc -o 'x::default'", cwd: chef_dir)
+ # in recipe mode we should still run normally with a compile/converge mode
+ expect(result.stdout).to include("first: bar")
+ expect(result.stdout).not_to include("first: foo")
+ result.error!
+ end
+ end
+end