chef 11.10.4 → 11.12.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +6 -6
  3. data/README.md +1 -1
  4. data/lib/chef/api_client.rb +1 -3
  5. data/lib/chef/application.rb +2 -1
  6. data/lib/chef/application/client.rb +11 -1
  7. data/lib/chef/client.rb +24 -9
  8. data/lib/chef/cookbook/syntax_check.rb +107 -6
  9. data/lib/chef/dsl/reboot_pending.rb +61 -0
  10. data/lib/chef/exceptions.rb +12 -1
  11. data/lib/chef/formatters/error_descriptor.rb +1 -1
  12. data/lib/chef/http/remote_request_id.rb +46 -0
  13. data/lib/chef/knife/bootstrap.rb +1 -1
  14. data/lib/chef/knife/bootstrap/README.md +12 -0
  15. data/lib/chef/knife/bootstrap/chef-full.erb +3 -0
  16. data/lib/chef/knife/client_create.rb +6 -0
  17. data/lib/chef/knife/client_delete.rb +15 -1
  18. data/lib/chef/knife/raw.rb +1 -0
  19. data/lib/chef/node.rb +1 -1
  20. data/lib/chef/node/attribute_collections.rb +8 -1
  21. data/lib/chef/node/immutable_collections.rb +8 -1
  22. data/lib/chef/provider/deploy.rb +1 -1
  23. data/lib/chef/provider/group.rb +1 -1
  24. data/lib/chef/provider/ifconfig/debian.rb +19 -8
  25. data/lib/chef/provider/ohai.rb +6 -5
  26. data/lib/chef/provider/service/macosx.rb +68 -14
  27. data/lib/chef/recipe.rb +2 -0
  28. data/lib/chef/request_id.rb +37 -0
  29. data/lib/chef/resource.rb +2 -0
  30. data/lib/chef/resource_reporter.rb +7 -4
  31. data/lib/chef/rest.rb +5 -1
  32. data/lib/chef/run_status.rb +4 -1
  33. data/lib/chef/server_api.rb +3 -1
  34. data/lib/chef/version.rb +2 -2
  35. data/spec/functional/dsl/reboot_pending_spec.rb +118 -0
  36. data/spec/functional/resource/base.rb +1 -3
  37. data/spec/functional/resource/deploy_revision_spec.rb +192 -1
  38. data/spec/functional/resource/git_spec.rb +1 -1
  39. data/spec/functional/resource/ohai_spec.rb +65 -0
  40. data/spec/functional/resource/registry_spec.rb +4 -5
  41. data/spec/integration/client/client_spec.rb +14 -0
  42. data/spec/spec_helper.rb +1 -2
  43. data/spec/support/shared/functional/windows_script.rb +1 -2
  44. data/spec/unit/api_client_spec.rb +46 -0
  45. data/spec/unit/client_spec.rb +345 -229
  46. data/spec/unit/cookbook/syntax_check_spec.rb +0 -1
  47. data/spec/unit/dsl/reboot_pending_spec.rb +100 -0
  48. data/spec/unit/knife/client_create_spec.rb +29 -1
  49. data/spec/unit/knife/client_delete_spec.rb +44 -1
  50. data/spec/unit/knife_spec.rb +55 -0
  51. data/spec/unit/node/attribute_spec.rb +7 -0
  52. data/spec/unit/node/immutable_collections_spec.rb +5 -1
  53. data/spec/unit/provider/group_spec.rb +5 -0
  54. data/spec/unit/provider/ifconfig/debian_spec.rb +251 -24
  55. data/spec/unit/provider/ohai_spec.rb +2 -3
  56. data/spec/unit/provider/service/macosx_spec.rb +29 -11
  57. data/spec/unit/resource_reporter_spec.rb +1 -1
  58. data/spec/unit/rest_spec.rb +38 -13
  59. metadata +151 -194
@@ -21,6 +21,7 @@ require 'chef/mixin/params_validate'
21
21
  require 'chef/dsl/platform_introspection'
22
22
  require 'chef/dsl/data_query'
23
23
  require 'chef/dsl/registry_helper'
24
+ require 'chef/dsl/reboot_pending'
24
25
  require 'chef/mixin/convert_to_class_name'
25
26
  require 'chef/resource/conditional'
26
27
  require 'chef/resource/conditional_action_not_nothing'
