chef 0.9.0.rc01 → 0.9.0.rc02

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.

@@ -252,6 +252,10 @@ Cookbooks are the fundamental unit of distribution in Chef. They encapsulate all
252
252
  .P
253
253
  \fBcookbook bulk delete REGEX\fR \fI(options)\fR
254
254
  .
255
+ .TP
256
+ \fB\-p\fR, \fB\-\-purge\fR
257
+ Purge files from backing store. This will disable any cookbook that contains any of the same files as the cookbook being purged.
258
+ .
255
259
  .P
256
260
  Delete cookbooks on the Chef Server based on a regular expression. The regular expression (\fIREGEX\fR) should be in quotes, not in //'s.
257
261
  .
@@ -262,6 +266,10 @@ Delete cookbooks on the Chef Server based on a regular expression. The regular e
262
266
  \fB\-a\fR, \fB\-\-all\fR
263
267
  Delete all versions
264
268
  .
269
+ .TP
270
+ \fB\-p\fR, \fB\-\-purge\fR
271
+ Purge files from backing store. This will disable any cookbook that contains any of the same files as the cookbook being purged.
272
+ .
265
273
  .P
266
274
  Delete the specified \fIVERSION\fR of the named \fICOOKBOOK\fR. If no version is specified, and only one version exists on the server, that version will be deleted. If multiple versions are available on the server, you will be prompted for a version to delete.
267
275
  .
@@ -161,6 +161,9 @@ Cookbooks are the fundamental unit of distribution in Chef. They encapsulate all
161
161
 
162
162
  __cookbook bulk delete REGEX__ _(options)_
163
163
 
164
+ * `-p`, `--purge`:
165
+ Purge files from backing store. This will disable any cookbook that contains any of the same files as the cookbook being purged.
166
+
164
167
  Delete cookbooks on the Chef Server based on a regular expression. The regular expression (_REGEX_) should be in quotes, not in //'s.
165
168
 
166
169
  __cookbook delete COOKBOOK [VERSION]__ _(options)_
@@ -168,6 +171,9 @@ __cookbook delete COOKBOOK [VERSION]__ _(options)_
168
171
  * `-a`, `--all`:
169
172
  Delete all versions
170
173
 
174
+ * `-p`, `--purge`:
175
+ Purge files from backing store. This will disable any cookbook that contains any of the same files as the cookbook being purged.
176
+
171
177
  Delete the specified _VERSION_ of the named _COOKBOOK_. If no version is specified, and only one version exists on the server, that version will be deleted. If multiple versions are available on the server, you will be prompted for a version to delete.
172
178
 
173
179
  __cookbook download COOKBOOK [VERSION]__ _(options)_
@@ -30,6 +30,7 @@ require 'chef/daemon'
30
30
  require 'chef/webui_user'
31
31
  require 'chef/openid_registration'
32
32
 
33
+ require 'chef/run_status'
33
34
  require 'chef/handler'
34
35
  require 'chef/handler/json_file'
35
36
 
@@ -74,12 +74,14 @@ class Chef
74
74
  build_node
75
75
 
76
76
  begin
77
- start_time = Time.now
77
+ run_status = Chef::RunStatus.new(node)
78
+ run_status.start_clock
78
79
  Chef::Log.info("Starting Chef Run")
79
80
 
80
81
  if Chef::Config[:solo]
81
82
  Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) }
82
83
  run_context = Chef::RunContext.new(node, Chef::CookbookCollection.new(Chef::CookbookLoader.new))
84
+ run_status.run_context = run_context
83
85
  assert_cookbook_path_not_empty(run_context)
84
86
  converge(run_context)
85
87
  else
@@ -98,7 +100,8 @@ class Chef
98
100
  Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::RemoteFileVendor.new(manifest, rest, valid_cache_entries) }
99
101
  cookbook_hash = sync_cookbooks(valid_cache_entries)
100
102
  run_context = Chef::RunContext.new(node, Chef::CookbookCollection.new(cookbook_hash))
101
-
103
+ run_status.run_context = run_context
104
+
102
105
  assert_cookbook_path_not_empty(run_context)
103
106
  save_node
104
107
 
