summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2016-04-08 15:11:30 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2016-04-11 13:25:02 -0700
commit9ed7d6a880749090403ee6d78d5592a4fa212343 (patch)
treee0c9e5300ea2c49d2da97009b9c04277a7d4e10d
parent224aaaef042659021eb65c9eeddd9cdb1417eb59 (diff)
downloadchef-9ed7d6a880749090403ee6d78d5592a4fa212343.tar.gz
add notifying_block and subcontext_block to chef
-rw-r--r--lib/chef/dsl/core.rb12
-rw-r--r--lib/chef/mixin/notifying_block.rb54
-rw-r--r--spec/integration/recipes/notifying_block_spec.rb111
3 files changed, 172 insertions, 5 deletions
diff --git a/lib/chef/dsl/core.rb b/lib/chef/dsl/core.rb
index 7f7edbfbda..c2dbea7628 100644
--- a/lib/chef/dsl/core.rb
+++ b/lib/chef/dsl/core.rb
@@ -17,15 +17,16 @@
# limitations under the License.
#
-require "chef/mixin/shell_out"
-require "chef/mixin/powershell_out"
require "chef/dsl/declare_resource"
+require "chef/mixin/notifying_block"
+require "chef/mixin/powershell_out"
+require "chef/mixin/shell_out"
class Chef
module DSL
# This is the "Core DSL" with various bits of Sugar that are mixed into core providers as well
# as user LWRPs. This module deliberately does not mixin the Resources or Defintions DSL bits
- # so that cookbooks are not injeting random things into the samespace of core providers.
+ # so that cookbooks are not injeting random things into the namespace of core providers.
#
# - If you are writing cookbooks: you have come to the wrong place, please inject things into
# Chef::DSL::Recipe instead.
@@ -34,9 +35,10 @@ class Chef
# into here.
#
module Core
- include Chef::Mixin::ShellOut
- include Chef::Mixin::PowershellOut
include Chef::DSL::DeclareResource
+ include Chef::Mixin::NotifyingBlock
+ include Chef::Mixin::PowershellOut
+ include Chef::Mixin::ShellOut
end
end
end
diff --git a/lib/chef/mixin/notifying_block.rb b/lib/chef/mixin/notifying_block.rb
new file mode 100644
index 0000000000..9ac1b79bb8
--- /dev/null
+++ b/lib/chef/mixin/notifying_block.rb
@@ -0,0 +1,54 @@
+#--
+# Author:: Lamont Granquist <lamont@chef.io>
+# Copyright:: Copyright 2010-2016, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+class Chef
+ module Mixin
+ module NotifyingBlock
+
+ def notifying_block(&block)
+ begin
+ subcontext = subcontext_block(&block)
+ Chef::Runner.new(subcontext).converge
+ ensure
+ new_resource.updated_by_last_action(
+ subcontext && subcontext.resource_collection.any?(&:updated?)
+ ) if respond_to?(:new_resource)
+ end
+ end
+
+ def subcontext_block(parent_context = nil, &block)
+ parent_context ||= @run_context
+ sub_run_context = parent_context.create_child
+
+ begin
+ outer_run_context = @run_context
+ @run_context = sub_run_context
+ instance_eval(&block)
+ ensure
+ @run_context = outer_run_context
+ end
+
+ sub_run_context
+ end
+
+ def global_resource_collection
+ Chef.run_context.resource_collection
+ end
+
+ end
+ end
+end
diff --git a/spec/integration/recipes/notifying_block_spec.rb b/spec/integration/recipes/notifying_block_spec.rb
new file mode 100644
index 0000000000..6a1287c7b1
--- /dev/null
+++ b/spec/integration/recipes/notifying_block_spec.rb
@@ -0,0 +1,111 @@
+#
+# Author:: John Keiser (<jkeiser@chef.io>)
+# Copyright:: Copyright 2013-2016, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require "support/shared/integration/integration_helper"
+require "chef/mixin/shell_out"
+
+describe "notifying_block" do
+ include IntegrationSupport
+ include Chef::Mixin::ShellOut
+
+ let(:chef_dir) { File.expand_path("../../../../bin", __FILE__) }
+ let(:chef_client) { "ruby '#{chef_dir}/chef-client' --minimal-ohai" }
+
+ when_the_repository "notifying_block test one" do
+ before do
+ directory "cookbooks/x" do
+ file "recipes/default.rb", <<-EOM
+ notifying_block do
+ log "gamma" do
+ action :nothing
+ end
+ log "alpha" do
+ notifies :write, "log[gamma]", :delayed
+ end
+ log "beta" do
+ notifies :write, "log[gamma]", :delayed
+ end
+ end
+ log "delta"
+ EOM
+ end
+ file "config/client.rb", <<-EOM
+ local_mode true
+ cookbook_path "#{path_to('cookbooks')}"
+ log_level :warn
+ EOM
+ end
+
+ # implicitly tests -
+ # 1. notifying block opens up a subcontext
+ # 2. delayed notifications are de-dup'd in the subcontext
+ # 3. delayed notifications (to resources inside the subcontext) are run at the end of the subcontext
+ it "should run alpha, beta, gamma, and delta in that order" do
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
+ expect(result.stdout).to match(/\* log\[alpha\] action write\s+\* log\[beta\] action write\s+\* log\[gamma\] action write\s+Converging 1 resources\s+\* log\[delta\] action write/)
+ result.error!
+ end
+ end
+
+ when_the_repository "notifying_block test two" do
+ before do
+ directory "cookbooks/x" do
+ file "resources/nb_test.rb", <<-EOM
+ default_action :run
+ provides :nb_test
+ resource_name :nb_test
+
+ action :run do
+ notifying_block do
+ log "foo" do
+ notifies :write, 'log[bar]', :delayed
+ end
+ end
+ end
+ EOM
+ file "recipes/default.rb", <<-EOM
+ log "bar" do
+ action :nothing
+ end
+ log "baz" do
+ action :nothing
+ end
+
+ nb_test "testing" do
+ notifies :write, 'log[baz]', :delayed
+ end
+
+ log "quux"
+ EOM
+ end
+ file "config/client.rb", <<-EOM
+ local_mode true
+ cookbook_path "#{path_to('cookbooks')}"
+ log_level :warn
+ EOM
+ end
+
+ # implicitly tests -
+ # 1. notifying block will correctly update wrapping new_resource updated_by_last_action status
+ # 2. delayed notifications from a subcontext inside a resource will notify resources in their outer run_context
+ it "should run foo, quux, bar, and baz in that order" do
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" --no-color -F doc -o 'x::default'", :cwd => chef_dir)
+ expect(result.stdout).to match(/\* log\[foo\] action write\s+\* log\[quux\] action write\s+\* log\[bar\] action write\s+\* log\[baz\] action write/)
+ result.error!
+ end
+ end
+end