summaryrefslogtreecommitdiff
path: root/lib/chef
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2016-03-15 15:09:45 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2016-03-15 15:09:45 -0700
commitd32484b767e11d4da48fd1c185315fe08b25fdbe (patch)
tree95f33d862ff59b6704f506279ec72854fad956c7 /lib/chef
parentc1a389c2a8452e9b796aa1d34c4d9e51f4af30c7 (diff)
downloadchef-d32484b767e11d4da48fd1c185315fe08b25fdbe.tar.gz
lazy module inclusion into DSL moduleslcg/use-and-lazy-module-include
Chef::DSL::Recipe::FullDSL.send(:include, MyModule) will now patch all its descendants that it has been included into (works the way actual inheritance works now).
Diffstat (limited to 'lib/chef')
-rw-r--r--lib/chef/dsl/recipe.rb9
-rw-r--r--lib/chef/mixin/lazy_module_include.rb77
-rw-r--r--lib/chef/recipe.rb1
3 files changed, 84 insertions, 3 deletions
diff --git a/lib/chef/dsl/recipe.rb b/lib/chef/dsl/recipe.rb
index 6d254df48d..22be303c5b 100644
--- a/lib/chef/dsl/recipe.rb
+++ b/lib/chef/dsl/recipe.rb
@@ -23,21 +23,21 @@ require "chef/mixin/powershell_out"
require "chef/dsl/resources"
require "chef/dsl/definitions"
require "chef/dsl/declare_resource"
+require "chef/mixin/lazy_module_include"
class Chef
module DSL
-
# == Chef::DSL::Recipe
# Provides the primary recipe DSL functionality for defining Chef resource
# objects via method calls.
module Recipe
-
include Chef::Mixin::ShellOut
include Chef::Mixin::PowershellOut
include Chef::DSL::Resources
include Chef::DSL::Definitions
include Chef::DSL::DeclareResource
+ extend Chef::Mixin::LazyModuleInclude
def resource_class_for(snake_case_name)
Chef::Resource.resource_for_node(snake_case_name, run_context.node)
@@ -113,6 +113,8 @@ class Chef
require "chef/dsl/reboot_pending"
require "chef/dsl/audit"
require "chef/dsl/powershell"
+ require "chef/mixin/lazy_module_include"
+
include Chef::DSL::DataQuery
include Chef::DSL::PlatformIntrospection
include Chef::DSL::IncludeRecipe
@@ -121,6 +123,9 @@ class Chef
include Chef::DSL::RebootPending
include Chef::DSL::Audit
include Chef::DSL::Powershell
+
+ extend Chef::Mixin::LazyModuleInclude
+
end
end
end
diff --git a/lib/chef/mixin/lazy_module_include.rb b/lib/chef/mixin/lazy_module_include.rb
new file mode 100644
index 0000000000..34e1fce4f1
--- /dev/null
+++ b/lib/chef/mixin/lazy_module_include.rb
@@ -0,0 +1,77 @@
+#
+# Copyright:: Copyright 2011-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
+ # If you have:
+ #
+ # module A
+ # extend LazyModuleInclude
+ # end
+ #
+ # module B
+ # include A
+ # end
+ #
+ # module C
+ # include B
+ # end
+ #
+ # module Monkeypatches
+ # def monkey
+ # puts "monkey!"
+ # end
+ # end
+ #
+ # A.send(:include, Monkeypatches)
+ #
+ # Then B and C and any classes that they're included in will also get the #monkey method patched into them.
+ #
+ module LazyModuleInclude
+
+ # Most of the magick is in this hook which creates a closure over the parent class and then builds an
+ # "infector" module which infects all descendants and which is responsible for updating the list of
+ # descendants in the parent class.
+ def included(klass)
+ super
+ parent_klass = self
+ infector = Module.new do
+ define_method(:included) do |subklass|
+ super(subklass)
+ subklass.extend(infector)
+ parent_klass.descendants.push(subklass)
+ end
+ end
+ klass.extend(infector)
+ parent_klass.descendants.push(klass)
+ end
+
+ def descendants
+ @descendants ||= []
+ end
+
+ def include(*classes)
+ super
+ classes.each do |klass|
+ descendants.each do |descendant|
+ descendant.send(:include, klass)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/recipe.rb b/lib/chef/recipe.rb
index 3a91781b2e..55b6fd7d52 100644
--- a/lib/chef/recipe.rb
+++ b/lib/chef/recipe.rb
@@ -114,6 +114,5 @@ class Chef
run_context.node.tags.delete(tag)
end
end
-
end
end