@@ -108,39 +111,35 @@ class Chef
108
111
  cleanup_file_cache(valid_cache_entries)
109
112
  end
110
113
 
111
- end_time = Time.now
112
- elapsed_time = end_time - start_time
113
- Chef::Log.info("Chef Run complete in #{elapsed_time} seconds")
114
- run_report_handlers(start_time, end_time, elapsed_time)
114
+ run_status.stop_clock
115
+ Chef::Log.info("Chef Run complete in #{run_status.elapsed_time} seconds")
116
+ run_report_handlers(run_status)
115
117
  true
116
118
  rescue Exception => e
117
- run_exception_handlers(node, runner ? runner : run_context, start_time, end_time, elapsed_time, e)
119
+ run_status.stop_clock
120
+ run_status.exception = e
121
+ run_exception_handlers(run_status)
118
122
  Chef::Log.error("Re-raising exception: #{e.class} - #{e.message}\n#{e.backtrace.join("\n ")}")
119
123
  raise
124
+ ensure
125
+ run_status = nil
120
126
  end
121
127
  end
122
128
 
123
- def run_report_handlers(start_time, end_time, elapsed_time)
124
- if Chef::Config[:report_handlers].length > 0
125
- Chef::Log.info("Running report handlers")
126
- Chef::Config[:report_handlers].each do |handler|
127
- handler.report(node, runner, start_time, end_time, elapsed_time)
128
- end
129
- Chef::Log.info("Report handlers complete")
129
+ def run_report_handlers(run_status)
130
+ Chef::Log.info("Running report handlers")
131
+ Array(Chef::Config[:report_handlers]).each do |handler|
132
+ handler.run_report_safely(handler)
130
133
  end
134
+ Chef::Log.info("Report handlers complete")
131
135
  end
132
136
 
133
- def run_exception_handlers(node, runner, start_time, end_time, elapsed_time, exception)
134
- if Chef::Config[:exception_handlers].length > 0
135
- end_time ||= Time.now
136
- elapsed_time ||= end_time - start_time
137
- Chef::Log.error("Received exception: #{exception.message}")
138
- Chef::Log.error("Running exception handlers")
139
- Chef::Config[:exception_handlers].each do |handler|
140
- handler.report(node, runner, start_time, end_time, elapsed_time, exception)
141
- end
142
- Chef::Log.error("Exception handlers complete")
137
+ def run_exception_handlers(run_status)
138
+ Chef::Log.error("Running exception handlers")
139
+ Array(Chef::Config[:exception_handlers]).each do |handler|
140
+ handler.run_report_safely(run_status)
143
141
  end
142
+ Chef::Log.error("Exception handlers complete")
144
143
  end
145
144
 
146
145
  def run_ohai
@@ -331,7 +330,7 @@ class Chef
331
330
  # true:: Always returns true
332
331
  def converge(run_context)
333
332
  Chef::Log.debug("Converging node #{node_name}")
334
- self.runner = Chef::Runner.new(run_context)
333
+ @runner = Chef::Runner.new(run_context)
335
334
  runner.converge
336
335
  true
337
336
  end
@@ -160,9 +160,11 @@ class Chef
160
160
  end
161
161
  response = @rest.delete_rest("#{couchdb_database}/#{uuid}?rev=#{rev}")
162
162
  response.couchdb = self if response.respond_to?(:couchdb=)
163
- Chef::Log.info("Sending #{obj_type}(#{uuid}) to the index queue for deletion..")
164
163
 
165
- object.delete_from_index(:database => couchdb_database, :id => uuid, :type => obj_type)
164
+ if object.respond_to?(:delete_from_index)
165
+ Chef::Log.info("Sending #{obj_type}(#{uuid}) to the index queue for deletion..")
166
+ object.delete_from_index(:database => couchdb_database, :id => uuid, :type => obj_type)
167
+ end
166
168
 
167
169
  response
168
170
  end
@@ -15,47 +15,106 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
  #
18
+ require 'forwardable'
18
19
 
19
20
  class Chef
20
21
  class Handler
21
22
 
22
- attr_accessor :config
23
+ extend Forwardable
23
24
 
