2015-08-14 13:28:03 +03:00
|
|
|
require "lib/executors/server_executor"
|
2018-04-04 22:44:39 +03:00
|
|
|
require "app/api3/parsers/stack"
|
2015-04-16 17:54:40 +03:00
|
|
|
require 'db/mongo/models/stack/stack_factory'
|
2016-01-27 11:51:54 +03:00
|
|
|
require 'workers/stack_bootstrap_worker'
|
2015-07-27 11:14:01 +03:00
|
|
|
require_relative "request_handler"
|
2015-04-16 17:54:40 +03:00
|
|
|
|
|
|
|
|
module Devops
|
2018-04-04 22:44:39 +03:00
|
|
|
module API3
|
2015-04-16 17:54:40 +03:00
|
|
|
module Handler
|
2015-07-27 11:14:01 +03:00
|
|
|
class Stack < RequestHandler
|
2015-04-16 17:54:40 +03:00
|
|
|
|
2018-04-04 22:44:39 +03:00
|
|
|
set_parser Devops::API3::Parser::StackParser
|
2015-07-30 15:37:43 +03:00
|
|
|
|
2015-07-27 11:14:01 +03:00
|
|
|
def stacks
|
2018-04-04 22:44:39 +03:00
|
|
|
Model::StackAws.all
|
2015-04-16 17:54:40 +03:00
|
|
|
end
|
|
|
|
|
|
2018-04-04 22:44:39 +03:00
|
|
|
# We support only aws, actually
|
2015-07-27 16:42:28 +03:00
|
|
|
def stacks_for_provider provider
|
2018-04-04 22:44:39 +03:00
|
|
|
Model::StackAws.all
|
2015-04-16 17:54:40 +03:00
|
|
|
end
|
|
|
|
|
|
2015-07-30 15:37:43 +03:00
|
|
|
def create_stack
|
2018-04-04 22:44:39 +03:00
|
|
|
object = parser.create
|
|
|
|
|
attrs = object['stack_attributes']
|
|
|
|
|
env, category = fetch_env_and_category(attrs)
|
|
|
|
|
fill_attributes_from_category(attrs, env, category)
|
|
|
|
|
jid = Worker.start_async(StackBootstrapWorker,
|
|
|
|
|
stack_attributes: attrs,
|
|
|
|
|
without_bootstrap: object['without_bootstrap'],
|
|
|
|
|
skip_rollback: object['skip_rollback']
|
|
|
|
|
)
|
2015-11-03 12:05:07 +03:00
|
|
|
[jid]
|
2015-04-16 17:54:40 +03:00
|
|
|
end
|
|
|
|
|
|
2018-04-04 22:44:39 +03:00
|
|
|
def stack name
|
|
|
|
|
Model::StackAws.where(name: name).first
|
2015-04-16 17:54:40 +03:00
|
|
|
end
|
|
|
|
|
|
2015-08-18 16:37:33 +03:00
|
|
|
def delete_stack name
|
2015-08-18 16:41:16 +03:00
|
|
|
stack = self.stack(name)
|
2015-07-27 11:14:01 +03:00
|
|
|
stack.delete_stack_in_cloud!
|
2018-04-04 22:44:39 +03:00
|
|
|
Model::Server.where(stack: stack.id).delete_all
|
|
|
|
|
stack.delete
|
2015-04-16 17:54:40 +03:00
|
|
|
end
|
|
|
|
|
|
2016-02-24 21:26:44 +03:00
|
|
|
def sync id
|
2015-07-27 16:42:28 +03:00
|
|
|
stack = self.stack(id)
|
2016-04-04 13:17:07 +03:00
|
|
|
stack.sync_status_and_events!
|
2015-07-27 16:42:28 +03:00
|
|
|
Devops::Db.connector.stack_update(stack)
|
2015-08-05 15:06:18 +03:00
|
|
|
|
|
|
|
|
stack
|
2015-07-27 16:42:28 +03:00
|
|
|
end
|
|
|
|
|
|
2015-08-19 16:52:01 +03:00
|
|
|
def stack_servers name
|
|
|
|
|
stack = Devops::Db.connector.stack(name)
|
|
|
|
|
Devops::Db.connector.stack_servers(stack.id)
|
|
|
|
|
end
|
|
|
|
|
|
2015-08-04 12:36:10 +03:00
|
|
|
def set_run_list id
|
|
|
|
|
Devops::Db.connector.set_stack_run_list(id, parser.run_list)
|
|
|
|
|
end
|
2015-08-14 13:28:03 +03:00
|
|
|
|
2015-09-15 17:14:26 +03:00
|
|
|
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
|
|
|
|
|
|
2015-08-14 13:28:03 +03:00
|
|
|
def deploy id
|
|
|
|
|
stack = self.stack(id)
|
|
|
|
|
owner = parser.current_user
|
|
|
|
|
project = Devops::Db.connector.check_project_auth(stack.project, stack.deploy_env, owner)
|
2015-09-02 11:38:58 +03:00
|
|
|
deploy_env_model = project.deploy_env(stack.deploy_env)
|
2015-08-14 13:28:03 +03:00
|
|
|
body = parser.deploy
|
|
|
|
|
names = body["names"]
|
|
|
|
|
tags = body["tags"] || []
|
|
|
|
|
files = []
|
|
|
|
|
jid = nil
|
2015-09-02 11:38:58 +03:00
|
|
|
servers = Devops::Db.connector.stack_servers(id, true)
|
2015-08-14 13:28:03 +03:00
|
|
|
servers.each do |s|
|
|
|
|
|
begin
|
2015-09-02 11:38:58 +03:00
|
|
|
deploy_info = project.deploy_info(deploy_env_model, nil)
|
2015-11-03 12:05:07 +03:00
|
|
|
jid = Worker.start_async(DeployWorker,
|
2015-09-02 11:38:58 +03:00
|
|
|
server_attrs: s.to_hash,
|
|
|
|
|
owner: owner,
|
|
|
|
|
tags: tags,
|
|
|
|
|
deploy_info: deploy_info
|
|
|
|
|
)
|
2015-08-14 13:28:03 +03:00
|
|
|
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}"
|
2015-09-02 11:38:58 +03:00
|
|
|
dir = DevopsConfig.config[:report_dir_v2]
|
2015-08-14 13:28:03 +03:00
|
|
|
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,
|
2018-04-04 22:44:39 +03:00
|
|
|
"type" => JobTask::DEPLOY_TYPE,
|
2015-08-14 13:28:03 +03:00
|
|
|
"status" => Worker::STATUS::FAILED
|
|
|
|
|
}
|
2018-04-04 22:44:39 +03:00
|
|
|
JobTask.create(o)
|
2015-08-14 13:28:03 +03:00
|
|
|
end
|
2015-11-03 12:05:07 +03:00
|
|
|
files.push jid
|
2015-08-14 13:28:03 +03:00
|
|
|
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
|
2015-11-23 17:21:43 +03:00
|
|
|
res = Devops::Executor::ServerExecutor.new(s, out, current_user: owner).deploy_server_with_tags(tags, deploy_info)
|
2015-08-14 13:28:03 +03:00
|
|
|
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
|
|
|
|
|
|
2015-09-24 15:06:02 +03:00
|
|
|
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
|
|
|
|
|
|
2015-11-17 18:08:38 +03:00
|
|
|
def change_stack_template(stack_id)
|
|
|
|
|
stack_template_id = parser.change_stack_template
|
|
|
|
|
Devops::Db.connector.stack_template(stack_template_id)
|
|
|
|
|
stack = Devops::Db.connector.stack(stack_id)
|
|
|
|
|
stack.change_stack_template!(stack_template_id)
|
|
|
|
|
end
|
|
|
|
|
|
2016-04-04 13:17:07 +03:00
|
|
|
private
|
|
|
|
|
|
2018-04-04 22:44:39 +03:00
|
|
|
# env is used in devops-nibr
|
|
|
|
|
def fill_attributes_from_category(stack_attrs, env, category)
|
|
|
|
|
stack_attrs['stack_template'] = category.provider.stack_template
|
2016-04-04 13:17:07 +03:00
|
|
|
stack_attrs['owner'] = parser.current_user
|
2018-04-04 22:44:39 +03:00
|
|
|
stack_attrs['provider'] = category.provider.name
|
|
|
|
|
stack_attrs['provider_account'] = category.provider.account
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def fetch_env_and_category(attrs)
|
|
|
|
|
project = Model::Project.find_with_category(*attrs.values_at('project', 'environment', 'category'))
|
|
|
|
|
unless project
|
|
|
|
|
raise InvalidRecord.new("Project '#{attrs['project']}' has no env '#{attrs['environment']}' or category '#{attrs['category']}")
|
|
|
|
|
end
|
|
|
|
|
env = project.environment(attrs['environment'])
|
|
|
|
|
category = env.get_category!(attrs['category'])
|
|
|
|
|
if category.provider.type != Model::CategoryProvider::STACK_TYPE
|
|
|
|
|
raise InvalidRecord.new("Category '#{category.id}' type isn't 'stack'")
|
|
|
|
|
end
|
|
|
|
|
[env, category]
|
2016-04-04 13:17:07 +03:00
|
|
|
end
|
|
|
|
|
|
2015-04-16 17:54:40 +03:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2015-07-27 11:14:01 +03:00
|
|
|
end
|