CID-444: persist stacks even in case of failures
This commit is contained in:
		
							parent
							
								
									48333a9097
								
							
						
					
					
						commit
						938616c489
					
				| @ -90,6 +90,8 @@ module Devops | |||||||
|       def sync! |       def sync! | ||||||
|         self.stack_status = provider_instance.stack_details(self)[:stack_status] |         self.stack_status = provider_instance.stack_details(self)[:stack_status] | ||||||
|         self.events = provider_instance.stack_events(self) |         self.events = provider_instance.stack_events(self) | ||||||
|  |       rescue Fog::AWS::CloudFormation::NotFound | ||||||
|  |         self.stack_status = 'NOT_FOUND' | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       def resources |       def resources | ||||||
|  | |||||||
| @ -10,12 +10,20 @@ RSpec.describe StackSynchronizer, stubbed_connector: true do | |||||||
|     allow(syncer).to receive(:sleep) |     allow(syncer).to receive(:sleep) | ||||||
|     allow(stubbed_connector).to receive(:stack_update) |     allow(stubbed_connector).to receive(:stack_update) | ||||||
| 
 | 
 | ||||||
|     lots_of_statuses = ['CREATE_IN_PROGRESS'] * 10 + ['CREATE_COMPLETE'] |     # lots_of_statuses = ['CREATE_IN_PROGRESS'] * 10 + ['CREATE_COMPLETE'] | ||||||
|     allow(stack).to receive(:stack_status).and_return(*lots_of_statuses) |     # allow(stack).to receive(:stack_status).and_return(*lots_of_statuses) | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   describe '#sync' do |   def setup_statuses(statuses_array) | ||||||
|  |     statuses = statuses_array.to_enum | ||||||
|  |     allow(stack).to receive(:sync!) { | ||||||
|  |       stack.stack_status = statuses.next | ||||||
|  |     } | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   describe '#sync', stubbed_logger: true do | ||||||
|     it 'waits for stack creating to be finished' do |     it 'waits for stack creating to be finished' do | ||||||
|  |       setup_statuses(['CREATE_IN_PROGRESS'] * 10 + ['CREATE_COMPLETE']) | ||||||
|       expect(syncer).to receive(:sleep).at_least(10).times |       expect(syncer).to receive(:sleep).at_least(10).times | ||||||
|       expect(stack).to receive(:sync!).at_least(10).times |       expect(stack).to receive(:sync!).at_least(10).times | ||||||
|       syncer.sync |       syncer.sync | ||||||
| @ -27,14 +35,23 @@ RSpec.describe StackSynchronizer, stubbed_connector: true do | |||||||
|       event3 = {'event_id' => 3, 'timestamp' => 't3'} |       event3 = {'event_id' => 3, 'timestamp' => 't3'} | ||||||
| 
 | 
 | ||||||
|       allow(stack).to receive(:events).and_return([event1], [event1, event2], [event1, event2, event3]) |       allow(stack).to receive(:events).and_return([event1], [event1, event2], [event1, event2, event3]) | ||||||
|  |       setup_statuses(['CREATE_IN_PROGRESS', 'CREATE_IN_PROGRESS', 'CREATE_IN_PROGRESS', 'CREATE_COMPLETE']) | ||||||
|       syncer.sync |       syncer.sync | ||||||
|       expect(out).to have_received(:puts).with(/t1/).once.ordered |       expect(out).to have_received(:puts).with(/t1/).once.ordered | ||||||
|       expect(out).to have_received(:puts).with(/t2/).once.ordered |       expect(out).to have_received(:puts).with(/t2/).once.ordered | ||||||
|       expect(out).to have_received(:puts).with(/t3/).once.ordered |       expect(out).to have_received(:puts).with(/t3/).once.ordered | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  |     it 'updates stack when status is changed' do | ||||||
|  |       setup_statuses(['CREATE_IN_PROGRESS', 'CREATE_IN_PROGRESS', 'ROLLBACK_IN_PROGRESS', 'ROLLBACK_COMPLETE']) | ||||||
|  | 
 | ||||||
|  |       expect(stubbed_connector).to receive(:stack_update).exactly(3).times | ||||||
|  |       syncer.sync | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|     context 'when stack creating was successful' do |     context 'when stack creating was successful' do | ||||||
|       it 'updates stack in DB when stack creating is finished and returns 0' do |       it 'updates stack in DB when stack creating is finished and returns 0' do | ||||||
|  |         setup_statuses(['CREATE_COMPLETE']) | ||||||
|         expect(stubbed_connector).to receive(:stack_update).with(stack) |         expect(stubbed_connector).to receive(:stack_update).with(stack) | ||||||
|         expect(syncer.sync).to eq 0 |         expect(syncer.sync).to eq 0 | ||||||
|       end |       end | ||||||
| @ -42,14 +59,15 @@ RSpec.describe StackSynchronizer, stubbed_connector: true do | |||||||
| 
 | 
 | ||||||
|     context 'when stack was rollbacked' do |     context 'when stack was rollbacked' do | ||||||
|       it 'returns 1 (:stack_rolled_back)' do |       it 'returns 1 (:stack_rolled_back)' do | ||||||
|         allow(stack).to receive(:stack_status).and_return('CREATE_IN_PROGRESS', 'ROLLBACK_IN_PROGRESS', 'ROLLBACK_COMPLETE') |         setup_statuses(['CREATE_IN_PROGRESS', 'ROLLBACK_IN_PROGRESS', 'ROLLBACK_COMPLETE']) | ||||||
|         expect(syncer.sync).to eq 1 |         expect(syncer.sync).to eq 1 | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     context 'when unkown stack status was found' do |     context 'when unkown stack status was found' do | ||||||
|       it 'returns 2 (:unkown_status)' do |       it 'returns 2 (:unkown_status)' do | ||||||
|         allow(stack).to receive(:stack_status).and_return('CREATE_IN_PROGRESS', 'unknown') |         setup_statuses(['CREATE_IN_PROGRESS', 'unknown']) | ||||||
|  | 
 | ||||||