24
- def initialize(config={})
25
- @config = config
26
- @config[:path] ||= "/var/chef/reports"
27
- @config
25
+ attr_reader :run_status
26
+
27
+ ##
28
+ # :method: start_time
29
+ #
30
+ # The time the chef run started
31
+ def_delegator :@run_status, :start_time
32
+
33
+ ##
34
+ # :method: end_time
35
+ #
36
+ # The time the chef run ended
37
+ def_delegator :@run_status, :end_time
38
+
39
+ ##
40
+ # :method: run_context
41
+ #
42
+ # The Chef::RunContext object used by the chef run
43
+ def_delegator :@run_status, :run_context
44
+
45
+ ##
46
+ # :method: exception
47
+ #
48
+ # The uncaught Exception that terminated the chef run, or nil if the run
49
+ # completed successfully
50
+ def_delegator :@run_status, :exception
51
+
52
+ ##
53
+ # :method: backtrace
54
+ #
55
+ # The backtrace captured by the uncaught exception that terminated the chef
56
+ # run, or nil if the run completed successfully
57
+ def_delegator :@run_status, :backtrace
58
+
59
+ ##
60
+ # :method: node
61
+ #
62
+ # The Chef::Node for this client run
63
+ def_delegator :@run_status, :node
64
+
65
+ ##
66
+ # :method: all_resources
67
+ #
68
+ # An Array containing all resources in the chef run's resource_collection
69
+ def_delegator :@run_status, :all_resources
70
+
71
+ ##
72
+ # :method: updated_resources
73
+ #
74
+ # An Array containing all resources that were updated during the chef run
75
+ def_delegator :@run_status, :updated_resources
76
+
77
+ ##
78
+ # :method: success?
79
+ #
80
+ # Was the chef run successful? True if the chef run did not raise an
81
+ # uncaught exception
82
+ def_delegator :@run_status, :success?
83
+
84
+ ##
85
+ # :method: failed?
86
+ #
87
+ # Did the chef run fail? True if the chef run raised an uncaught exception
88
+ def_delegator :@run_status, :failed?
89
+
90
+ # The main entry point for report handling. Subclasses should override this
91
+ # method with their own report handling logic.
92
+ def report
93
+ end
94
+
95
+ # Runs the report handler, rescuing and logging any errors it may cause.
96
+ # This ensures that all handlers get a chance to run even if one fails.
97
+ # This method should not be overridden by subclasses unless you know what
98
+ # you're doing.
99
+ def run_report_safely(run_status)
100
+ run_report_unsafe(run_status)
101
+ rescue Exception => e
102
+ Chef::Log.error("Report handler #{self.class.name} raised #{e.inspect}")
103
+ Array(e.backtrace).each { |line| Chef::Log.error(line) }
104
+ ensure
105
+ @run_status = nil
28
106
  end
29
107
 
30
- def build_report_data(node, runner, start_time, end_time, elapsed_time, exception=nil)
31
- data = Hash.new
32
- data[:node] = node if node
33
- if runner
34
- data[:resources] = {
35
- :all => runner.run_context.resource_collection.all_resources,
36
- :updated => runner.run_context.resource_collection.inject([]) { |m, r| m << r if r.updated; m }
37
- }
38
- end
39
- if exception
40
- data[:success] = false
41
- data[:exception] = {
42
- :message => exception.message,
43
- :backtrace => exception.backtrace
44
- }
45
- else
46
- data[:success] = true
47
- end
48
- data[:elapsed_time] = elapsed_time
49
- data[:start_time] = start_time
50
- data[:end_time] = end_time
51
- data
108
+ # Runs the report handler without any error handling. This method should
109
+ # not be used directly except in testing.
110
+ def run_report_unsafe(run_status)
111
+ @run_status = run_status
112
+ report
52
113
  end
53
114
 
54
- def build_report_dir
55
- unless File.exists?(config[:path])
56
- FileUtils.mkdir_p(config[:path])
57
- File.chmod(octal_mode("0700"), config[:path])
58
- end
115
+ # Return the Hash representation of the run_status
116
+ def data
117
+ @run_status.to_hash
59
118
  end
60
119
 
