chef 0.7.10

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of chef might be problematic. Click here for more details.

Files changed (120) hide show
  1. data/LICENSE +201 -0
  2. data/README.rdoc +135 -0
  3. data/bin/chef-client +26 -0
  4. data/bin/chef-solo +26 -0
  5. data/lib/chef.rb +49 -0
  6. data/lib/chef/application.rb +98 -0
  7. data/lib/chef/application/agent.rb +18 -0
  8. data/lib/chef/application/client.rb +209 -0
  9. data/lib/chef/application/indexer.rb +141 -0
  10. data/lib/chef/application/server.rb +18 -0
  11. data/lib/chef/application/solo.rb +214 -0
  12. data/lib/chef/client.rb +396 -0
  13. data/lib/chef/compile.rb +138 -0
  14. data/lib/chef/config.rb +141 -0
  15. data/lib/chef/cookbook.rb +144 -0
  16. data/lib/chef/cookbook/metadata.rb +407 -0
  17. data/lib/chef/cookbook/metadata/version.rb +87 -0
  18. data/lib/chef/cookbook_loader.rb +168 -0
  19. data/lib/chef/couchdb.rb +172 -0
  20. data/lib/chef/daemon.rb +170 -0
  21. data/lib/chef/exceptions.rb +36 -0
  22. data/lib/chef/file_cache.rb +205 -0
  23. data/lib/chef/log.rb +39 -0
  24. data/lib/chef/mixin/check_helper.rb +31 -0
  25. data/lib/chef/mixin/checksum.rb +37 -0
  26. data/lib/chef/mixin/command.rb +351 -0
  27. data/lib/chef/mixin/create_path.rb +56 -0
  28. data/lib/chef/mixin/deep_merge.rb +36 -0
  29. data/lib/chef/mixin/find_preferred_file.rb +99 -0
  30. data/lib/chef/mixin/from_file.rb +36 -0
  31. data/lib/chef/mixin/generate_url.rb +48 -0
  32. data/lib/chef/mixin/language.rb +79 -0
  33. data/lib/chef/mixin/params_validate.rb +197 -0
  34. data/lib/chef/mixin/template.rb +84 -0
  35. data/lib/chef/node.rb +406 -0
  36. data/lib/chef/node/attribute.rb +412 -0
  37. data/lib/chef/openid_registration.rb +181 -0
  38. data/lib/chef/platform.rb +253 -0
  39. data/lib/chef/provider.rb +40 -0
  40. data/lib/chef/provider/cron.rb +137 -0
  41. data/lib/chef/provider/directory.rb +72 -0
  42. data/lib/chef/provider/execute.rb +58 -0
  43. data/lib/chef/provider/file.rb +191 -0
  44. data/lib/chef/provider/group.rb +120 -0
  45. data/lib/chef/provider/group/groupadd.rb +92 -0
  46. data/lib/chef/provider/group/pw.rb +88 -0
  47. data/lib/chef/provider/http_request.rb +102 -0
  48. data/lib/chef/provider/ifconfig.rb +131 -0
  49. data/lib/chef/provider/link.rb +157 -0
  50. data/lib/chef/provider/mount.rb +121 -0
  51. data/lib/chef/provider/mount/mount.rb +208 -0
  52. data/lib/chef/provider/package.rb +160 -0
  53. data/lib/chef/provider/package/apt.rb +110 -0
  54. data/lib/chef/provider/package/dpkg.rb +113 -0
  55. data/lib/chef/provider/package/freebsd.rb +153 -0
  56. data/lib/chef/provider/package/macports.rb +105 -0
  57. data/lib/chef/provider/package/portage.rb +124 -0
  58. data/lib/chef/provider/package/rpm.rb +99 -0
  59. data/lib/chef/provider/package/rubygems.rb +130 -0
  60. data/lib/chef/provider/package/yum-dump.py +104 -0
  61. data/lib/chef/provider/package/yum.rb +175 -0
  62. data/lib/chef/provider/remote_directory.rb +126 -0
  63. data/lib/chef/provider/remote_file.rb +134 -0
  64. data/lib/chef/provider/route.rb +118 -0
  65. data/lib/chef/provider/ruby_block.rb +15 -0
  66. data/lib/chef/provider/script.rb +42 -0
  67. data/lib/chef/provider/service.rb +129 -0
  68. data/lib/chef/provider/service/debian.rb +64 -0
  69. data/lib/chef/provider/service/freebsd.rb +157 -0
  70. data/lib/chef/provider/service/gentoo.rb +54 -0
  71. data/lib/chef/provider/service/init.rb +126 -0
  72. data/lib/chef/provider/service/redhat.rb +62 -0
  73. data/lib/chef/provider/template.rb +141 -0
  74. data/lib/chef/provider/user.rb +170 -0
  75. data/lib/chef/provider/user/pw.rb +113 -0
  76. data/lib/chef/provider/user/useradd.rb +107 -0
  77. data/lib/chef/queue.rb +145 -0
  78. data/lib/chef/recipe.rb +210 -0
  79. data/lib/chef/resource.rb +256 -0
  80. data/lib/chef/resource/apt_package.rb +34 -0
  81. data/lib/chef/resource/bash.rb +33 -0
  82. data/lib/chef/resource/cron.rb +143 -0
  83. data/lib/chef/resource/csh.rb +33 -0
  84. data/lib/chef/resource/directory.rb +76 -0
  85. data/lib/chef/resource/dpkg_package.rb +34 -0
  86. data/lib/chef/resource/execute.rb +127 -0
  87. data/lib/chef/resource/file.rb +84 -0
  88. data/lib/chef/resource/gem_package.rb +41 -0
  89. data/lib/chef/resource/group.rb +68 -0
  90. data/lib/chef/resource/http_request.rb +52 -0
  91. data/lib/chef/resource/ifconfig.rb +134 -0
  92. data/lib/chef/resource/link.rb +78 -0
  93. data/lib/chef/resource/macports_package.rb +29 -0
  94. data/lib/chef/resource/mount.rb +135 -0
  95. data/lib/chef/resource/package.rb +80 -0
  96. data/lib/chef/resource/perl.rb +33 -0
  97. data/lib/chef/resource/portage_package.rb +33 -0
  98. data/lib/chef/resource/python.rb +33 -0
  99. data/lib/chef/resource/remote_directory.rb +91 -0
  100. data/lib/chef/resource/remote_file.rb +60 -0
  101. data/lib/chef/resource/route.rb +135 -0
  102. data/lib/chef/resource/ruby.rb +33 -0
  103. data/lib/chef/resource/ruby_block.rb +20 -0
  104. data/lib/chef/resource/script.rb +51 -0
  105. data/lib/chef/resource/service.rb +134 -0
  106. data/lib/chef/resource/template.rb +60 -0
  107. data/lib/chef/resource/user.rb +98 -0
  108. data/lib/chef/resource_collection.rb +176 -0
  109. data/lib/chef/resource_definition.rb +67 -0
  110. data/lib/chef/rest.rb +238 -0
  111. data/lib/chef/role.rb +231 -0
  112. data/lib/chef/run_list.rb +156 -0
  113. data/lib/chef/runner.rb +123 -0
  114. data/lib/chef/search.rb +88 -0
  115. data/lib/chef/search/result.rb +64 -0
  116. data/lib/chef/search_index.rb +77 -0
  117. data/lib/chef/tasks/chef_repo.rake +345 -0
  118. data/lib/chef/util/file_edit.rb +125 -0
  119. data/lib/chef/util/fileedit.rb +121 -0
  120. metadata +262 -0