@@ -125,6 +126,7 @@ F
125
126
  include Chef::Mixin::ParamsValidate
126
127
  include Chef::DSL::PlatformIntrospection
127
128
  include Chef::DSL::RegistryHelper
129
+ include Chef::DSL::RebootPending
128
130
  include Chef::Mixin::ConvertToClassName
129
131
  include Chef::Mixin::Deprecation
130
132
 
@@ -107,7 +107,6 @@ class Chef
107
107
  @pending_update = nil
108
108
  @status = "success"
109
109
  @exception = nil
110
- @run_id = SecureRandom.uuid
111
110
  @rest_client = rest_client
112
111
  @error_descriptions = {}
113
112
  end
@@ -118,7 +117,7 @@ class Chef
118
117
  if reporting_enabled?
119
118
  begin
120
119
  resource_history_url = "reports/nodes/#{node_name}/runs"
121
- server_response = @rest_client.post_rest(resource_history_url, {:action => :start, :run_id => @run_id,
120
+ server_response = @rest_client.post_rest(resource_history_url, {:action => :start, :run_id => run_id,
122
121
  :start_time => start_time.to_s}, headers)
123
122
  rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
124
123
  handle_error_starting_run(e, resource_history_url)
@@ -158,6 +157,10 @@ class Chef
158
157
  @reporting_enabled = false
159
158
  end
160
159
 
160
+ def run_id
161
+ @run_status.run_id
162
+ end
163
+
161
164
  def resource_current_state_loaded(new_resource, action, current_resource)
162
165
  unless nested_resource?(new_resource)
163
166
  @pending_update = ResourceReport.new_with_current_state(new_resource, action, current_resource)
@@ -214,8 +217,8 @@ class Chef
214
217
  def post_reporting_data
215
218
  if reporting_enabled?
216
219
  run_data = prepare_run_data
217
- resource_history_url = "reports/nodes/#{node_name}/runs/#{@run_id}"
218
- Chef::Log.info("Sending resource update report (run-id: #{@run_id})")
220
+ resource_history_url = "reports/nodes/#{node_name}/runs/#{run_id}"
221
+ Chef::Log.info("Sending resource update report (run-id: #{run_id})")
219
222
  Chef::Log.debug run_data.inspect
220
223
  compressed_data = encode_gzip(run_data.to_json)
221
224
  begin
@@ -36,6 +36,7 @@ require 'chef/http/validate_content_length'
36
36
  require 'chef/config'
37
37
  require 'chef/exceptions'
38
38
  require 'chef/platform/query_helpers'
39
+ require 'chef/http/remote_request_id'
39
40
 
40
41
  class Chef
41
42
  # == Chef::REST
@@ -62,6 +63,7 @@ class Chef
62
63
 
63
64
  @decompressor = Decompressor.new(options)
64
65
  @authenticator = Authenticator.new(options)
66
+ @request_id = RemoteRequestID.new(options)
65
67
 
66
68
  @middlewares << ValidateContentLength.new(options)
67
69
  @middlewares << JSONInput.new(options)
@@ -69,6 +71,8 @@ class Chef
69
71
  @middlewares << CookieManager.new(options)
70
72
  @middlewares << @decompressor
71
73
  @middlewares << @authenticator
74
+ @middlewares << @request_id
75
+
72
76
  end
73
77
 
74
78
  def signing_key_filename
@@ -132,7 +136,7 @@ class Chef
132
136
  def raw_http_request(method, path, headers, data)
133
137
  url = create_url(path)
134
138
  method, url, headers, data = @authenticator.handle_request(method, url, headers, data)
135
-
139
+ method, url, headers, data = @request_id.handle_request(method, url, headers, data)
136
140
  response, rest_request, return_value = send_http_request(method, url, headers, data)
137
141
  response.error! unless success_response?(response)
138
142
  return_value
@@ -37,6 +37,8 @@ class Chef::RunStatus
37
37
 
38
38
  attr_writer :exception
39
39
 
40
+ attr_accessor :run_id
41
+
40
42
  def initialize(node, events)
41
43
  @node = node
42
44
  @events = events
@@ -112,7 +114,8 @@ class Chef::RunStatus
112
114
  :all_resources => all_resources,
113
115
  :updated_resources => updated_resources,
114
116
  :exception => formatted_exception,
115
- :backtrace => backtrace}
117
+ :backtrace => backtrace,
118
+ :run_id => run_id}
116
119
  end
