class StackSynchronizer include PutsAndFlush attr_reader :out, :stack def initialize(stack, out) @stack, @out = stack, out @printed_events = [] end def sync puts_and_flush "Syncing stack '#{stack.id}'..." # 5 tries each 5 seconds, then 200 tries each 10 seconds sleep_times = [5]*5 + [10]*400 sleep_times.each do |sleep_time| sleep sleep_time stack.sync_details! print_new_events case stack.stack_status when 'CREATE_IN_PROGRESS', 'ROLLBACK_IN_PROGRESS' when 'CREATE_COMPLETE' ::Devops::Db.connector.stack_update(stack) puts_and_flush "Stack '#{stack.id}' status is now #{stack.stack_status}" return 0 when 'ROLLBACK_COMPLETE' puts_and_flush "Stack '#{stack.id}' status is rolled back" return error_code(:stack_rolled_back) else puts_and_flush "Unknown stack status: '#{stack.stack_status}'" return error_code(:unkown_status) end end puts_and_flush "Stack hasn't been synced in #{sleep_times.inject(&:+)} seconds." error_code(:timeout) rescue StandardError => e DevopsLogger.logger.error e.message puts_and_flush "Error: #{e.message}\n#{e.backtrace.join("\n")}" error_code(:error) end def reason_from_error_code(code) error_codes.key(code) end private def error_code(reason) error_codes.fetch(reason) end def error_codes { stack_rolled_back: 1, unkown_status: 2, timeout: 3, error: 5 } end def print_new_events stack.events.each do |event| unless @printed_events.include?(event["event_id"]) @printed_events << event["event_id"] out.puts "#{event["timestamp"]} - #{event["status"]}: #{event["reason"]}" end end out.flush end end