@@ -0,0 +1,396 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'chef/config'
19
+ require 'chef/mixin/params_validate'
20
+ require 'chef/mixin/generate_url'
21
+ require 'chef/mixin/checksum'
22
+ require 'chef/log'
23
+ require 'chef/rest'
24
+ require 'chef/platform'
25
+ require 'chef/node'
26
+ require 'chef/role'
27
+ require 'chef/file_cache'
28
+ require 'chef/compile'
29
+ require 'chef/runner'
30
+ require 'ohai'
31
+
32
+ class Chef
33
+ class Client
34
+
35
+ include Chef::Mixin::GenerateURL
36
+ include Chef::Mixin::Checksum
37
+
38
+ attr_accessor :node, :registration, :safe_name, :json_attribs, :validation_token, :node_name, :ohai
39
+
40
+ # Creates a new Chef::Client.
41
+ def initialize()
42
+ @node = nil
43
+ @safe_name = nil
44
+ @validation_token = nil
45
+ @registration = nil
46
+ @json_attribs = nil
47
+ @node_name = nil
48
+ @node_exists = true
49
+ Ohai::Log.logger = Chef::Log.logger
50
+ @ohai = Ohai::System.new
51
+ @rest = Chef::REST.new(Chef::Config[:registration_url])
52
+ end
53
+
54
+ # Do a full run for this Chef::Client. Calls:
55
+ #
56
+ # * build_node - Get the last known state, merge with local changes
57
+ # * register - Make sure we have an openid
58
+ # * authenticate - Authenticate with our openid
59
+ # * sync_definitions - Populate the local cache with all the definitions
60
+ # * sync_recipes - Populate the local cache with all the recipes
61
+ # * do_attribute_files - Populate the local cache with all attributes, and execute them
62
+ # * save_node - Store the new node configuration
63
+ # * converge - Bring this system up to date, based on the local cache
64
+ # * save_node - Store the node again, in case convergence altered future state
65
+ #
66
+ # === Returns
67
+ # true:: Always returns true.
68
+ def run
69
+ start_time = Time.now
70
+ Chef::Log.info("Starting Chef Run")
71
+
72
+ determine_node_name
73
+ register
74
+ authenticate
75
+ build_node(@node_name)
76
+ save_node
77
+ sync_library_files
78
+ sync_attribute_files
79
+ sync_definitions
80
+ sync_recipes
81
+ save_node
82
+ converge
83
+ save_node
84
+
85
+ end_time = Time.now
86
+ Chef::Log.info("Chef Run complete in #{end_time - start_time} seconds")
87
+ true
88
+ end
89
+
90
+ # Similar to Chef::Client#run, but instead of talking to the Chef server,
91
+ # simply runs in a standalone ("solo") mode.
92
+ #
93
+ # Someday, we'll have chef_chewbacca.
94
+ #
95
+ # === Returns
96
+ # true:: Always returns true.
97
+ def run_solo
98
+ start_time = Time.now
99
+ Chef::Log.info("Starting Chef Solo Run")
100
+
101
+ determine_node_name
102
+ build_node(@node_name, true)
103
+ converge(true)
104
+
105
+ end_time = Time.now
106
+ Chef::Log.info("Chef Run complete in #{end_time - start_time} seconds")
107
+ true
108
+ end
109
+
110
+ def run_ohai
111
+ if @ohai.keys
112
+ @ohai.refresh_plugins
113
+ else
114
+ @ohai.all_plugins
115
+ end
116
+ end
117
+
118
+ def determine_node_name
119
+ run_ohai
120
+ unless @safe_name && @node_name
121
+ @node_name ||= @ohai[:fqdn] ? @ohai[:fqdn] : @ohai[:hostname]
122
+ @safe_name = @node_name.gsub(/\./, '_')
123
+ end
124
+ @node_name
125
+ end
126
+
127
+ # Builds a new node object for this client. Starts with querying for the FQDN of the current
128
+ # host (unless it is supplied), then merges in the facts from Ohai.
129
+ #
130
+ # === Parameters
131
+ # node_name<String>:: The name of the node to build - defaults to nil
132
+ #
133
+ # === Returns
134
+ # node<Chef::Node>:: Returns the created node object, also stored in @node
135
+ def build_node(node_name=nil, solo=false)
136
+ node_name ||= determine_node_name
137
+ raise RuntimeError, "Unable to determine node name from ohai" unless node_name
138
+ Chef::Log.debug("Building node object for #{@safe_name}")
139
+ unless solo
140
+ begin
141
+ @node = @rest.get_rest("nodes/#{@safe_name}")
142
+ rescue Net::HTTPServerException => e
143
+ unless e.message =~ /^404/
144
+ raise e
145
+ end
146
+ end
147
+ end
148
+ unless @node
149
+ @node_exists = false
150
+ @node ||= Chef::Node.new
151
+ @node.name(node_name)
152
+ end
153
+ if @json_attribs
154
+ Chef::Log.debug("Adding JSON Attributes")
155
+ @json_attribs.each do |key, value|
156
+ if key == "recipes" || key == "run_list"
157
+ value.each do |recipe|
158
+ unless @node.recipes.detect { |r| r == recipe }
159
+ Chef::Log.debug("Adding recipe #{recipe}")
160
+ @node.recipes << recipe
161
+ end
162
+ end
163
+ else
164
+ Chef::Log.debug("JSON Attribute: #{key} - #{value.inspect}")
165
+ @node[key] = value
166
+ end
167
+ end
168
+ end
169
+ ohai.each do |field, value|
170
+ Chef::Log.debug("Ohai Attribute: #{field} - #{value.inspect}")
171
+ @node[field] = value
172
+ end
173
+ platform, version = Chef::Platform.find_platform_and_version(@node)
174
+ Chef::Log.debug("Platform is #{platform} version #{version}")
175
+ @node[:platform] = platform
176
+ @node[:platform_version] = version
177
+ @node[:tags] = Array.new unless @node.attribute?(:tags)
178
+ @node
179
+ end
180
+
181
+ # If this node has been registered before, this method will fetch the current registration
182
+ # data.
183
+ #
184
+ # If it has not, we register it by calling create_registration.
185
+ #
186
+ # === Returns
187
+ # true:: Always returns true
188
+ def register
189
+ determine_node_name unless @node_name
190
+ Chef::Log.debug("Registering #{@safe_name} for an openid")
191
+
192
+ begin
193
+ if @rest.get_rest("registrations/#{@safe_name}")
194
+ @secret = Chef::FileCache.load(File.join("registration", @safe_name))
195
+ end
196
+ rescue Net::HTTPServerException => e
197
+ case e.message
198
+ when /^404/
199
+ create_registration
200
+ else
201
+ raise
202
+ end
203
+ rescue Chef::Exceptions::FileNotFound
204
+ Chef::Application.fatal! "A remote registration already exists for #{@safe_name}, however the local shared secret does not exist." +
205
+ " To remedy this, you could delete the registration via webUI/REST, change the node_name option in config.rb" +
206
+ " (or use the -N/--node-name option to the CLI) or" +
207
+ " copy the old shared secret to #{File.join(Chef::Config[:file_cache_path], 'registration', @safe_name)}", 3
208
+ end
209
+
210
+ true
211
+ end
212
+
213
+ # Generates a random secret, stores it in the Chef::Filestore with the "registration" key,
214
+ # and posts our nodes registration information to the server.
215
+ #
216
+ # === Returns
217
+ # true:: Always returns true
218
+ def create_registration
219
+ @secret = random_password(500)
220
+ Chef::FileCache.store(File.join("registration", @safe_name), @secret)
221
+ @rest.post_rest("registrations", { :id => @safe_name, :password => @secret, :validation_token => @validation_token })
222
+ true
223
+ end
224
+
225
+ # Authenticates the node via OpenID.
226
+ #
227
+ # === Returns
228
+ # true:: Always returns true
229
+ def authenticate
230
+ determine_node_name unless @node_name
231
+ Chef::Log.debug("Authenticating #{@safe_name} via openid")
232
+ response = @rest.post_rest('openid/consumer/start', {
233
+ "openid_identifier" => "#{Chef::Config[:openid_url]}/openid/server/node/#{@safe_name}",
234
+ "submit" => "Verify"
235
+ })
236
+ @rest.post_rest(
237
+ "#{Chef::Config[:openid_url]}#{response["action"]}",
238
+ { "password" => @secret }
239
+ )
240
+ end
241
+
242
+ # Update the file caches for a given cache segment. Takes a segment name
243
+ # and a hash that matches one of the cookbooks/_attribute_files style
244
+ # remote file listings.
245
+ #
246
+ # === Parameters
247
+ # segment<String>:: The cache segment to update
248
+ # remote_list<Hash>:: A cookbooks/_attribute_files style remote file listing
249
+ def update_file_cache(segment, remote_list)
250
+ # We need the list of known good attribute files, so we can delete any that are
251
+ # just laying about.
252
+ file_canonical = Hash.new
253
+
254
+ remote_list.each do |rf|
255
+ cache_file = File.join("cookbooks", rf['cookbook'], segment, rf['name'])
256
+ file_canonical[cache_file] = true
257
+
258
+ # For back-compat between older clients and new chef servers
259
+ rf['checksum'] ||= nil
260
+
261
+ current_checksum = nil
262
+ if Chef::FileCache.has_key?(cache_file)
263
+ current_checksum = checksum(Chef::FileCache.load(cache_file, false))
264
+ end
265
+
266
+ rf_url = generate_cookbook_url(
267
+ rf['name'],
268
+ rf['cookbook'],
269
+ segment,
270
+ @node,
271
+ current_checksum ? { 'checksum' => current_checksum } : nil
272
+ )
273
+ Chef::Log.debug(rf_url)
274
+
275
+ if current_checksum != rf['checksum']
276
+ changed = true
277
+ begin
278
+ raw_file = @rest.get_rest(rf_url, true)
279
+ rescue Net::HTTPRetriableError => e
280
+ if e.response.kind_of?(Net::HTTPNotModified)
281
+ changed = false
282
+ Chef::Log.debug("Cache file #{cache_file} is unchanged")
283
+ else
284
+ raise e
285
+ end
286
+ end
287
+
288
+ if changed
289
+ Chef::Log.info("Storing updated #{cache_file} in the cache.")
290
+ Chef::FileCache.move_to(raw_file.path, cache_file)
291
+ end
292
+ end
293
+ end
294
+
295
+ Chef::FileCache.list.each do |cache_file|
296
+ if cache_file.match("cookbooks/.+?/#{segment}")
297
+ unless file_canonical[cache_file]
298
+ Chef::Log.info("Removing #{cache_file} from the cache; it is no longer on the server.")
299
+ Chef::FileCache.delete(cache_file)
300
+ end
301
+ end
302
+ end
303
+
304
+ end
305
+
306
+ # Gets all the attribute files included in all the cookbooks available on the server,
307
+ # and executes them.
308
+ #
309
+ # === Returns
310
+ # true:: Always returns true
311
+ def sync_attribute_files
312
+ Chef::Log.debug("Synchronizing attributes")
313
+ update_file_cache("attributes", @rest.get_rest("cookbooks/_attribute_files?node=#{@node.name}"))
314
+ true
315
+ end
316
+
317
+ # Gets all the library files included in all the cookbooks available on the server,
318
+ # and loads them.
319
+ #
320
+ # === Returns
321
+ # true:: Always returns true
322
+ def sync_library_files
323
+ Chef::Log.debug("Synchronizing libraries")
324
+ update_file_cache("libraries", @rest.get_rest("cookbooks/_library_files?node=#{@node.name}"))
325
+ true
326
+ end
327
+
328
+ # Gets all the definition files included in all the cookbooks available on the server,
329
+ # and loads them.
330
+ #
331
+ # === Returns
332
+ # true:: Always returns true
333
+ def sync_definitions
334
+ Chef::Log.debug("Synchronizing definitions")
335
+ update_file_cache("definitions", @rest.get_rest("cookbooks/_definition_files?node=#{@node.name}"))
336
+ end
337
+
338
+ # Gets all the recipe files included in all the cookbooks available on the server,
339
+ # and loads them.
340
+ #
341
+ # === Returns
342
+ # true:: Always returns true
343
+ def sync_recipes
344
+ Chef::Log.debug("Synchronizing recipes")
345
+ update_file_cache("recipes", @rest.get_rest("cookbooks/_recipe_files?node=#{@node.name}"))
346
+ end
347
+
348
+ # Updates the current node configuration on the server.
349
+ #
350
+ # === Returns
351
+ # true:: Always returns true
352
+ def save_node
353
+ Chef::Log.debug("Saving the current state of node #{@safe_name}")
354
+ if @node_exists
355
+ @node = @rest.put_rest("nodes/#{@safe_name}", @node)
356
+ else
357
+ result = @rest.post_rest("nodes", @node)
358
+ @node = @rest.get_rest(result['uri'])
359
+ @node_exists = true
360
+ end
361
+ true
362
+ end
363
+
364
+ # Compiles the full list of recipes for the server, and passes it to an instance of
365
+ # Chef::Runner.converge.
366
+ #
367
+ # === Returns
368
+ # true:: Always returns true
369
+ def converge(solo=false)
370
+ Chef::Log.debug("Compiling recipes for node #{@safe_name}")
371
+ unless solo
372
+ Chef::Config[:cookbook_path] = File.join(Chef::Config[:file_cache_path], "cookbooks")
373
+ end
374
+ compile = Chef::Compile.new(@node)
375
+ compile.load_libraries
376
+ compile.load_attributes
377
+ compile.load_definitions
378
+ compile.load_recipes
379
+
380
+ Chef::Log.debug("Converging node #{@safe_name}")
381
+ cr = Chef::Runner.new(@node, compile.collection)
382
+ cr.converge
383
+ true
384
+ end
385
+
386
+ protected
387
+ # Generates a random password of "len" length.
388
+ def random_password(len)
389
+ chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
390
+ newpass = ""
391
+ 1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
392
+ newpass
393
+ end
394
+
395
+ end
396
+ end
@@ -0,0 +1,138 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'chef/cookbook_loader'
19
+ require 'chef/resource_collection'
20
+ require 'chef/node'
21
+ require 'chef/role'
22
+ require 'chef/log'
23
+ require 'chef/mixin/deep_merge'
24
+
25
+ class Chef
26
+ class Compile
27
+
28
+ attr_accessor :node, :cookbook_loader, :collection, :definitions
29
+
30
+ # Creates a new Chef::Compile object. This object gets used by the Chef Server to generate
31
+ # a fully compiled recipe list for a node.
32
+ #
33
+ # === Returns
34
+ # object<Chef::Compile>:: Duh. :)
35
+ def initialize(node=nil)
36
+ @node = node
37
+ @cookbook_loader = Chef::CookbookLoader.new
38
+ @collection = Chef::ResourceCollection.new
39
+ @definitions = Hash.new
40
+ @recipes = Array.new
41
+ @default_attributes = Array.new
42
+ @override_attributes = Array.new
43
+ end
44
+
45
+ # Looks up the node via the "name" argument, first from CouchDB, then by calling
46
+ # Chef::Node.find_file(name)
47
+ #
48
+ # The first step in compiling the catalog. Results available via the node accessor.
49
+ #
50
+ # === Returns
51
+ # node<Chef::Node>:: The loaded Chef Node
52
+ def load_node(name)
53
+ Chef::Log.debug("Loading Chef Node #{name} from CouchDB")
54
+ @node = Chef::Node.load(name)
55
+ Chef::Log.debug("Loading Recipe for Chef Node #{name}")
56
+ @node.find_file(name)
57
+ @node
58
+ end
59
+
60
+ # Load all the attributes, from every cookbook
61
+ #
62
+ # === Returns
63
+ # true:: Always returns true
64
+ def load_attributes()
65
+ recipes, default_attrs, override_attrs = expand_node
66
+
67
+ @cookbook_loader.each do |cookbook|
68
+ cookbook.load_attributes(@node)
69
+ end
70
+
71
+ true
72
+ end
73
+
74
+ # Load all the definitions, from every cookbook, so they are available when we process
75
+ # the recipes.
76
+ #
77
+ # Results available via the definitions accessor.
78
+ #
79
+ # === Returns
80
+ # true:: Always returns true
81
+ def load_definitions()
82
+ @cookbook_loader.each do |cookbook|
83
+ hash = cookbook.load_definitions
84
+ @definitions.merge!(hash)
85
+ end
86
+ true
87
+ end
88
+
89
+ # Load all the libraries, from every cookbook, so they are available when we process
90
+ # the recipes.
91
+ #
92
+ # === Returns
93
+ # true:: Always returns true
94
+ def load_libraries()
95
+ @cookbook_loader.each do |cookbook|
96
+ cookbook.load_libraries
97
+ end
98
+ true
99
+ end
100
+
101
+ # Load all the recipes specified in the node data (loaded via load_node, above.)
102
+ #
103
+ # The results are available via the collection accessor (which returns a Chef::ResourceCollection
104
+ # object)
105
+ #
106
+ # === Returns
107
+ # true:: Always returns true
108
+ def load_recipes
109
+ expand_node
110
+ @recipes.each do |recipe|
111
+ if @node.run_state[:seen_recipes].has_key?(recipe)
112
+ Chef::Log.debug("I am not loading #{recipe}, because I have already seen it.")
113
+ next
114
+ end
115
+ Chef::Log.debug("Loading Recipe #{recipe}")
116
+ @node.run_state[:seen_recipes][recipe] = true
117
+
118
+ rmatch = recipe.match(/(.+?)::(.+)/)
119
+ if rmatch
120
+ cookbook = @cookbook_loader[rmatch[1]]
121
+ cookbook.load_recipe(rmatch[2], @node, @collection, @definitions, @cookbook_loader)
122
+ else
123
+ cookbook = @cookbook_loader[recipe]
124
+ cookbook.load_recipe("default", @node, @collection, @definitions, @cookbook_loader)
125
+ end
126
+ end
127
+ true
128
+ end
129
+
130
+ def expand_node
131
+ @recipes, @default_attributes, @override_attributes = @node.run_list.expand
132
+ @node.default = @default_attributes
133
+ @node.override = @override_attributes
134
+ return @recipes, @default_attributes, @override_attributes
135
+ end
136
+
137
+ end
138
+ end