117
120
 
118
121
  # Returns a string of the format "ExceptionClass: message" or +nil+ if no
@@ -22,6 +22,7 @@ require 'chef/http/cookie_manager'
22
22
  require 'chef/http/decompressor'
23
23
  require 'chef/http/json_input'
24
24
  require 'chef/http/json_output'
25
+ require 'chef/http/remote_request_id'
25
26
 
26
27
  class Chef
27
28
  class ServerAPI < Chef::HTTP
@@ -37,5 +38,6 @@ class Chef
37
38
  use Chef::HTTP::CookieManager
38
39
  use Chef::HTTP::Decompressor
39
40
  use Chef::HTTP::Authenticator
41
+ use Chef::HTTP::RemoteRequestID
40
42
  end
41
- end
43
+ end
@@ -1,4 +1,4 @@
1
- #rc
1
+ #
2
2
  # Author:: Daniel DeLeo (<dan@opscode.com>)
3
3
  # Copyright:: Copyright (c) 2010-2011 Opscode, Inc.
4
4
  # License:: Apache License, Version 2.0
@@ -17,7 +17,7 @@
17
17
 
18
18
  class Chef
19
19
  CHEF_ROOT = File.dirname(File.expand_path(File.dirname(__FILE__)))
20
- VERSION = '11.10.4'
20
+ VERSION = '11.12.0.alpha.1'
21
21
  end
22
22
 
23
23
  # NOTE: the Chef::Version class is defined in version_class.rb
@@ -0,0 +1,118 @@
1
+ #
2
+ # Author:: Bryan McLellan <btm@loftninjas.org>
3
+ # Copyright:: Copyright (c) 2014 Chef Software, 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
+ require "chef/dsl/reboot_pending"
20
+ require "chef/win32/registry"
21
+ require "spec_helper"
22
+
23
+ describe Chef::DSL::RebootPending, :windows_only do
24
+ def run_ohai
25
+ ohai = Ohai::System.new
26
+ # Would be nice to limit this to platform/kernel/arch etc for Ohai 7
27
+ ohai.all_plugins
28
+ node.consume_external_attrs(ohai.data,{})
29
+
30
+ ohai
31
+ end
32
+
33
+ def registry_safe?
34
+ !registry.value_exists?('HKLM\SYSTEM\CurrentControlSet\Control\Session Manager', { :name => 'PendingFileRenameOperations' }) ||
35
+ !registry.key_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired') ||
36
+ !registry.key_exists?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootRequired') ||
37
+ !registry.key_exists?('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile')
38
+ end
39
+
40
+ let(:node) { Chef::Node.new }
41
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
42
+ let!(:ohai) { run_ohai } # Ensure we have necessary node data
43
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
44
+ let(:recipe) { Chef::Recipe.new("a windows cookbook", "the windows recipe", run_context) }
45
+ let(:registry) { Chef::Win32::Registry.new(run_context) }
46
+
47
+ describe "reboot_pending?" do
48
+
49
+ context "when there is nothing to indicate a reboot is pending" do
50
+ it { expect(recipe.reboot_pending?).to be_false }
51
+ end
52
+
53
+ describe 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations' do
54
+ it "returns true if the registry value exists" do
55
+ pending "Found existing registry keys" unless registry_safe?
56
+ registry.set_value('HKLM\SYSTEM\CurrentControlSet\Control\Session Manager',
57
+ { :name => 'PendingFileRenameOperations', :type => :multi_string, :data => ['\??\C:\foo.txt|\??\C:\bar.txt'] })
58
+
59
+ expect(recipe.reboot_pending?).to be_true
60
+ end
61
+
62
+ after do
63
+ if registry_safe?
64
+ registry.delete_value('HKLM\SYSTEM\CurrentControlSet\Control\Session Manager', { :name => 'PendingFileRenameOperations' })
65
+ end
66
+ end
67
+ end
68
+
69
+ describe 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired' do
70
+ it "returns true if the registry key exists" do
71
+ pending "Found existing registry keys" unless registry_safe?
72
+ registry.create_key('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired', false)
73
+
74
+ expect(recipe.reboot_pending?).to be_true
75
+ end
76
+
77
+ after do
78
+ if registry_safe?
79
+ registry.delete_key('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired', false)
80
+ end
81
+ end
82
+ end
83
+
84
+ describe 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootRequired' do
85
+ it "returns true if the registry key exists" do
86
+ pending "Permissions are limited to 'TrustedInstaller' by default"
87
+ pending "Found existing registry keys" unless registry_safe?
88
+ registry.create_key('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootRequired', false)
89
+
90
+ expect(recipe.reboot_pending?).to be_true
91
+ end
92
+
93
+ after do
94
+ if registry_safe?
95
+ registry.delete_key('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootRequired', false)
96
+ end
97
+ end
98
+ end
99
+
100
+ describe 'HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile\Flags' do
101
+ it "returns true if the registry key exists" do
102
+ pending "Found existing registry keys" unless registry_safe?
103
+ registry.create_key('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile', true)
104
+ registry.set_value('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile',
105
+ { :name => 'Flags', :type => :dword, :data => 3 })
106
+
107
+ expect(recipe.reboot_pending?).to be_true
108
+ end
109
+
110
+ after do
111
+ if registry_safe?
112
+ registry.delete_value('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile', { :name => 'Flags' })
113
+ registry.delete_key('HKLM\SOFTWARE\Microsoft\Updates\UpdateExeVolatile', false)
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -22,9 +22,7 @@ def ohai
22
22
  # provider is platform-dependent, we need platform ohai data:
23
23
  @OHAI_SYSTEM ||= begin
24
24
  ohai = Ohai::System.new
25
- ohai.require_plugin("os")
26
- ohai.require_plugin("platform")
27
- ohai.require_plugin("passwd")
25
+ ohai.all_plugins("platform")
28
26
  ohai
29
27
  end
30
28
  end
@@ -45,7 +45,7 @@ describe Chef::Resource::DeployRevision, :unix_only => true do
45
45
 
46
46
  before(:all) do
47
47
  @ohai = Ohai::System.new
48
- @ohai.require_plugin("os")
48
+ @ohai.all_plugins("os")
49
49
  end
50
50
 
51
51
  let(:node) do
@@ -78,6 +78,9 @@ describe Chef::Resource::DeployRevision, :unix_only => true do
78
78
  # This is the third version
79
79
  let(:previous_rev) { "6d19a6dbecc8e37f5b2277345885c0c783eb8fb1" }
80
80
 
81
+ # This is the second version
82
+ let(:second_rev) { "0827e1b0e5043608ac0a824da5c558e252154ad0" }
83
+
81
84
  # This is the sixth version, it is on the "with-deploy-scripts" branch
82
85
  let(:rev_with_in_repo_callbacks) { "2404d015882659754bdb93ad6e4b4d3d02691a82" }
83
86
 
@@ -100,6 +103,7 @@ describe Chef::Resource::DeployRevision, :unix_only => true do
100
103
 
101
104
  let(:basic_deploy_resource) do
102
105
  Chef::Resource::DeployRevision.new(deploy_directory, run_context).tap do |r|
106
+ r.name "deploy-revision-unit-test"
103
107
  r.repo git_bundle_repo
104
108
  r.symlink_before_migrate({})
105
109
  r.symlinks({})
@@ -127,6 +131,34 @@ describe Chef::Resource::DeployRevision, :unix_only => true do
127
131
  end
128
132
  end
129
133
 
134
+ let(:deploy_to_previous_rev_again) do
135
+ basic_deploy_resource.dup.tap do |r|
136
+ r.revision(previous_rev)
137
+ r.restart_command shell_restart_command(:deploy_to_previous_rev_again)
138
+ end
139
+ end
140
+
141
+ let(:deploy_to_second_rev) do
142
+ basic_deploy_resource.dup.tap do |r|
143
+ r.revision(second_rev)
144
+ r.restart_command shell_restart_command(:deploy_to_second_rev)
145
+ end
146
+ end
147
+
148
+ let(:deploy_to_second_rev_again) do
149
+ basic_deploy_resource.dup.tap do |r|
150
+ r.revision(second_rev)
151
+ r.restart_command shell_restart_command(:deploy_to_second_rev_again)
152
+ end
153
+ end
154
+
155
+ let(:deploy_to_second_rev_again_again) do
156
+ basic_deploy_resource.dup.tap do |r|
157
+ r.revision(second_rev)
158
+ r.restart_command shell_restart_command(:deploy_to_second_rev_again_again)
159
+ end
160
+ end
161
+
130
162
  # Computes the full path for +path+ relative to the deploy directory
