require "lib/executors/server_executor" require 'db/mongo/models/stack/stack_factory' require "app/api2/parsers/stack" require_relative "request_handler" module Devops module API2_0 module Handler class Stack < RequestHandler set_parser Devops::API2_0::Parser::StackParser def stacks Devops::Db.connector.stacks end def stacks_for_provider provider Devops::Db.connector.stacks(provider: provider) end def create_stack object = parser.create project = Devops::Db.connector.project(object["project"]) env = project.deploy_env(object["deploy_env"]) raise InvalidRecord.new("Environment '#{env.identifier}' of project '#{project.id}' has no stack template") if env.stack_template.nil? object["stack_template"] = env.stack_template object["owner"] = parser.current_user uri = Worker.start_async(StackBootstrapWorker, @request, provider_name: env.provider, stack_attributes: object ) puts "Syncing report is located here: #{uri}" [uri] end def stack id Devops::Db.connector.stack(id) end def delete_stack name stack = self.stack(name) stack.delete_stack_in_cloud! Devops::Db.connector.stack_servers_delete(stack.name) Devops::Db.connector.stack_delete(stack.id) end def sync_details id stack = self.stack(id) stack.sync_details! Devops::Db.connector.stack_update(stack) stack end def stack_servers name stack = Devops::Db.connector.stack(name) Devops::Db.connector.stack_servers(stack.id) end def resources id stack = Devops::Db.connector.stack(id) stack.resources end def resource id, resource_id stack = Devops::Db.connector.stack(id) stack.resource(resource_id) end def set_run_list id Devops::Db.connector.set_stack_run_list(id, parser.run_list) end def set_tags id tags = parser.tags prepare_tags do |id, provider| provider.set_tags id, tags end end def unset_tags id tags = parser.tags prepare_tags do |id, provider| provider.unset_tags id, tags end end def prepare_tags node_name stack = Devops::Db.connector.stack(id) Devops::Db.connector.check_project_auth stack.project, stack.deploy_env, parser.current_user stack_servers = Devops::Db.connector.stack_servers(id) provider = stack.provider_instance stack_servers.each do |s| yield s.id, provider end end def deploy id stack = self.stack(id) owner = parser.current_user status = [] project = Devops::Db.connector.check_project_auth(stack.project, stack.deploy_env, owner) deploy_env_model = project.deploy_env(stack.deploy_env) body = parser.deploy names = body["names"] tags = body["tags"] || [] files = [] jid = nil servers = Devops::Db.connector.stack_servers(id, true) servers.each do |s| begin deploy_info = project.deploy_info(deploy_env_model, nil) uri = Worker.start_async(DeployWorker, @request, server_attrs: s.to_hash, owner: owner, tags: tags, deploy_info: deploy_info ) rescue DeployInfoError => e msg = "Can not get deploy info: " + e.message DevopsLogger.logger.error msg jid = "error_#{s.chef_node_name}_#{Time.new.to_i}" dir = DevopsConfig.config[:report_dir_v2] file = File.jon(dir, jid) File.open(file, "w") do |out| out.write msg end o = { "file" => file, "_id" => jid, "created_by" => owner, "project" => s.project, "deploy_env" => s.deploy_env, "type" => Report::DEPLOY_TYPE, "status" => Worker::STATUS::FAILED } Devops::Db.connector.save_report(Report.new(o)) end files.push uri end files end def deploy_stream id, out stack = self.stack(id) owner = parser.current_user status = [] project = Devops::Db.connector.check_project_auth(stack.project, stack.deploy_env, owner) body = parser.deploy #TODO: deploy servers names # names = body["names"] tags = body["tags"] || [] # find all stack reserved servers servers = Devops::Db.connector.stack_servers(stack_id, true) deploy_info = project.deploy_info(stack.deploy_env, nil) servers.each do |s| begin res = Devops::Executor::ServerExecutor.new(s, out).deploy_server_with_tags(tags, deploy_info) status.push(res) rescue DeployInfoError => e msg = "Can not get deploy info: " + e.message DevopsLogger.logger.error msg out << msg + "\n" status.push 2 next end end status rescue RecordNotFound => e out << e.message [-10] end def reserve_servers(stack_id) stack = self.stack(stack_id) user = parser.current_user Devops::Db.connector.check_project_auth stack.project, stack.deploy_env, user # check if none of servers are reserved by somebody else servers = Devops::Db.connector.stack_servers(stack_id) servers.each do |server| if server.reserved_by.present? && server.reserved_by != user raise ConflictException.new("Server '#{server.chef_node_name}' already reserved by #{server.reserved_by}") end end # reserve them servers.each do |server| server.reserved_by = user Devops::Db.connector.server_update(server) end end def unreserve_servers(stack_id) stack = self.stack(stack_id) user = parser.current_user Devops::Db.connector.check_project_auth stack.project, stack.deploy_env, user servers = Devops::Db.connector.stack_servers(stack_id) servers.each do |server| server.reserved_by = nil Devops::Db.connector.server_update(server) end end end end end end