fluke/devops-service/workers/stack_bootstrap/stack_creation_waiter.rb
2016-03-29 20:09:05 +03:00

99 lines
2.4 KiB
Ruby

# Polling stack status until it's completed or failed.
class StackCreationWaiter
include PutsAndFlush
attr_reader :out, :stack
class SyncResult < Devops::Helpers::ResultObject
set_result_codes(
ok: 0,
stack_rolled_back: 1,
unkown_status: 2,
timeout: 3,
error: 5,
stack_deleted: 6,
stack_not_found: 7
)
end
def initialize(stack, out)
@stack, @out = stack, out
@printed_events = []
@sync_result = nil
end
def sync
puts_and_flush "Syncing stack '#{stack.id}'..."
sleep_times.detect do |sleep_time|
sleep sleep_time
stack.sync!
print_new_events
update_stack_status if stack_status_changed?
stack_is_already_created_or_failed?
end
@sync_result ||= result(:timeout)
print_result_message
@sync_result
rescue StandardError => e
DevopsLogger.logger.error e.message
puts_and_flush "Error: #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
result(:error)
end
private
def stack_is_already_created_or_failed?
case stack.stack_status
when 'CREATE_IN_PROGRESS', 'ROLLBACK_IN_PROGRESS', 'DELETE_IN_PROGRESS'
false
when 'CREATE_COMPLETE', 'ROLLBACK_COMPLETE', 'DELETE_COMPLETE', 'CREATE_FAILED', 'NOT_FOUND'
@sync_result = result_for_provider_status(stack.stack_status)
else
@sync_result = result(:unkown_status)
end
end
def sleep_times
[5]*5 + [10]*400
end
def result(reason)
SyncResult.from_reason(reason)
end
def result_for_provider_status(status)
provider_status_mapping = {
'CREATE_COMPLETE' => :ok,
'ROLLBACK_COMPLETE' => :stack_rolled_back,
'DELETE_COMPLETE' => :stack_deleted,
'NOT_FOUND' => :stack_not_found
}
result(provider_status_mapping.fetch(status))
end
def print_result_message
puts_and_flush Devops::Messages.t("stack_creation_waiter.result.#{@sync_result.reason}",
stack_id: stack.id, status: stack.stack_status, seconds: sleep_times.inject(&:+))
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 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