chef 0.9.8 → 0.9.10.rc.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -1
- data/distro/common/man/man8/knife.8 +89 -79
- data/distro/common/markdown/knife.mkd +7 -0
- data/distro/debian/etc/default/chef-server +3 -0
- data/distro/debian/etc/default/chef-server-webui +3 -0
- data/distro/debian/etc/default/chef-solr +3 -0
- data/distro/debian/etc/default/chef-solr-indexer +3 -0
- data/distro/debian/etc/init.d/chef-server +3 -1
- data/distro/debian/etc/init.d/chef-server-webui +3 -1
- data/distro/redhat/etc/init.d/chef-client +1 -1
- data/lib/chef/application.rb +2 -0
- data/lib/chef/application/client.rb +5 -3
- data/lib/chef/application/knife.rb +16 -5
- data/lib/chef/application/solo.rb +0 -1
- data/lib/chef/checksum.rb +65 -1
- data/lib/chef/checksum_cache.rb +173 -0
- data/lib/chef/client.rb +84 -121
- data/lib/chef/cookbook/remote_file_vendor.rb +10 -3
- data/lib/chef/cookbook/syntax_check.rb +2 -2
- data/lib/chef/cookbook_loader.rb +2 -0
- data/lib/chef/cookbook_site_streaming_uploader.rb +29 -0
- data/lib/chef/cookbook_uploader.rb +8 -7
- data/lib/chef/cookbook_version.rb +155 -114
- data/lib/chef/exceptions.rb +5 -0
- data/lib/chef/handler.rb +43 -0
- data/lib/chef/index_queue/consumer.rb +1 -1
- data/lib/chef/index_queue/indexable.rb +1 -1
- data/lib/chef/knife.rb +18 -5
- data/lib/chef/knife/bootstrap.rb +2 -2
- data/lib/chef/knife/bootstrap/archlinux-gems.erb +44 -0
- data/lib/chef/knife/bootstrap/client-install.vbs +80 -0
- data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +2 -2
- data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +6 -7
- data/lib/chef/knife/bootstrap/windows-gems.erb +34 -0
- data/lib/chef/knife/configure_client.rb +4 -2
- data/lib/chef/knife/cookbook_metadata.rb +1 -1
- data/lib/chef/knife/cookbook_site_share.rb +2 -1
- data/lib/chef/knife/cookbook_site_vendor.rb +6 -0
- data/lib/chef/knife/cookbook_test.rb +1 -1
- data/lib/chef/knife/ec2_server_create.rb +51 -26
- data/lib/chef/knife/exec.rb +52 -0
- data/lib/chef/knife/ssh.rb +27 -15
- data/lib/chef/knife/status.rb +27 -10
- data/lib/chef/knife/windows_bootstrap.rb +154 -0
- data/lib/chef/mixin/checksum.rb +2 -2
- data/lib/chef/mixin/xml_escape.rb +75 -49
- data/lib/chef/node.rb +54 -58
- data/lib/chef/node/attribute.rb +61 -53
- data/lib/chef/platform.rb +19 -2
- data/lib/chef/provider/breakpoint.rb +1 -1
- data/lib/chef/provider/cookbook_file.rb +3 -3
- data/lib/chef/provider/cron.rb +3 -3
- data/lib/chef/provider/cron/solaris.rb +195 -0
- data/lib/chef/provider/deploy.rb +3 -3
- data/lib/chef/provider/directory.rb +2 -2
- data/lib/chef/provider/env.rb +5 -5
- data/lib/chef/provider/execute.rb +1 -1
- data/lib/chef/provider/file.rb +10 -9
- data/lib/chef/provider/git.rb +12 -4
- data/lib/chef/provider/group.rb +5 -5
- data/lib/chef/provider/http_request.rb +25 -9
- data/lib/chef/provider/ifconfig.rb +2 -2
- data/lib/chef/provider/link.rb +11 -6
- data/lib/chef/provider/log.rb +1 -0
- data/lib/chef/provider/mdadm.rb +3 -3
- data/lib/chef/provider/mount.rb +5 -5
- data/lib/chef/provider/mount/mount.rb +1 -1
- data/lib/chef/provider/ohai.rb +41 -0
- data/lib/chef/provider/package.rb +5 -5
- data/lib/chef/provider/package/yum-dump.py +5 -2
- data/lib/chef/provider/remote_directory.rb +11 -5
- data/lib/chef/provider/remote_file.rb +2 -2
- data/lib/chef/provider/route.rb +154 -133
- data/lib/chef/provider/ruby_block.rb +1 -1
- data/lib/chef/provider/service.rb +6 -6
- data/lib/chef/provider/subversion.rb +12 -9
- data/lib/chef/provider/template.rb +2 -2
- data/lib/chef/provider/user.rb +7 -7
- data/lib/chef/provider/user/useradd.rb +15 -1
- data/lib/chef/providers.rb +2 -0
- data/lib/chef/resource.rb +164 -58
- data/lib/chef/resource/http_request.rb +9 -0
- data/lib/chef/resource/ohai.rb +40 -0
- data/lib/chef/resource/remote_directory.rb +10 -1
- data/lib/chef/resource/rpm_package.rb +34 -0
- data/lib/chef/resource_collection.rb +3 -2
- data/lib/chef/resources.rb +2 -0
- data/lib/chef/rest.rb +13 -7
- data/lib/chef/rest/auth_credentials.rb +1 -1
- data/lib/chef/rest/rest_request.rb +3 -1
- data/lib/chef/runner.rb +31 -55
- data/lib/chef/shef/shef_session.rb +1 -1
- data/lib/chef/util/windows/net_use.rb +1 -1
- data/lib/chef/version.rb +1 -1
- data/lib/chef/webui_user.rb +0 -1
- metadata +38 -19
- data/lib/chef/cache.rb +0 -61
- data/lib/chef/cache/checksum.rb +0 -91
@@ -19,6 +19,7 @@
|
|
19
19
|
# limitations under the License.
|
20
20
|
|
21
21
|
require 'chef/log'
|
22
|
+
require 'chef/client'
|
22
23
|
require 'chef/node'
|
23
24
|
require 'chef/resource_definition_list'
|
24
25
|
require 'chef/recipe'
|
@@ -39,7 +40,7 @@ class Chef
|
|
39
40
|
COOKBOOK_SEGMENTS = [ :resources, :providers, :recipes, :definitions, :libraries, :attributes, :files, :templates, :root_files ]
|
40
41
|
|
41
42
|
DESIGN_DOCUMENT = {
|
42
|
-
"version" =>
|
43
|
+
"version" => 7,
|
43
44
|
"language" => "javascript",
|
44
45
|
"views" => {
|
45
46
|
"all" => {
|
@@ -89,8 +90,8 @@ class Chef
|
|
89
90
|
continue;
|
90
91
|
}
|
91
92
|
|
92
|
-
var valueParts = value
|
93
|
-
var resultParts = result
|
93
|
+
var valueParts = value.split('.').map(function(v) { return parseInt(v); });
|
94
|
+
var resultParts = result.split('.').map(function(v) { return parseInt(v); });
|
94
95
|
|
95
96
|
if (valueParts[0] != resultParts[0]) {
|
96
97
|
if (valueParts[0] > resultParts[0]) {
|
@@ -116,7 +117,7 @@ class Chef
|
|
116
117
|
"map" => %q@
|
117
118
|
function(doc) {
|
118
119
|
if (doc.chef_type == "cookbook_version") {
|
119
|
-
emit(doc.cookbook_name, doc.version);
|
120
|
+
emit(doc.cookbook_name, {version: doc.version, id:doc._id});
|
120
121
|
}
|
121
122
|
}
|
122
123
|
@,
|
@@ -132,8 +133,8 @@ class Chef
|
|
132
133
|
continue;
|
133
134
|
}
|
134
135
|
|
135
|
-
var valueParts = value
|
136
|
-
var resultParts = result
|
136
|
+
var valueParts = value.version.split('.').map(function(v) { return parseInt(v); });
|
137
|
+
var resultParts = result.version.split('.').map(function(v) { return parseInt(v); });
|
137
138
|
|
138
139
|
if (valueParts[0] != resultParts[0]) {
|
139
140
|
if (valueParts[0] > resultParts[0]) {
|
@@ -151,13 +152,14 @@ class Chef
|
|
151
152
|
}
|
152
153
|
}
|
153
154
|
}
|
154
|
-
return
|
155
|
+
return result;
|
155
156
|
}
|
156
157
|
@
|
157
158
|
},
|
158
159
|
}
|
159
160
|
}
|
160
161
|
|
162
|
+
attr_accessor :root_dir
|
161
163
|
attr_accessor :definition_filenames
|
162
164
|
attr_accessor :template_filenames
|
163
165
|
attr_accessor :file_filenames
|
@@ -188,12 +190,132 @@ class Chef
|
|
188
190
|
# This is the one and only method that knows how cookbook files'
|
189
191
|
# checksums are generated.
|
190
192
|
def self.checksum_cookbook_file(filepath)
|
191
|
-
Chef::
|
193
|
+
Chef::ChecksumCache.generate_md5_checksum_for_file(filepath)
|
192
194
|
rescue Errno::ENOENT
|
193
195
|
Chef::Log.debug("File #{filepath} does not exist, so there is no checksum to generate")
|
194
196
|
nil
|
195
197
|
end
|
196
198
|
|
199
|
+
# Keep track of the filenames that we use in both eager cookbook
|
200
|
+
# downloading (during sync_cookbooks) and lazy (during the run
|
201
|
+
# itself, through FileVendor). After the run is over, clean up the
|
202
|
+
# cache.
|
203
|
+
def self.valid_cache_entries
|
204
|
+
@valid_cache_entries ||= {}
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.reset_cache_validity
|
208
|
+
@valid_cache_entries = nil
|
209
|
+
end
|
210
|
+
|
211
|
+
# Setup a notification to clear the valid_cache_entries when a Chef client
|
212
|
+
# run starts
|
213
|
+
Chef::Client.when_run_starts do |run_status|
|
214
|
+
reset_cache_validity
|
215
|
+
end
|
216
|
+
|
217
|
+
# Synchronizes all the cookbooks from the chef-server.
|
218
|
+
#
|
219
|
+
# === Returns
|
220
|
+
# true:: Always returns true
|
221
|
+
def self.sync_cookbooks(cookbook_hash)
|
222
|
+
Chef::Log.debug("Cookbooks to load: #{cookbook_hash.inspect}")
|
223
|
+
|
224
|
+
# Remove all cookbooks no longer relevant to this node
|
225
|
+
Chef::FileCache.find(File.join(%w{cookbooks ** *})).each do |cache_file|
|
226
|
+
cache_file =~ /^cookbooks\/([^\/]+)\//
|
227
|
+
unless cookbook_hash.has_key?($1)
|
228
|
+
Chef::Log.info("Removing #{cache_file} from the cache; its cookbook is no longer needed on this client.")
|
229
|
+
Chef::FileCache.delete(cache_file)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Synchronize each of the node's cookbooks, and add to the
|
234
|
+
# valid_cache_entries hash.
|
235
|
+
cookbook_hash.values.each do |cookbook|
|
236
|
+
sync_cookbook_file_cache(cookbook)
|
237
|
+
end
|
238
|
+
|
239
|
+
true
|
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
|
+
# cookbook<Chef::Cookbook>:: The cookbook to update
|
248
|
+
# valid_cache_entries<Hash>:: Out-param; Added to this hash are the files that
|
249
|
+
# were referred to by this cookbook
|
250
|
+
def self.sync_cookbook_file_cache(cookbook)
|
251
|
+
Chef::Log.debug("Synchronizing cookbook #{cookbook.name}")
|
252
|
+
|
253
|
+
# files and templates are lazily loaded, and will be done later.
|
254
|
+
eager_segments = COOKBOOK_SEGMENTS.dup
|
255
|
+
eager_segments.delete(:files)
|
256
|
+
eager_segments.delete(:templates)
|
257
|
+
|
258
|
+
eager_segments.each do |segment|
|
259
|
+
segment_filenames = Array.new
|
260
|
+
cookbook.manifest[segment].each do |manifest_record|
|
261
|
+
# segment = cookbook segment
|
262
|
+
# remote_list = list of file hashes
|
263
|
+
#
|
264
|
+
# We need the list of known good attribute files, so we can delete any that are
|
265
|
+
# just laying about.
|
266
|
+
|
267
|
+
cache_filename = File.join("cookbooks", cookbook.name, manifest_record['path'])
|
268
|
+
valid_cache_entries[cache_filename] = true
|
269
|
+
|
270
|
+
current_checksum = nil
|
271
|
+
if Chef::FileCache.has_key?(cache_filename)
|
272
|
+
current_checksum = checksum_cookbook_file(Chef::FileCache.load(cache_filename, false))
|
273
|
+
end
|
274
|
+
|
275
|
+
# If the checksums are different between on-disk (current) and on-server
|
276
|
+
# (remote, per manifest), do the update. This will also execute if there
|
277
|
+
# is no current checksum.
|
278
|
+
if current_checksum != manifest_record['checksum']
|
279
|
+
raw_file = chef_server_rest.get_rest(manifest_record[:url], true)
|
280
|
+
|
281
|
+
Chef::Log.info("Storing updated #{cache_filename} in the cache.")
|
282
|
+
Chef::FileCache.move_to(raw_file.path, cache_filename)
|
283
|
+
else
|
284
|
+
Chef::Log.debug("Not storing #{cache_filename}, as the cache is up to date.")
|
285
|
+
end
|
286
|
+
|
287
|
+
# make the segment filenames a full path.
|
288
|
+
full_path_cache_filename = Chef::FileCache.load(cache_filename, false)
|
289
|
+
segment_filenames << full_path_cache_filename
|
290
|
+
end
|
291
|
+
|
292
|
+
# replace segment filenames with a full-path one.
|
293
|
+
if segment.to_sym == :recipes
|
294
|
+
cookbook.recipe_filenames = segment_filenames
|
295
|
+
elsif segment.to_sym == :attributes
|
296
|
+
cookbook.attribute_filenames = segment_filenames
|
297
|
+
else
|
298
|
+
cookbook.segment_filenames(segment).replace(segment_filenames)
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def self.cleanup_file_cache
|
304
|
+
# Delete each file in the cache that we didn't encounter in the
|
305
|
+
# manifest.
|
306
|
+
Chef::FileCache.find(File.join(%w{cookbooks ** *})).each do |cache_filename|
|
307
|
+
unless valid_cache_entries[cache_filename]
|
308
|
+
Chef::Log.info("Removing #{cache_filename} from the cache; it is no longer on the server.")
|
309
|
+
Chef::FileCache.delete(cache_filename)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
# Register a notification to cleanup unused files from cookbooks
|
315
|
+
Chef::Client.when_run_completes_successfully do |run_status|
|
316
|
+
cleanup_file_cache
|
317
|
+
end
|
318
|
+
|
197
319
|
# Creates a new Chef::CookbookVersion object.
|
198
320
|
#
|
199
321
|
# === Returns
|
@@ -210,6 +332,7 @@ class Chef
|
|
210
332
|
@resource_filenames = Array.new
|
211
333
|
@provider_filenames = Array.new
|
212
334
|
@metadata_filenames = Array.new
|
335
|
+
@root_dir = nil
|
213
336
|
@root_filenames = Array.new
|
214
337
|
@couchdb_id = nil
|
215
338
|
@couchdb = couchdb || Chef::CouchDB.new
|
@@ -473,113 +596,8 @@ class Chef
|
|
473
596
|
|
474
597
|
records_by_pref[best_pref]
|
475
598
|
end
|
476
|
-
|
477
|
-
# Given a node, segment and path (filename or directory name),
|
478
|
-
# return the priority-ordered list of preference locations to
|
479
|
-
# look.
|
480
|
-
def preferences_for_path(node, segment, path)
|
481
|
-
# only files and templates can be platform-specific
|
482
|
-
if segment.to_sym == :files || segment.to_sym == :templates
|
483
|
-
begin
|
484
|
-
platform, version = Chef::Platform.find_platform_and_version(node)
|
485
|
-
rescue ArgumentError => e
|
486
|
-
# Skip platform/version if they were not found by find_platform_and_version
|
487
|
-
if e.message =~ /Cannot find a (?:platform|version)/
|
488
|
-
platform = "/unknown_platform/"
|
489
|
-
version = "/unknown_platform_version/"
|
490
|
-
else
|
491
|
-
raise
|
492
|
-
end
|
493
|
-
end
|
494
|
-
|
495
|
-
fqdn = node[:fqdn]
|
496
|
-
|
497
|
-
# Most specific to least specific places to find the path
|
498
|
-
[
|
499
|
-
File.join(segment.to_s, "host-#{fqdn}", path),
|
500
|
-
File.join(segment.to_s, "#{platform}-#{version}", path),
|
501
|
-
File.join(segment.to_s, platform.to_s, path),
|
502
|
-
File.join(segment.to_s, "default", path)
|
503
|
-
]
|
504
|
-
else
|
505
|
-
[File.join(segment, path)]
|
506
|
-
end
|
507
|
-
end
|
508
|
-
private :preferences_for_path
|
509
|
-
|
510
|
-
|
511
|
-
def relative_filenames_in_preferred_directory(node, segment, dirname)
|
512
|
-
preferences = preferences_for_path(node, segment, dirname)
|
513
|
-
filenames_by_pref = Hash.new
|
514
|
-
preferences.each { |pref| filenames_by_pref[pref] = Array.new }
|
515
|
-
|
516
|
-
manifest[segment].each do |manifest_record|
|
517
|
-
manifest_record_path = manifest_record[:path]
|
518
|
-
|
519
|
-
# find the NON SPECIFIC filenames, but prefer them by filespecificity.
|
520
|
-
# For example, if we have a file:
|
521
|
-
# 'files/default/somedir/somefile.conf' we only keep
|
522
|
-
# 'somedir/somefile.conf'. If there is also
|
523
|
-
# 'files/$hostspecific/somedir/otherfiles' that matches the requested
|
524
|
-
# hostname specificity, that directory will win, as it is more specific.
|
525
|
-
#
|
526
|
-
# This is clearly ugly b/c the use case is for remote directory, where
|
527
|
-
# we're just going to make cookbook_files out of these and make the
|
528
|
-
# cookbook find them by filespecificity again. but it's the shortest
|
529
|
-
# path to "success" for now.
|
530
|
-
if manifest_record_path =~ /(#{Regexp.escape(segment.to_s)}\/[^\/]+\/#{Regexp.escape(dirname)})\/.+$/
|
531
|
-
specificity_dirname = $1
|
532
|
-
non_specific_path = manifest_record_path[/#{Regexp.escape(segment.to_s)}\/[^\/]+\/#{Regexp.escape(dirname)}\/(.+)$/, 1]
|
533
|
-
# Record the specificity_dirname only if it's in the list of
|
534
|
-
# valid preferences
|
535
|
-
if filenames_by_pref[specificity_dirname]
|
536
|
-
filenames_by_pref[specificity_dirname] << non_specific_path
|
537
|
-
end
|
538
|
-
end
|
539
|
-
end
|
540
|
-
|
541
|
-
best_pref = preferences.find { |pref| !filenames_by_pref[pref].empty? }
|
542
|
-
|
543
|
-
raise Chef::Exceptions::FileNotFound, "cookbook #{name} has no directory #{segment}/#{dirname}" unless best_pref
|
544
|
-
|
545
|
-
filenames_by_pref[best_pref]
|
546
|
-
|
547
|
-
end
|
548
|
-
|
549
|
-
# Determine the manifest records from the most specific directory
|
550
|
-
# for the given node. See #preferred_manifest_record for a
|
551
|
-
# description of entries of the returned Array.
|
552
|
-
def preferred_manifest_records_for_directory(node, segment, dirname)
|
553
|
-
preferences = preferences_for_path(node, segment, dirname)
|
554
|
-
records_by_pref = Hash.new
|
555
|
-
preferences.each { |pref| records_by_pref[pref] = Array.new }
|
556
|
-
|
557
|
-
manifest[segment].each do |manifest_record|
|
558
|
-
manifest_record_path = manifest_record[:path]
|
559
599
|
|
560
|
-
# extract the preference part from the path.
|
561
|
-
if manifest_record_path =~ /(#{Regexp.escape(segment.to_s)}\/[^\/]+\/#{Regexp.escape(dirname)})\/.+$/
|
562
|
-
# Note the specificy_dirname includes the segment and
|
563
|
-
# dirname argument as above, which is what
|
564
|
-
# preferences_for_path returns. It could be
|
565
|
-
# "files/ubuntu-9.10/dirname", for example.
|
566
|
-
specificity_dirname = $1
|
567
|
-
|
568
|
-
# Record the specificity_dirname only if it's in the list of
|
569
|
-
# valid preferences
|
570
|
-
if records_by_pref[specificity_dirname]
|
571
|
-
records_by_pref[specificity_dirname] << manifest_record
|
572
|
-
end
|
573
|
-
end
|
574
|
-
end
|
575
|
-
|
576
|
-
best_pref = preferences.find { |pref| !records_by_pref[pref].empty? }
|
577
|
-
|
578
|
-
raise Chef::Exceptions::FileNotFound, "cookbook #{name} has no directory #{segment}/#{dirname}" unless best_pref
|
579
600
|
|
580
|
-
records_by_pref[best_pref]
|
581
|
-
end
|
582
|
-
|
583
601
|
# Given a node, segment and path (filename or directory name),
|
584
602
|
# return the priority-ordered list of preference locations to
|
585
603
|
# look.
|
@@ -656,6 +674,20 @@ class Chef
|
|
656
674
|
rendered_manifest
|
657
675
|
end
|
658
676
|
|
677
|
+
def metadata_json_file
|
678
|
+
File.join(root_dir, "metadata.json")
|
679
|
+
end
|
680
|
+
|
681
|
+
def metadata_rb_file
|
682
|
+
File.join(root_dir, "metadata.rb")
|
683
|
+
end
|
684
|
+
|
685
|
+
def reload_metadata!
|
686
|
+
if File.exists?(metadata_json_file)
|
687
|
+
metadata.from_json(IO.read(metadata_json_file))
|
688
|
+
end
|
689
|
+
end
|
690
|
+
|
659
691
|
##
|
660
692
|
# REST API
|
661
693
|
##
|
@@ -727,7 +759,7 @@ class Chef
|
|
727
759
|
def self.cdb_list_latest(inflate=false, couchdb=nil)
|
728
760
|
couchdb ||= Chef::CouchDB.new
|
729
761
|
if inflate
|
730
|
-
doc_ids = cdb_list_latest_ids
|
762
|
+
doc_ids = cdb_list_latest_ids.map {|i|i["id"]}
|
731
763
|
couchdb.bulk_get(doc_ids)
|
732
764
|
else
|
733
765
|
results = couchdb.get_view("cookbooks", "all_latest_version", :group=>true)["rows"]
|
@@ -761,6 +793,15 @@ class Chef
|
|
761
793
|
(couchdb || Chef::CouchDB.new).delete("cookbook_version", full_name, couchdb_rev)
|
762
794
|
end
|
763
795
|
|
796
|
+
# Runs on Chef Server (API); deletes the cookbook from couchdb and also destroys associated
|
797
|
+
# checksum documents
|
798
|
+
def purge
|
799
|
+
checksums.keys.each do |checksum|
|
800
|
+
Chef::Checksum.cdb_load(checksum, couchdb).purge
|
801
|
+
end
|
802
|
+
cdb_destroy
|
803
|
+
end
|
804
|
+
|
764
805
|
def cdb_save
|
765
806
|
@couchdb_rev = couchdb.store("cookbook_version", full_name, self)["rev"]
|
766
807
|
end
|
data/lib/chef/exceptions.rb
CHANGED
@@ -57,5 +57,10 @@ class Chef
|
|
57
57
|
class DsclCommandFailed < RuntimeError; end
|
58
58
|
class UserIDNotFound < ArgumentError; end
|
59
59
|
class GroupIDNotFound < ArgumentError; end
|
60
|
+
class InvalidResourceReference < RuntimeError; end
|
61
|
+
class ResourceNotFound < RuntimeError; end
|
62
|
+
class InvalidResourceSpecification < ArgumentError; end
|
63
|
+
class SolrConnectionError < RuntimeError; end
|
64
|
+
class IllegalChecksumRevert < RuntimeError; end
|
60
65
|
end
|
61
66
|
end
|
data/lib/chef/handler.rb
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
|
+
require 'chef/client'
|
18
19
|
require 'forwardable'
|
19
20
|
|
20
21
|
class Chef
|
@@ -56,8 +57,50 @@ class Chef
|
|
56
57
|
#
|
57
58
|
class Handler
|
58
59
|
|
60
|
+
# The list of currently configured report handlers
|
61
|
+
def self.report_handlers
|
62
|
+
Array(Chef::Config[:report_handlers])
|
63
|
+
end
|
64
|
+
|
65
|
+
# Run the report handlers. This will usually be called by a notification
|
66
|
+
# from Chef::Client
|
67
|
+
def self.run_report_handlers(run_status)
|
68
|
+
Chef::Log.info("Running report handlers")
|
69
|
+
report_handlers.each do |handler|
|
70
|
+
handler.run_report_safely(run_status)
|
71
|
+
end
|
72
|
+
Chef::Log.info("Report handlers complete")
|
73
|
+
end
|
74
|
+
|
75
|
+
# Wire up a notification to run the report handlers if the chef run
|
76
|
+
# succeeds.
|
77
|
+
Chef::Client.when_run_completes_successfully do |run_status|
|
78
|
+
run_report_handlers(run_status)
|
79
|
+
end
|
80
|
+
|
81
|
+
# The list of currently configured exception handlers
|
82
|
+
def self.exception_handlers
|
83
|
+
Array(Chef::Config[:exception_handlers])
|
84
|
+
end
|
85
|
+
|
86
|
+
# Run the exception handlers. Usually will be called by a notification
|
87
|
+
# from Chef::Client when the run fails.
|
88
|
+
def self.run_exception_handlers(run_status)
|
89
|
+
Chef::Log.error("Running exception handlers")
|
90
|
+
exception_handlers.each do |handler|
|
91
|
+
handler.run_report_safely(run_status)
|
92
|
+
end
|
93
|
+
Chef::Log.error("Exception handlers complete")
|
94
|
+
end
|
95
|
+
|
96
|
+
# Wire up a notification to run the exception handlers if the chef run fails.
|
97
|
+
Chef::Client.when_run_fails do |run_status|
|
98
|
+
run_exception_handlers(run_status)
|
99
|
+
end
|
100
|
+
|
59
101
|
extend Forwardable
|
60
102
|
|
103
|
+
# The Chef::RunStatus object containing data about the Chef run.
|
61
104
|
attr_reader :run_status
|
62
105
|
|
63
106
|
##
|
@@ -56,7 +56,7 @@ class Chef
|
|
56
56
|
alias :start :run
|
57
57
|
|
58
58
|
def call_action_for_message(message)
|
59
|
-
amqp_payload = JSON.parse(message[:payload])
|
59
|
+
amqp_payload = JSON.parse(message[:payload], :create_additions => false, :max_nesting => false)
|
60
60
|
action = amqp_payload["action"].to_sym
|
61
61
|
app_payload = amqp_payload["payload"]
|
62
62
|
assert_method_whitelisted(action)
|
@@ -55,7 +55,7 @@ class Chef
|
|
55
55
|
with_metadata["type"] ||= self.index_object_type
|
56
56
|
with_metadata["id"] ||= self.index_id
|
57
57
|
with_metadata["database"] ||= Chef::Config[:couchdb_database]
|
58
|
-
with_metadata["item"] ||= self
|
58
|
+
with_metadata["item"] ||= self.to_hash
|
59
59
|
|
60
60
|
raise ArgumentError, "Type, Id, or Database missing in index operation: #{with_metadata.inspect}" if (with_metadata["id"].nil? or with_metadata["type"].nil?)
|
61
61
|
with_metadata
|
data/lib/chef/knife.rb
CHANGED
@@ -151,6 +151,18 @@ class Chef
|
|
151
151
|
subcommand_class || subcommand_not_found!(args)
|
152
152
|
end
|
153
153
|
|
154
|
+
protected
|
155
|
+
|
156
|
+
def load_late_dependency(dep, gem_name = nil)
|
157
|
+
begin
|
158
|
+
require dep
|
159
|
+
rescue LoadError
|
160
|
+
gem_name ||= dep.gsub('/', '-')
|
161
|
+
Chef::Log.fatal "#{gem_name} is not installed. run \"gem install #{gem_name}\" to install it."
|
162
|
+
exit 1
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
154
166
|
private
|
155
167
|
|
156
168
|
# :nodoc:
|
@@ -255,7 +267,6 @@ class Chef
|
|
255
267
|
Chef::Config[:node_name] = config[:node_name] if config[:node_name]
|
256
268
|
Chef::Config[:client_key] = config[:client_key] if config[:client_key]
|
257
269
|
Chef::Config[:chef_server_url] = config[:chef_server_url] if config[:chef_server_url]
|
258
|
-
Mixlib::Log::Formatter.show_time = false
|
259
270
|
Chef::Log.init(Chef::Config[:log_location])
|
260
271
|
Chef::Log.level(Chef::Config[:log_level])
|
261
272
|
|
@@ -407,10 +418,12 @@ class Chef
|
|
407
418
|
object = klass.load(name)
|
408
419
|
|
409
420
|
output = edit_data(object)
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
421
|
+
if output.to_s != object.to_s
|
422
|
+
output.save
|
423
|
+
self.msg("Saved #{output}")
|
424
|
+
else
|
425
|
+
self.msg("Object unchanged, not saving")
|
426
|
+
end
|
414
427
|
|
415
428
|
output(format_for_display(object)) if config[:print_after]
|
416
429
|
end
|