61
120
  end
@@ -23,18 +23,21 @@ class Chef
23
23
  class Handler
24
24
  class JsonFile < ::Chef::Handler
25
25
 
26
+ attr_reader :config
27
+
26
28
  def initialize(config={})
27
- super(config)
29
+ @config = config
30
+ @config[:path] ||= "/var/chef/reports"
31
+ @config
28
32
  end
29
33
 
30
- def report(node, runner, start_time, end_time, elapsed_time, exception)
34
+ def report
31
35
  if exception
32
36
  Chef::Log.error("Creating JSON exception report")
33
37
  else
34
38
  Chef::Log.info("Creating JSON run report")
35
39
  end
36
40
 
37
- data = build_report_data(node, runner, start_time, end_time, elapsed_time, exception)
38
41
  build_report_dir
39
42
  savetime = Time.now.strftime("%Y%m%d%H%M%S")
40
43
  File.open(File.join(config[:path], "chef-run-report-#{savetime}.json"), "w") do |file|
@@ -42,6 +45,14 @@ class Chef
42
45
  end
43
46
  end
44
47
 
48
+ def build_report_dir
49
+ unless File.exists?(config[:path])
50
+ FileUtils.mkdir_p(config[:path])
51
+ File.chmod(00700, config[:path])
52
+ end
53
+ end
54
+
55
+
45
56
  end
46
57
  end
47
58
  end
@@ -24,6 +24,8 @@ class Chef
24
24
  class Knife
25
25
  class CookbookBulkDelete < Knife
26
26
 
27
+ option :purge, :short => '-p', :long => '--purge', :boolean => true, :description => 'Permanently remove files from backing data store'
28
+
27
29
  banner "Sub-Command: cookbook bulk delete REGEX (options)"
28
30
 
29
31
  def run
@@ -41,10 +43,12 @@ class Chef
41
43
 
42
44
  confirm("Do you really want to delete these cookbooks? All versions will be deleted. (Y/N) ", false)
43
45
 
46
+ confirm("Files that are common to multiple cookbooks are shared, so purging the files may disable other cookbooks. Are you sure you want to purge files instead of just deleting the cookbooks") if config[:purge]
47
+
44
48
  cookbooks_names.each do |cookbook_name|
45
49
  versions = rest.get_rest("cookbooks/#{cookbook_name}").values.flatten
46
50
  versions.each do |version|
47
- object = rest.delete_rest("cookbooks/#{cookbook_name}/#{version}")
51
+ object = rest.delete_rest("cookbooks/#{cookbook_name}/#{version}#{config[:purge] ? "?purge=true" : ""}")
48
52
  Chef::Log.info("Deleted cookbook #{cookbook_name.ljust(25)} [#{version}]")
49
53
  end
50
54
  end
@@ -52,10 +56,3 @@ class Chef
52
56
  end
53
57
  end
54
58
  end
55
-
56
-
57
-
58
-
59
-
60
-
61
-
@@ -24,9 +24,12 @@ class Chef
24
24
 
25
25
  option :all, :short => '-a', :long => '--all', :boolean => true, :description => 'delete all versions'
26
26
 
27
+ option :purge, :short => '-p', :long => '--purge', :boolean => true, :description => 'Permanently remove files from backing data store'
28
+
27
29
  banner "Sub-Command: cookbook delete COOKBOOK VERSION (options)"
28
30
 
29
31
  def run
32
+ confirm("Files that are common to multiple cookbooks are shared, so purging the files may disable other cookbooks. Are you sure you want to purge files instead of just deleting the cookbook") if config[:purge]
30
33
  @cookbook_name, @version = name_args
31
34
  if @cookbook_name && @version
32
35
  delete_explicit_version
@@ -43,7 +46,7 @@ class Chef
43
46
 
44
47
  def delete_explicit_version
45
48
  delete_object(Chef::CookbookVersion, "#{@cookbook_name} version #{@version}", "cookbook") do
46
- rest.delete_rest("cookbooks/#{@cookbook_name}/#{@version}")
49
+ delete_request("cookbooks/#{@cookbook_name}/#{@version}", config[:purge])
47
50
  end
48
51
  end
