require "db/mongo/models/stack/stack_factory" require "db/mongo/models/project" require "db/mongo/models/report" require "workers/stack_bootstrap/stack_synchronizer" require "workers/stack_bootstrap/stack_servers_bootstrapper" require "workers/stack_bootstrap/stack_servers_persister" require "workers/stack_bootstrap/errors" class StackBootstrapWorker < Worker def perform(options) stack_attrs = options.fetch('stack_attributes') call() do |out, file| @out = out without_bootstrap = stack_attrs.delete('without_bootstrap') @out.puts "Received 'without_bootstrap' option" if without_bootstrap save_report(file, stack_attrs) begin @stack = create_stack(stack_attrs) begin @servers_with_priority = stack_servers_persister.persist bootstrap_in_priority_order unless without_bootstrap 0 rescue StackServerBootstrapError puts_and_flush "\nAn error occured during bootstraping stack servers. Initiating stack rollback." rollback_stack!(@stack) 2 rescue StackServerDeployError => e out.puts "\nStack was launched, but an error occured during deploying stack servers." puts_and_flush "You can redeploy stack after fixing the error." 3 rescue StackServerBootstrapDeployTimeout puts_and_flush "\nBootstrap or deploy wasn't completed due to timeout." 4 rescue StandardError => e puts_and_flush "\nAn error occured. Initiating stack rollback." rollback_stack!(@stack) raise e end rescue StackCreatingError puts_and_flush "Stack creating error" 1 end end end private def stack_synchronizer(stack) StackSynchronizer.new(stack, out) end def stack_servers_persister @stack_servers_persister ||= StackServersPersister.new(@stack, out) end def stack_servers_bootstrapper @stack_servers_bootstrapper ||= StackServersBootstrapper.new(out, jid) end # builds and persist stack model, initiate stack creating in cloud def create_stack(stack_attrs) stack = Devops::Model::StackFactory.create(stack_attrs["provider"], stack_attrs, @out) mongo.stack_insert(stack) synchronizer = stack_synchronizer(stack) operation_result = synchronizer.sync if operation_result == 0 puts_and_flush "\nStack '#{stack.name}' has been created" stack else human_readable_code = synchronizer.reason_from_error_code(operation_result) out.puts "An error ocurred during stack creating" puts_and_flush "Stack creating operation result was #{human_readable_code}" raise StackCreatingError end end # Bootstrap servers with high priorities first def bootstrap_in_priority_order sorted_priorities = @servers_with_priority.keys.sort.reverse sorted_priorities.each do |priority| @out.puts "Servers with priority '#{priority}':" stack_servers_bootstrapper.bootstrap(@servers_with_priority[priority]) end puts_and_flush "Done." end def rollback_stack!(stack) puts_and_flush "\nStart rollback of a stack" stack.delete_stack_in_cloud! Devops::Db.connector.stack_servers_delete(stack.name) Devops::Db.connector.stack_delete(stack.id) puts_and_flush "Rollback has been completed" end def save_report(file, stack_attrs) report = ::Devops::Model::Report.new( "file" => file, "_id" => jid, "created_by" => stack_attrs['owner'], "project" => stack_attrs["project"], "deploy_env" => stack_attrs["deploy_env"], "type" => ::Devops::Model::Report::STACK_TYPE, "subreports" => [], "stack" => stack_attrs['name'] ) mongo.save_report(report) report end end