|         expect(syncer.sync).to eq 2 |         expect(syncer.sync).to eq 2 | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
| @ -63,7 +81,7 @@ RSpec.describe StackSynchronizer, stubbed_connector: true do | |||||||
| 
 | 
 | ||||||
|     context 'when an error occured during syncing', stubbed_logger: true do |     context 'when an error occured during syncing', stubbed_logger: true do | ||||||
|       it 'returns 5 (:error)' do |       it 'returns 5 (:error)' do | ||||||
|         allow(stack).to receive(:stack_status).and_return('CREATE_IN_PROGRESS', 'CREATE_COMPLETE') |         setup_statuses(['CREATE_IN_PROGRESS', 'CREATE_COMPLETE']) | ||||||
|         allow(stubbed_connector).to receive(:stack_update) { raise } |         allow(stubbed_connector).to receive(:stack_update) { raise } | ||||||
|         expect(syncer.sync).to eq 5 |         expect(syncer.sync).to eq 5 | ||||||
|       end |       end | ||||||
|  | |||||||
| @ -17,18 +17,14 @@ class StackSynchronizer | |||||||
|       sleep sleep_time |       sleep sleep_time | ||||||
|       stack.sync! |       stack.sync! | ||||||
|       print_new_events |       print_new_events | ||||||
|  | 
 | ||||||
|  |       update_stack_status if stack_status_changed? | ||||||
|  | 
 | ||||||
|       case stack.stack_status |       case stack.stack_status | ||||||
|       when 'CREATE_IN_PROGRESS', 'ROLLBACK_IN_PROGRESS', 'DELETE_IN_PROGRESS' |       when 'CREATE_IN_PROGRESS', 'ROLLBACK_IN_PROGRESS', 'DELETE_IN_PROGRESS' | ||||||
|       when 'CREATE_COMPLETE' |       when 'CREATE_COMPLETE', 'ROLLBACK_COMPLETE', 'DELETE_COMPLETE', 'CREATE_FAILED', 'NOT_FOUND' | ||||||
|         ::Devops::Db.connector.stack_update(stack) |  | ||||||
|         puts_and_flush "Stack '#{stack.id}' status is now #{stack.stack_status}" |         puts_and_flush "Stack '#{stack.id}' status is now #{stack.stack_status}" | ||||||
|         return 0 |         return code_for_status(stack.stack_status) | ||||||
|       when 'ROLLBACK_COMPLETE' |  | ||||||
|         puts_and_flush "Stack '#{stack.id}' status is rolled back" |  | ||||||
|         return error_code(:stack_rolled_back) |  | ||||||
|       when 'DELETE_COMPLETE' |  | ||||||
|         puts_and_flush "Stack '#{stack.id}' status is deleted" |  | ||||||
|         return error_code(:stack_deleted) |  | ||||||
|       else |       else | ||||||
|         puts_and_flush "Unknown stack status: '#{stack.stack_status}'" |         puts_and_flush "Unknown stack status: '#{stack.stack_status}'" | ||||||
|         return error_code(:unkown_status) |         return error_code(:unkown_status) | ||||||
| @ -38,7 +34,7 @@ class StackSynchronizer | |||||||
|     error_code(:timeout) |     error_code(:timeout) | ||||||
|   rescue StandardError => e |   rescue StandardError => e | ||||||
|     DevopsLogger.logger.error e.message |     DevopsLogger.logger.error e.message | ||||||
|     puts_and_flush "Error: #{e.message}\n#{e.backtrace.join("\n")}" |     puts_and_flush "Error: #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}" | ||||||
|     error_code(:error) |     error_code(:error) | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
| @ -48,6 +44,24 @@ class StackSynchronizer | |||||||
| 
 | 
 | ||||||
|   private |   private | ||||||
| 
 | 
 | ||||||
|  |   def code_for_status(status) | ||||||
|  |     { | ||||||
|  |       'CREATE_COMPLETE' => 0, | ||||||
|  |       'ROLLBACK_COMPLETE' => error_code(:stack_rolled_back), | ||||||
|  |       'DELETE_COMPLETE' => error_code(:stack_deleted), | ||||||
|  |       'NOT_FOUND' => error_code(:stack_not_found) | ||||||
|  |     }.fetch(status) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def update_stack_status | ||||||
|  |     ::Devops::Db.connector.stack_update(stack) | ||||||
|  |     @last_status = stack.stack_status | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def stack_status_changed? | ||||||
|  |     @last_status != stack.stack_status | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   def error_code(reason) |   def error_code(reason) | ||||||
|     error_codes.fetch(reason) |     error_codes.fetch(reason) | ||||||
|   end |   end | ||||||
| @ -58,7 +72,8 @@ class StackSynchronizer | |||||||
|       unkown_status: 2, |       unkown_status: 2, | ||||||
|       timeout: 3, |       timeout: 3, | ||||||
|       error: 5, |       error: 5, | ||||||
|       stack_deleted: 6 |       stack_deleted: 6, | ||||||
|  |       stack_not_found: 7 | ||||||
|     } |     } | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Anton Chuchkalov
						Anton Chuchkalov