49
52
 
@@ -112,7 +115,7 @@ class Chef
112
115
  end
113
116
 
114
117
  def delete_version_without_confirmation(version)
115
- object = rest.delete_rest("cookbooks/#{@cookbook_name}/#{version}")
118
+ object = delete_request("cookbooks/#{@cookbook_name}/#{version}", config[:purge])
116
119
  output(format_for_display(object)) if config[:print_after]
117
120
  Chef::Log.info("Deleted cookbook[#{@cookbook_name}][#{version}]")
118
121
  end
@@ -127,6 +130,13 @@ class Chef
127
130
  end
128
131
  end
129
132
  end
133
+
134
+ private
135
+
136
+ def delete_request(path, purge)
137
+ url = "cookbooks/#{@cookbook_name}/#{@version}#{purge ? "?purge=true" : ""}"
138
+ rest.delete_rest(url)
139
+ end
130
140
 
131
141
  end
132
142
  end
@@ -0,0 +1,94 @@
1
+ #
2
+ # Author:: Daniel DeLeo (<dan@opscode.com>)
3
+ # Copyright:: Copyright (c) 2010 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
+
19
+ class Chef::RunStatus
20
+
21
+ attr_reader :run_context
22
+
23
+ attr_writer :run_context
24
+
25
+ attr_reader :start_time
26
+
27
+ attr_reader :end_time
28
+
29
+ attr_reader :exception
30
+
31
+ attr_writer :exception
32
+
33
+ def initialize(node)
34
+ @node = node
35
+ end
36
+
37
+ def node
38
+ @node
39
+ end
40
+
41
+ def start_clock
42
+ @start_time = Time.now
43
+ end
44
+
45
+ def stop_clock
46
+ @end_time = Time.now
47
+ end
48
+
49
+ def elapsed_time
50
+ if @start_time && @end_time
51
+ @end_time - @start_time
52
+ else
53
+ nil
54
+ end
55
+ end
56
+
57
+ def all_resources
58
+ @run_context && @run_context.resource_collection.all_resources
59
+ end
60
+
61
+ def updated_resources
62
+ @run_context && @run_context.resource_collection.select { |r| r.updated }
63
+ end
64
+
65
+ def backtrace
66
+ @exception && @exception.backtrace
67
+ end
68
+
69
+ def failed?
70
+ !success?
71
+ end
72
+
73
+ def success?
74
+ @exception.nil?
75
+ end
76
+
77
+ def to_hash
78
+ # use a flat hash here so we can't errors from intermediate values being nil
79
+ { :node => node,
80
+ :success => success?,
81
+ :start_time => start_time,
82
+ :end_time => end_time,
83
+ :elapsed_time => elapsed_time,
84
+ :all_resources => all_resources,
85
+ :updated_resources => updated_resources,
86
+ :exception => formatted_exception,
87
+ :backtrace => backtrace}
88
+ end
89
+
90
+ def formatted_exception
91
+ @exception && "#{@exception.class.name}: #{@exception.message}"
92
+ end
93
+
94
+ end
@@ -16,5 +16,5 @@
16
16
  # limitations under the License.
17
17
 
18
18
  class Chef
19
- VERSION = '0.9.0.rc01'
19
+ VERSION = '0.9.0.rc02'
20
20
  end
metadata CHANGED
@@ -6,8 +6,8 @@ version: !ruby/object:Gem::Version
6
6
  - 0
7
7
  - 9
8
8
  - 0
9
- - rc01
10
- version: 0.9.0.rc01
9
+ - rc02
10
+ version: 0.9.0.rc02
11
11
  platform: ruby
12
12
  authors:
13
13
  - Adam Jacob
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-15 00:00:00 -07:00
18
+ date: 2010-06-16 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -509,6 +509,7 @@ files:
509
509
  - lib/chef/run_list/run_list_expansion.rb
510
510
  - lib/chef/run_list/run_list_item.rb
511
511
  - lib/chef/run_list.rb
512
+ - lib/chef/run_status.rb
512
513
  - lib/chef/runner.rb
513
514
  - lib/chef/sandbox.rb
514
515
  - lib/chef/search/query.rb