131
163
  def rel_path(path)
132
164
  File.expand_path(path, deploy_directory)
@@ -306,6 +338,165 @@ describe Chef::Resource::DeployRevision, :unix_only => true do
306
338
  end
307
339
  end
308
340
 
341
+ describe "back to a previously deployed revision where resource rev == latest revision (explicit rollback)" do
342
+ before do
343
+ deploy_to_previous_rev.run_action(:deploy)
344
+ @previous_rev_all_releases = deploy_to_previous_rev.provider_for_action(:deploy).all_releases
345
+ deploy_to_latest_rev.run_action(:deploy)
346
+ @latest_rev_all_releases = deploy_to_latest_rev.provider_for_action(:deploy).all_releases
347
+ deploy_to_latest_rev_again.run_action(:rollback)
348
+ @previous_rev_again_all_releases = deploy_to_latest_rev_again.provider_for_action(:deploy).all_releases
349
+ end
350
+
351
+ the_app_is_deployed_at_revision(:previous_rev)
352
+
353
+ it "restarts the application after rolling back" do
354
+ actual_operations_order.should == %w[deploy_to_previous_rev deploy_to_latest_rev deploy_to_latest_rev_again]
355
+ end
356
+
357
+ it "is marked updated" do
358
+ deploy_to_latest_rev_again.should be_updated_by_last_action
359
+ end
360
+
361
+ it "deploys the right code" do
362
+ IO.read(rel_path("current/app/app.rb")).should include("this is the third version of the app")
363
+ end
364
+
365
+ it "all_releases after first deploy should have one entry" do
366
+ @previous_rev_all_releases.length.should == 1
367
+ end
368
+
369
+ it "all_releases after second deploy should have two entries" do
370
+ @latest_rev_all_releases.length.should == 2
371
+ end
372
+
373
+ it "all_releases after rollback should have one entry" do
374
+ @previous_rev_again_all_releases.length.should == 1
375
+ end
376
+
377
+ it "all_releases after rollback should be the same as after the first deploy" do
378
+ @previous_rev_again_all_releases.should == @previous_rev_all_releases
379
+ end
380
+
381
+ end
382
+
383
+ describe "back to a previously deployed revision where resource rev == previous revision (explicit rollback)" do
384
+ before do
385
+ deploy_to_previous_rev.run_action(:deploy)
386
+ @previous_rev_all_releases = deploy_to_previous_rev.provider_for_action(:deploy).all_releases
387
+ deploy_to_latest_rev.run_action(:deploy)
388
+ @latest_rev_all_releases = deploy_to_latest_rev.provider_for_action(:deploy).all_releases
389
+ deploy_to_previous_rev_again.run_action(:rollback)
390
+ # FIXME: only difference with previous test is using latest_rev_again insetad of previous_rev_again
391
+ @previous_rev_again_all_releases = deploy_to_latest_rev_again.provider_for_action(:deploy).all_releases
392
+ end
393
+
394
+ the_app_is_deployed_at_revision(:previous_rev)
395
+
396
+ it "restarts the application after rolling back" do
397
+ actual_operations_order.should == %w[deploy_to_previous_rev deploy_to_latest_rev deploy_to_previous_rev_again]
398
+ end
399
+
400
+ it "is marked updated" do
401
+ deploy_to_previous_rev_again.should be_updated_by_last_action
402
+ end
403
+
404
+ it "deploys the right code" do
405
+ IO.read(rel_path("current/app/app.rb")).should include("this is the third version of the app")
406
+ end
407
+
408
+ it "all_releases after first deploy should have one entry" do
409
+ @previous_rev_all_releases.length.should == 1
410
+ end
411
+
412
+ it "all_releases after second deploy should have two entries" do
413
+ @latest_rev_all_releases.length.should == 2
414
+ end
415
+
416
+ it "all_releases after rollback should have one entry" do
417
+ @previous_rev_again_all_releases.length.should == 1
418
+ end
419
+
420
+ it "all_releases after rollback should be the same as after the first deploy" do
421
+ @previous_rev_again_all_releases.should == @previous_rev_all_releases
422
+ end
423
+ end
424
+
425
+ describe "back to a previously deployed revision where resource rev == latest revision (explicit rollback)" do
426
+ before do
427
+ deploy_to_second_rev.run_action(:deploy)
428
+ @first_deploy_all_releases = deploy_to_second_rev.provider_for_action(:deploy).all_releases
429
+ deploy_to_previous_rev.run_action(:deploy)
430
+ @second_deploy_all_releases = deploy_to_previous_rev.provider_for_action(:deploy).all_releases
431
+ deploy_to_previous_rev_again.run_action(:rollback)
432
+ @third_deploy_all_releases = deploy_to_previous_rev_again.provider_for_action(:deploy).all_releases
433
+ deploy_to_latest_rev.run_action(:deploy)
434
+ @fourth_deploy_all_releases = deploy_to_latest_rev.provider_for_action(:deploy).all_releases
435
+ deploy_to_latest_rev_again.run_action(:rollback)
436
+ @fifth_deploy_all_releases = deploy_to_latest_rev_again.provider_for_action(:deploy).all_releases
437
+ end
438
+
439
+ the_app_is_deployed_at_revision(:second_rev)
440
+
441
+ it "restarts the application after rolling back" do
442
+ actual_operations_order.should == %w[deploy_to_second_rev deploy_to_previous_rev deploy_to_previous_rev_again deploy_to_latest_rev deploy_to_latest_rev_again]
443
+ end
444
+
445
+ it "is marked updated" do
446
+ deploy_to_latest_rev_again.should be_updated_by_last_action
447
+ end
448
+
449
+ it "deploys the right code" do
450
+ IO.read(rel_path("current/app/app.rb")).should include("this is the second version of the app")
451
+ end
452
+
453
+ it "all_releases after rollback should have one entry" do
454
+ @fifth_deploy_all_releases.length.should == 1
455
+ end
456
+
457
+ it "all_releases after rollback should be the same as after the first deploy" do
458
+ @fifth_deploy_all_releases.should == @first_deploy_all_releases
459
+ end
460
+ end
461
+
462
+ describe "back to a previously deployed revision where resource rev == latest revision (explicit rollback)" do
463
+ before do
464
+ deploy_to_second_rev.run_action(:deploy)
465
+ @first_deploy_all_releases = deploy_to_second_rev.provider_for_action(:deploy).all_releases
466
+ deploy_to_previous_rev.run_action(:deploy)
467
+ @second_deploy_all_releases = deploy_to_previous_rev.provider_for_action(:deploy).all_releases
468
+ deploy_to_second_rev_again.run_action(:rollback)
469
+ @third_deploy_all_releases = deploy_to_second_rev_again.provider_for_action(:deploy).all_releases
470
+ deploy_to_latest_rev.run_action(:deploy)
471
+ @fourth_deploy_all_releases = deploy_to_latest_rev.provider_for_action(:deploy).all_releases
472
+ deploy_to_second_rev_again_again.run_action(:rollback)
473
+ @fifth_deploy_all_releases = deploy_to_second_rev_again_again.provider_for_action(:deploy).all_releases
474
+ end
475
+
476
+ the_app_is_deployed_at_revision(:second_rev)
477
+
478
+ it "restarts the application after rolling back" do
479
+ actual_operations_order.should == %w[deploy_to_second_rev deploy_to_previous_rev deploy_to_second_rev_again deploy_to_latest_rev deploy_to_second_rev_again_again]
480
+ end
481
+
482
+ it "is marked updated" do
483
+ deploy_to_second_rev_again_again.should be_updated_by_last_action
484
+ end
485
+
486
+ it "deploys the right code" do
487
+ IO.read(rel_path("current/app/app.rb")).should include("this is the second version of the app")
488
+ end
489
+
490
+ it "all_releases after rollback should have one entry" do
491
+ @fifth_deploy_all_releases.length.should == 1
492
+ end
493
+
494
+ it "all_releases after rollback should be the same as after the first deploy" do
495
+ @fifth_deploy_all_releases.should == @first_deploy_all_releases
496
+ end
497
+
498
+ end
499
+
309
500
  # CHEF-3435
310
501
  describe "to a deploy_to path that does not yet exist" do
311
502