diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2016-03-15 15:09:45 -0700 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2016-03-15 15:09:45 -0700 |
commit | d32484b767e11d4da48fd1c185315fe08b25fdbe (patch) | |
tree | 95f33d862ff59b6704f506279ec72854fad956c7 /lib | |
parent | c1a389c2a8452e9b796aa1d34c4d9e51f4af30c7 (diff) | |
download | chef-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')
-rw-r--r-- | lib/chef/dsl/recipe.rb | 9 | ||||
-rw-r--r-- | lib/chef/mixin/lazy_module_include.rb | 77 | ||||
-rw-r--r-- | lib/chef/recipe.rb | 1 |
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 |