chef 0.9.8 → 0.9.10.rc.0
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.
- 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
|