compat_resource 12.9.1 → 12.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +8 -3
- data/files/lib/chef_compat/copied_from_chef/chef/dsl/core.rb +56 -0
- data/files/lib/chef_compat/copied_from_chef/chef/dsl/declare_resource.rb +182 -7
- data/files/lib/chef_compat/copied_from_chef/chef/dsl/recipe.rb +5 -2
- data/files/lib/chef_compat/copied_from_chef/chef/mixin/lazy_module_include.rb +90 -0
- data/files/lib/chef_compat/copied_from_chef/chef/mixin/notifying_block.rb +66 -0
- data/files/lib/chef_compat/copied_from_chef/chef/mixin/powershell_out.rb +109 -0
- data/files/lib/chef_compat/copied_from_chef/chef/property.rb +9 -2
- data/files/lib/chef_compat/copied_from_chef/chef/provider.rb +2 -2
- data/files/lib/chef_compat/copied_from_chef/chef/resource.rb +1 -0
- data/files/lib/chef_compat/copied_from_chef/chef/resource/action_class.rb +3 -0
- data/files/lib/chef_compat/copied_from_chef/chef/resource_builder.rb +1 -1
- data/files/lib/chef_compat/monkeypatches.rb +7 -3
- data/files/lib/chef_compat/monkeypatches/chef.rb +3 -2
- data/files/lib/chef_compat/monkeypatches/chef/log.rb +13 -0
- data/files/lib/chef_compat/monkeypatches/chef/resource_collection.rb +103 -0
- data/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_list.rb +49 -0
- data/files/lib/chef_compat/monkeypatches/chef/resource_collection/resource_set.rb +49 -0
- data/files/lib/chef_compat/monkeypatches/chef/run_context.rb +74 -9
- data/files/lib/chef_compat/monkeypatches/chef/runner.rb +60 -0
- data/files/lib/compat_resource/version.rb +1 -1
- data/files/spec/cookbook_spec.rb +10 -1
- data/files/spec/data/.bundle/config +1 -0
- data/files/spec/data/Gemfile.lock +18 -50
- data/files/spec/data/config.rb +1 -1
- data/files/spec/data/cookbooks/notifications/metadata.rb +4 -0
- data/files/spec/data/cookbooks/notifications/recipes/default.rb +5 -0
- data/files/spec/data/cookbooks/notifications/resources/resource.rb +8 -0
- metadata +15 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c7c3400d3a6270d353403967a7285c17b4c0e01
|
4
|
+
data.tar.gz: 058a4752161e3c8e1610e80f5ff9497d3802a6b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e1d3dc00dbe9e97c67a6cc14baa7700ae7462e977130bc2bbe8f6ed75c3f35c45505de9d8082506ac68db68532afbd6443e6b9eb3c356a04d4ac216ffac8ba2
|
7
|
+
data.tar.gz: f87ce089823b777aa404cf36ab66f1222a50b9554c0bf0c1c948a6687aa85bcc2b9ca33ea4c836d7a54a3d80431cf401d4cd24156d9101e915df7ac26ecc567b
|
data/Rakefile
CHANGED
@@ -16,15 +16,19 @@ task default: :spec
|
|
16
16
|
CHEF_FILES = %w(
|
17
17
|
chef/constants
|
18
18
|
chef/delayed_evaluator
|
19
|
+
chef/dsl/core
|
19
20
|
chef/dsl/declare_resource
|
20
21
|
chef/dsl/recipe
|
22
|
+
chef/mixin/lazy_module_include
|
23
|
+
chef/mixin/notifying_block
|
21
24
|
chef/mixin/params_validate
|
25
|
+
chef/mixin/powershell_out
|
22
26
|
chef/mixin/properties
|
23
27
|
chef/property
|
24
28
|
chef/provider
|
25
29
|
chef/resource
|
26
|
-
chef/resource_builder
|
27
30
|
chef/resource/action_class
|
31
|
+
chef/resource_builder
|
28
32
|
)
|
29
33
|
SPEC_FILES = %w(
|
30
34
|
unit/mixin/properties_spec.rb
|
@@ -69,8 +73,8 @@ KEEP_FUNCTIONS = {
|
|
69
73
|
}
|
70
74
|
KEEP_INCLUDES = {
|
71
75
|
'chef/resource' => %w(Chef::Mixin::ParamsValidate Chef::Mixin::Properties),
|
72
|
-
'chef/provider' => %w(Chef::DSL::
|
73
|
-
'chef/dsl/recipe' => %w(Chef::DSL::
|
76
|
+
'chef/provider' => %w(Chef::DSL::Core),
|
77
|
+
'chef/dsl/recipe' => %w(Chef::DSL::Core Chef::DSL::Recipe Chef::Mixin::LazyModuleInclude),
|
74
78
|
}
|
75
79
|
KEEP_CLASSES = {
|
76
80
|
'chef/provider' => %w(Chef::Provider Chef::Provider::InlineResources Chef::Provider::InlineResources::ClassMethods)
|
@@ -83,6 +87,7 @@ PROCESS_LINES = {
|
|
83
87
|
# See chef_compat/resource for def. of resource_name and provider
|
84
88
|
# See chef_compat/monkeypatches/chef/resource for def. of current_value
|
85
89
|
|
90
|
+
desc "Pull new files from the chef client this is bundled with and update this cookbook"
|
86
91
|
task :update do
|
87
92
|
# Copy files from chef to chef_compat/chef, with a few changes
|
88
93
|
target_path = File.expand_path("../files/lib/chef_compat/copied_from_chef", __FILE__)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
begin
|
2
|
+
require 'chef/dsl/core'
|
3
|
+
rescue LoadError; end
|
4
|
+
|
5
|
+
require 'chef_compat/copied_from_chef'
|
6
|
+
class Chef
|
7
|
+
module ::ChefCompat
|
8
|
+
module CopiedFromChef
|
9
|
+
#--
|
10
|
+
# Author:: Adam Jacob (<adam@chef.io>)
|
11
|
+
# Author:: Christopher Walters (<cw@chef.io>)
|
12
|
+
# Copyright:: Copyright 2008-2016, 2009-2015 Chef Software, Inc.
|
13
|
+
# License:: Apache License, Version 2.0
|
14
|
+
#
|
15
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
16
|
+
# you may not use this file except in compliance with the License.
|
17
|
+
# You may obtain a copy of the License at
|
18
|
+
#
|
19
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
20
|
+
#
|
21
|
+
# Unless required by applicable law or agreed to in writing, software
|
22
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
23
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
24
|
+
# See the License for the specific language governing permissions and
|
25
|
+
# limitations under the License.
|
26
|
+
#
|
27
|
+
|
28
|
+
require "chef_compat/copied_from_chef/chef/dsl/declare_resource"
|
29
|
+
require "chef_compat/copied_from_chef/chef/mixin/notifying_block"
|
30
|
+
require "chef_compat/copied_from_chef/chef/mixin/powershell_out"
|
31
|
+
|
32
|
+
class Chef < (defined?(::Chef) ? ::Chef : Object)
|
33
|
+
module DSL
|
34
|
+
CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL)
|
35
|
+
# This is the "Core DSL" with various bits of Sugar that are mixed into core providers as well
|
36
|
+
# as user LWRPs. This module deliberately does not mixin the Resources or Defintions DSL bits
|
37
|
+
# so that cookbooks are not injeting random things into the namespace of core providers.
|
38
|
+
#
|
39
|
+
# - If you are writing cookbooks: you have come to the wrong place, please inject things into
|
40
|
+
# Chef::DSL::Recipe instead.
|
41
|
+
#
|
42
|
+
# - If you are writing core chef: you have come to the right place, please drop your DSL modules
|
43
|
+
# into here.
|
44
|
+
#
|
45
|
+
module Core
|
46
|
+
CopiedFromChef.extend_chef_module(::Chef::DSL::Core, self) if defined?(::Chef::DSL::Core)
|
47
|
+
include Chef::DSL::DeclareResource
|
48
|
+
include Chef::Mixin::NotifyingBlock
|
49
|
+
include Chef::Mixin::PowershellOut
|
50
|
+
include Chef::Mixin::ShellOut
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -8,7 +8,7 @@ module ::ChefCompat
|
|
8
8
|
module CopiedFromChef
|
9
9
|
#--
|
10
10
|
# Author:: Adam Jacob (<adam@chef.io>)
|
11
|
-
# Author:: Christopher Walters
|
11
|
+
# Author:: Christopher Walters
|
12
12
|
# Copyright:: Copyright 2008-2016, 2009-2015 Chef Software, Inc.
|
13
13
|
# License:: Apache License, Version 2.0
|
14
14
|
#
|
@@ -32,7 +32,180 @@ class Chef < (defined?(::Chef) ? ::Chef : Object)
|
|
32
32
|
module DeclareResource
|
33
33
|
CopiedFromChef.extend_chef_module(::Chef::DSL::DeclareResource, self) if defined?(::Chef::DSL::DeclareResource)
|
34
34
|
|
35
|
+
# Helper for switching run_contexts. Allows for using :parent or :root in place of
|
36
|
+
# passing the run_context. Executes the block in the run_context. Returns the return
|
37
|
+
# value of the passed block.
|
35
38
|
#
|
39
|
+
# @param rc [Chef::RunContext,Symbol] Either :root, :parent or a Chef::RunContext
|
40
|
+
#
|
41
|
+
# @return return value of the block
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
# # creates/returns a 'service[foo]' resource in the root run_context
|
45
|
+
# resource = with_run_context(:root)
|
46
|
+
# edit_resource(:service, "foo") do
|
47
|
+
# action :nothing
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
def with_run_context(rc)
|
52
|
+
raise ArgumentError, "with_run_context is useless without a block" unless block_given?
|
53
|
+
old_run_context = @run_context
|
54
|
+
@run_context =
|
55
|
+
case rc
|
56
|
+
when Chef::RunContext
|
57
|
+
rc
|
58
|
+
when :root
|
59
|
+
Chef.run_context
|
60
|
+
when :parent
|
61
|
+
run_context.parent_run_context
|
62
|
+
else
|
63
|
+
raise ArgumentError, "bad argument to run_context helper, must be :root, :parent, or a Chef::RunContext"
|
64
|
+
end
|
65
|
+
yield
|
66
|
+
ensure
|
67
|
+
@run_context = old_run_context
|
68
|
+
end
|
69
|
+
|
70
|
+
# Lookup a resource in the resource collection by name and delete it. This
|
71
|
+
# will raise Chef::Exceptions::ResourceNotFound if the resource is not found.
|
72
|
+
#
|
73
|
+
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
|
74
|
+
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
|
75
|
+
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
|
76
|
+
#
|
77
|
+
# @return [Chef::Resource] The resource
|
78
|
+
#
|
79
|
+
# @example
|
80
|
+
# delete_resource!(:template, '/x/y.txy')
|
81
|
+
#
|
82
|
+
def delete_resource!(type, name, run_context: self.run_context)
|
83
|
+
run_context.resource_collection.delete("#{type}[#{name}]")
|
84
|
+
end
|
85
|
+
|
86
|
+
# Lookup a resource in the resource collection by name and delete it. Returns
|
87
|
+
# nil if the resource is not found and should not fail.
|
88
|
+
#
|
89
|
+
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
|
90
|
+
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
|
91
|
+
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
|
92
|
+
#
|
93
|
+
# @return [Chef::Resource] The resource
|
94
|
+
#
|
95
|
+
# @example
|
96
|
+
# delete_resource(:template, '/x/y.txy')
|
97
|
+
#
|
98
|
+
def delete_resource(type, name, run_context: self.run_context)
|
99
|
+
delete_resource!(type, name, run_context: run_context)
|
100
|
+
rescue Chef::Exceptions::ResourceNotFound
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
|
104
|
+
# Lookup a resource in the resource collection by name and edit the resource. If the resource is not
|
105
|
+
# found this will raise Chef::Exceptions::ResourceNotFound. This is the correct API to use for
|
106
|
+
# "chef_rewind" functionality.
|
107
|
+
#
|
108
|
+
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
|
109
|
+
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
|
110
|
+
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
|
111
|
+
# @param resource_attrs_block A block that lets you set attributes of the
|
112
|
+
# resource (it is instance_eval'd on the resource instance).
|
113
|
+
#
|
114
|
+
# @return [Chef::Resource] The updated resource
|
115
|
+
#
|
116
|
+
# @example
|
117
|
+
# edit_resource!(:template, '/x/y.txy') do
|
118
|
+
# cookbook_name: cookbook_name
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
def edit_resource!(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block)
|
122
|
+
resource = find_resource!(type, name, run_context: run_context)
|
123
|
+
resource.instance_eval(&resource_attrs_block) if block_given?
|
124
|
+
resource
|
125
|
+
end
|
126
|
+
|
127
|
+
# Lookup a resource in the resource collection by name. If it exists,
|
128
|
+
# return it. If it does not exist, create it. This is a useful function
|
129
|
+
# for accumulator patterns. In CRUD terminology this is an "upsert" operation and is
|
130
|
+
# used to assert that the resource must exist with the specified properties.
|
131
|
+
#
|
132
|
+
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
|
133
|
+
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
|
134
|
+
# @param created_at [String] The caller of the resource. Use `caller[0]`
|
135
|
+
# to get the caller of your function. Defaults to the caller of this
|
136
|
+
# function.
|
137
|
+
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
|
138
|
+
# @param resource_attrs_block A block that lets you set attributes of the
|
139
|
+
# resource (it is instance_eval'd on the resource instance).
|
140
|
+
#
|
141
|
+
# @return [Chef::Resource] The updated or created resource
|
142
|
+
#
|
143
|
+
# @example
|
144
|
+
# resource = edit_resource(:template, '/x/y.txy') do
|
145
|
+
# source "y.txy.erb"
|
146
|
+
# variables {}
|
147
|
+
# end
|
148
|
+
# resource.variables.merge!({ home: "/home/klowns" })
|
149
|
+
#
|
150
|
+
def edit_resource(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block)
|
151
|
+
edit_resource!(type, name, created_at, run_context: run_context, &resource_attrs_block)
|
152
|
+
rescue Chef::Exceptions::ResourceNotFound
|
153
|
+
declare_resource(type, name, created_at, run_context: run_context, &resource_attrs_block)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Lookup a resource in the resource collection by name. If the resource is not
|
157
|
+
# found this will raise Chef::Exceptions::ResourceNotFound. This API is identical to the
|
158
|
+
# resources() call and while it is a synonym it is not intended to deprecate that call.
|
159
|
+
#
|
160
|
+
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
|
161
|
+
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
|
162
|
+
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
|
163
|
+
#
|
164
|
+
# @return [Chef::Resource] The updated resource
|
165
|
+
#
|
166
|
+
# @example
|
167
|
+
# resource = find_resource!(:template, '/x/y.txy')
|
168
|
+
#
|
169
|
+
def find_resource!(type, name, run_context: self.run_context)
|
170
|
+
raise ArgumentError, "find_resource! does not take a block" if block_given?
|
171
|
+
run_context.resource_collection.find(type => name)
|
172
|
+
end
|
173
|
+
|
174
|
+
# Lookup a resource in the resource collection by name. If the resource is not found
|
175
|
+
# the will be no exception raised and the call will return nil. If a block is given and
|
176
|
+
# no resource is found it will create the resource using the block, if the resource is
|
177
|
+
# found then the block will not be applied. The block version is similar to create_if_missing
|
178
|
+
#
|
179
|
+
# @param type [Symbol] The type of resource (e.g. `:file` or `:package`)
|
180
|
+
# @param name [String] The name of the resource (e.g. '/x/y.txt' or 'apache2')
|
181
|
+
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
|
182
|
+
#
|
183
|
+
# @return [Chef::Resource] The updated resource
|
184
|
+
#
|
185
|
+
# @example
|
186
|
+
# if ( find_resource(:template, '/x/y.txy') )
|
187
|
+
# # do something
|
188
|
+
# else
|
189
|
+
# # don't worry about the error
|
190
|
+
# end
|
191
|
+
#
|
192
|
+
# @example
|
193
|
+
# # this API can be used to return a resource from an outer run context, and will only create
|
194
|
+
# # an action :nothing service if one does not already exist.
|
195
|
+
# resource = with_run_context(:root) do
|
196
|
+
# find_resource(:service, 'whatever') do
|
197
|
+
# action :nothing
|
198
|
+
# end
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
def find_resource(type, name, created_at: nil, run_context: self.run_context, &resource_attrs_block)
|
202
|
+
find_resource!(type, name, run_context: run_context)
|
203
|
+
rescue Chef::Exceptions::ResourceNotFound
|
204
|
+
if block_given?
|
205
|
+
declare_resource(type, name, created_at, run_context: run_context, &resource_attrs_block)
|
206
|
+
end # returns nil otherwise
|
207
|
+
end
|
208
|
+
|
36
209
|
# Instantiates a resource (via #build_resource), then adds it to the
|
37
210
|
# resource collection. Note that resource classes are looked up directly,
|
38
211
|
# so this will create the resource you intended even if the method name
|
@@ -43,6 +216,7 @@ class Chef < (defined?(::Chef) ? ::Chef : Object)
|
|
43
216
|
# @param created_at [String] The caller of the resource. Use `caller[0]`
|
44
217
|
# to get the caller of your function. Defaults to the caller of this
|
45
218
|
# function.
|
219
|
+
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
|
46
220
|
# @param resource_attrs_block A block that lets you set attributes of the
|
47
221
|
# resource (it is instance_eval'd on the resource instance).
|
48
222
|
#
|
@@ -61,11 +235,9 @@ class Chef < (defined?(::Chef) ? ::Chef : Object)
|
|
61
235
|
created_at ||= caller[0]
|
62
236
|
|
63
237
|
if create_if_missing
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
rescue Chef::Exceptions::ResourceNotFound
|
68
|
-
end
|
238
|
+
Chef::Log.deprecation "build_resource with a create_if_missing flag is deprecated, use edit_resource instead"
|
239
|
+
# midly goofy since we call edit_resource only to re-call ourselves, but that's why its deprecated...
|
240
|
+
return edit_resource(type, name, created_at, run_context: run_context, &resource_attrs_block)
|
69
241
|
end
|
70
242
|
|
71
243
|
resource = build_resource(type, name, created_at, &resource_attrs_block)
|
@@ -74,7 +246,6 @@ class Chef < (defined?(::Chef) ? ::Chef : Object)
|
|
74
246
|
resource
|
75
247
|
end
|
76
248
|
|
77
|
-
#
|
78
249
|
# Instantiate a resource of the given +type+ with the given +name+ and
|
79
250
|
# attributes as given in the +resource_attrs_block+.
|
80
251
|
#
|
@@ -85,6 +256,7 @@ class Chef < (defined?(::Chef) ? ::Chef : Object)
|
|
85
256
|
# @param created_at [String] The caller of the resource. Use `caller[0]`
|
86
257
|
# to get the caller of your function. Defaults to the caller of this
|
87
258
|
# function.
|
259
|
+
# @param run_context [Chef::RunContext] the run_context of the resource collection to operate on
|
88
260
|
# @param resource_attrs_block A block that lets you set attributes of the
|
89
261
|
# resource (it is instance_eval'd on the resource instance).
|
90
262
|
#
|
@@ -97,6 +269,9 @@ class Chef < (defined?(::Chef) ? ::Chef : Object)
|
|
97
269
|
#
|
98
270
|
def build_resource(type, name, created_at = nil, run_context: self.run_context, &resource_attrs_block)
|
99
271
|
created_at ||= caller[0]
|
272
|
+
|
273
|
+
# this needs to be lazy in order to avoid circular dependencies since ResourceBuilder
|
274
|
+
# will requires the entire provider+resolver universe
|
100
275
|
require "chef_compat/copied_from_chef/chef/resource_builder" unless defined?(Chef::ResourceBuilder)
|
101
276
|
|
102
277
|
Chef::ResourceBuilder.new(
|
@@ -6,16 +6,19 @@ require 'chef_compat/copied_from_chef'
|
|
6
6
|
class Chef
|
7
7
|
module ::ChefCompat
|
8
8
|
module CopiedFromChef
|
9
|
-
require "chef_compat/copied_from_chef/chef/dsl/
|
9
|
+
require "chef_compat/copied_from_chef/chef/dsl/core"
|
10
|
+
require "chef_compat/copied_from_chef/chef/mixin/lazy_module_include"
|
10
11
|
class Chef < (defined?(::Chef) ? ::Chef : Object)
|
11
12
|
module DSL
|
12
13
|
CopiedFromChef.extend_chef_module(::Chef::DSL, self) if defined?(::Chef::DSL)
|
13
14
|
module Recipe
|
14
15
|
CopiedFromChef.extend_chef_module(::Chef::DSL::Recipe, self) if defined?(::Chef::DSL::Recipe)
|
15
|
-
include Chef::DSL::
|
16
|
+
include Chef::DSL::Core
|
17
|
+
extend Chef::Mixin::LazyModuleInclude
|
16
18
|
module FullDSL
|
17
19
|
CopiedFromChef.extend_chef_module(::Chef::DSL::Recipe::FullDSL, self) if defined?(::Chef::DSL::Recipe::FullDSL)
|
18
20
|
include Chef::DSL::Recipe
|
21
|
+
extend Chef::Mixin::LazyModuleInclude
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
begin
|
2
|
+
require 'chef/mixin/lazy_module_include'
|
3
|
+
rescue LoadError; end
|
4
|
+
|
5
|
+
require 'chef_compat/copied_from_chef'
|
6
|
+
class Chef
|
7
|
+
module ::ChefCompat
|
8
|
+
module CopiedFromChef
|
9
|
+
#
|
10
|
+
# Copyright:: Copyright 2011-2016, Chef Software Inc.
|
11
|
+
# License:: Apache License, Version 2.0
|
12
|
+
#
|
13
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
14
|
+
# you may not use this file except in compliance with the License.
|
15
|
+
# You may obtain a copy of the License at
|
16
|
+
#
|
17
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
18
|
+
#
|
19
|
+
# Unless required by applicable law or agreed to in writing, software
|
20
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
21
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
22
|
+
# See the License for the specific language governing permissions and
|
23
|
+
# limitations under the License.
|
24
|
+
#
|
25
|
+
|
26
|
+
class Chef < (defined?(::Chef) ? ::Chef : Object)
|
27
|
+
module Mixin
|
28
|
+
CopiedFromChef.extend_chef_module(::Chef::Mixin, self) if defined?(::Chef::Mixin)
|
29
|
+
# If you have:
|
30
|
+
#
|
31
|
+
# module A
|
32
|
+
# extend LazyModuleInclude
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# module B
|
36
|
+
# include A
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# module C
|
40
|
+
# include B
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# module Monkeypatches
|
44
|
+
# def monkey
|
45
|
+
# puts "monkey!"
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# A.send(:include, Monkeypatches)
|
50
|
+
#
|
51
|
+
# Then B and C and any classes that they're included in will also get the #monkey method patched into them.
|
52
|
+
#
|
53
|
+
module LazyModuleInclude
|
54
|
+
CopiedFromChef.extend_chef_module(::Chef::Mixin::LazyModuleInclude, self) if defined?(::Chef::Mixin::LazyModuleInclude)
|
55
|
+
|
56
|
+
# Most of the magick is in this hook which creates a closure over the parent class and then builds an
|
57
|
+
# "infector" module which infects all descendants and which is responsible for updating the list of
|
58
|
+
# descendants in the parent class.
|
59
|
+
def included(klass)
|
60
|
+
super
|
61
|
+
parent_klass = self
|
62
|
+
infector = Module.new do
|
63
|
+
define_method(:included) do |subklass|
|
64
|
+
super(subklass)
|
65
|
+
subklass.extend(infector)
|
66
|
+
parent_klass.descendants.push(subklass)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
klass.extend(infector)
|
70
|
+
parent_klass.descendants.push(klass)
|
71
|
+
end
|
72
|
+
|
73
|
+
def descendants
|
74
|
+
@descendants ||= []
|
75
|
+
end
|
76
|
+
|
77
|
+
def include(*classes)
|
78
|
+
super
|
79
|
+
classes.each do |klass|
|
80
|
+
descendants.each do |descendant|
|
81
|
+
descendant.send(:include, klass)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|