333 lines
13 KiB
Ruby
333 lines
13 KiB
Ruby
require "commands/status"
|
|
require "db/mongo/models/project"
|
|
require "workers/project_test_worker"
|
|
require "app/api2/parsers/project"
|
|
require "lib/project/type/types_factory"
|
|
require "lib/executors/server_executor"
|
|
require "workers/delete_server_worker"
|
|
require_relative "../helpers/version_2.rb"
|
|
require_relative "request_handler"
|
|
|
|
module Devops
|
|
module API2_0
|
|
module Handler
|
|
class Project < RequestHandler
|
|
|
|
set_parser Devops::API2_0::Parser::ProjectParser
|
|
|
|
include Devops::API2_0::Helpers
|
|
|
|
extend StatusCommands
|
|
|
|
def project_types
|
|
Devops::TypesFactory.types_names
|
|
end
|
|
|
|
def projects
|
|
Devops::Db.connector.projects(nil, nil, parser.projects, parser.archived_projects)
|
|
end
|
|
|
|
def project id
|
|
Devops::Db.connector.project(id)
|
|
end
|
|
|
|
def project_deploy_envs(id)
|
|
project = Devops::Db.connector.project(id)
|
|
project.deploy_envs
|
|
end
|
|
|
|
def project_deploy_env(project_id, env)
|
|
project = Devops::Db.connector.project(project_id)
|
|
project.deploy_env(env)
|
|
end
|
|
|
|
def project_servers id
|
|
Devops::Db.connector.project(id)
|
|
Devops::Db.connector.servers(id, parser.project_servers)
|
|
end
|
|
|
|
def project_stacks id
|
|
# check if project exists
|
|
Devops::Db.connector.project(id)
|
|
options = {project: id}
|
|
deploy_env = parser.project_stacks
|
|
options[:deploy_env] = deploy_env if deploy_env
|
|
Devops::Db.connector.stacks(options)
|
|
end
|
|
|
|
def create_project
|
|
p = parser.create_project
|
|
raise InvalidRecord.new("Project '#{p.id}' already exist") if Devops::Db.connector.is_project_exists?(p)
|
|
|
|
p.deploy_envs.each do |env|
|
|
env.add_users [parser.current_user]
|
|
end
|
|
res = p.create
|
|
info = if p.multi?
|
|
"Project '#{p.id}' with type 'multi' created"
|
|
else
|
|
"Project '#{p.id}' created."
|
|
end
|
|
# info << " " + res[:before] if res[:before]
|
|
# info << " " + res[:after] if res[:after]
|
|
info
|
|
end
|
|
|
|
def set_project_components id
|
|
body = parser.set_project_components
|
|
project = Devops::Db.connector.project(id)
|
|
project.components = body["components"]
|
|
project.validate_components
|
|
Devops::Db.connector.project_update_field id, "components", body["components"]
|
|
"Updated project '#{project.id}' with components '#{body["components"].inspect}'"
|
|
end
|
|
|
|
def add_deploy_env id
|
|
project = Devops::Db.connector.project(id)
|
|
env = parser.add_deploy_env
|
|
env.add_users [parser.current_user]
|
|
env.validate!
|
|
begin
|
|
db_env = project.deploy_env(env.identifier)
|
|
raise InvalidRecord.new("Can not add new environment for project '#{id}'. Environment '#{env.identifier}' already exist")
|
|
rescue RecordNotFound => e
|
|
res = project.add_deploy_env env
|
|
return "Deploy environment '#{env.identifier}' has been added to project '#{project.id}'." + res, env
|
|
end
|
|
end
|
|
|
|
def update_deploy_env_field id, deploy_env, field
|
|
project = Devops::Db.connector.project(id)
|
|
db_env = project.deploy_env(deploy_env)
|
|
value = parser.update_deploy_env_field
|
|
if db_env.respond_to?(field + "=")
|
|
if field == "identifier"
|
|
Devops::Db.connector.change_servers_deploy_env(db_env.identifier, value)
|
|
Devops::Db.connector.change_stacks_deploy_env(db_env.identifier, value)
|
|
db_env.rename id, value
|
|
"Environment '#{deploy_env}' has been renamed to '#{value}'"
|
|
else
|
|
db_env.update_field(id, field, value)
|
|
"Environment's field '#{field}' has been updated"
|
|
end
|
|
else
|
|
raise RecordNotFound.new("Field '#{field}' does not exist")
|
|
end
|
|
end
|
|
|
|
def update_deploy_env id, deploy_env
|
|
project = Devops::Db.connector.project(id)
|
|
db_env = project.deploy_env(deploy_env)
|
|
env = parser.update_deploy_env
|
|
env.identifier = deploy_env if env.identifier.nil?
|
|
begin
|
|
unless env.identifier == deploy_env
|
|
servers = Devops::Db.connector.servers_by_project_and_deploy_env(id, deploy_env)
|
|
raise InvalidRecord.new("Environment '#{deploy_env}' can't be updated: it has #{servers.size} running servers.") unless servers.empty?
|
|
end
|
|
begin
|
|
project.deploy_env(env.identifier)
|
|
raise InvalidRecord.new("Environment '#{deploy_env}' can't be renamed to '#{env.identifier}', environment '#{env.identifier}' already exists") unless deploy_env == env.identifier
|
|
rescue RecordNotFound => e
|
|
end
|
|
env.validate!
|
|
project.delete_deploy_env(deploy_env)
|
|
project.add_deploy_env(env)
|
|
"Deploy environment '#{deploy_env}' has been updated in project '#{project.id}'"
|
|
rescue RecordNotFound => e
|
|
env.identifier = deploy_env
|
|
res = project.add_deploy_env env
|
|
"Deploy environment '#{env.identifier}' has been added to project '#{project.id}'." + res
|
|
end
|
|
end
|
|
|
|
def delete_deploy_env id, deploy_env
|
|
project = Devops::Db.connector.project(id)
|
|
servers = Devops::Db.connector.servers_by_project_and_deploy_env(id, deploy_env)
|
|
raise InvalidRecord.new("Can not delete environment '#{deploy_env}', there are #{servers.size} servers on it") unless servers.empty?
|
|
project.delete_deploy_env(deploy_env)
|
|
"Deploy environment '#{deploy_env}' has been deleted from project '#{project.id}'."
|
|
end
|
|
|
|
# updates only run_list and description
|
|
def update_project id
|
|
body = parser.update
|
|
old_project = Devops::Db.connector.project id
|
|
Devops::Db.connector.project_update id, body
|
|
end
|
|
|
|
# TODO: multi project
|
|
def update_project_users id
|
|
deploy_env, users = parser.project_users
|
|
project = Devops::Db.connector.project(id)
|
|
Validators::Helpers::Users.new(users).validate!
|
|
project.add_authorized_user users, deploy_env
|
|
info = "Users '#{users.join("', '")}' has been added to '#{id}' project's authorized users."
|
|
info
|
|
end
|
|
|
|
# TODO: multi project
|
|
def delete_project_users id
|
|
deploy_env, users = parser.project_users
|
|
project = Devops::Db.connector.project(id)
|
|
project.remove_authorized_user users, deploy_env
|
|
"Users '#{users.join("', '")}' have been removed from '#{id}' project's authorized users"
|
|
end
|
|
|
|
def set_project_run_list id
|
|
list = parser.run_list
|
|
project = Devops::Db.connector.project(id)
|
|
Devops::Db.connector.set_project_run_list id, list
|
|
"Updated project with run_list '#{list.inspect}'"
|
|
end
|
|
|
|
def set_project_env_run_list id, deploy_env
|
|
list = parser.run_list
|
|
project = Devops::Db.connector.project(id)
|
|
env = project.deploy_env deploy_env
|
|
Devops::Db.connector.set_project_env_run_list id, deploy_env, list
|
|
"Updated environment '#{env.identifier}' with run_list '#{list.inspect}' in project '#{project.id}'"
|
|
end
|
|
|
|
def delete_project id
|
|
deploy_env = parser.delete
|
|
project = Devops::Db.connector.project(id)
|
|
if deploy_env.nil?
|
|
servers = Devops::Db.connector.servers id
|
|
raise DependencyError.new "Deleting project #{id} is forbidden: Project has servers" unless servers.empty?
|
|
project.delete
|
|
"Project '#{id}' is deleted"
|
|
else
|
|
servers = Devops::Db.connector.servers id, deploy_env
|
|
raise DependencyError.new "Deleting deploy_env #{deploy_env} is forbidden: Project has servers" unless servers.empty?
|
|
project.delete_deploy_env(deploy_env)
|
|
"Project '#{id}'. Deploy environment '#{deploy_env}' has been deleted"
|
|
end
|
|
end
|
|
|
|
def deploy_project_stream out, id
|
|
# check if project exist
|
|
project = Devops::Db.connector.project(id)
|
|
deploy_env, servers = parser.deploy
|
|
keys = {}
|
|
dbserver = Devops::Db.connector.servers(id, deploy_env, servers, true)
|
|
out << (dbservers.empty? ? "No reserved servers to deploy\n" : "Deploy servers: '#{dbservers.map{|s| s.chef_node_name}.join("', '")}'\n")
|
|
status = []
|
|
deploy_info_buf = {}
|
|
dbservers.each do |s|
|
|
begin
|
|
Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user
|
|
rescue InvalidPrivileges, RecordNotFound => e
|
|
out << e.message + "\n"
|
|
status.push 2
|
|
next
|
|
end
|
|
deploy_env_model = project.deploy_env(s.deploy_env)
|
|
deploy_info = if deploy_info_buf[s.deploy_env]
|
|
deploy_info_buf[s.deploy_env]
|
|
else
|
|
# мы не можем указать один build_number для всех окружений, поэтому nil
|
|
deploy_info_buf[s.deploy_env] = project.deploy_info(deploy_env_model, nil)
|
|
end
|
|
status.push(Devops::Executor::ServerExecutor.new(s, out, current_user: parser.current_user).deploy_server(deploy_info))
|
|
end
|
|
status
|
|
end
|
|
|
|
def deploy_project id
|
|
# check if project exist
|
|
project_model = Devops::Db.connector.project(id)
|
|
deploy_env, servers = parser.deploy
|
|
files = []
|
|
dbservers = Devops::Db.connector.servers(id, deploy_env, servers, true)
|
|
#out << (dbservers.empty? ? "No reserved servers to deploy\n" : "Deploy servers: '#{dbservers.map{|s| s.chef_node_name}.join("', '")}'\n")
|
|
deploy_info_buf = {}
|
|
dbservers.each do |s|
|
|
begin
|
|
Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user
|
|
rescue InvalidPrivileges, RecordNotFound => e
|
|
next
|
|
end
|
|
|
|
deploy_env_model = project_model.deploy_env(s.deploy_env)
|
|
deploy_info = if deploy_info_buf[s.deploy_env]
|
|
deploy_info_buf[s.deploy_env]
|
|
else
|
|
# мы не можем указать один build_number для всех окружений, поэтому nil
|
|
deploy_info_buf[s.deploy_env] = project_model.deploy_info(deploy_env_model, nil)
|
|
end
|
|
|
|
jid = Worker.start_async(DeployWorker,
|
|
server_attrs: s.to_hash,
|
|
owner: parser.current_user,
|
|
tags: [],
|
|
deploy_info: deploy_info
|
|
)
|
|
files.push jid
|
|
end
|
|
files
|
|
end
|
|
|
|
def archive_project id
|
|
project = Devops::Db.connector.project(id)
|
|
Devops::Db.connector.archive_project(id)
|
|
msg = "Project '#{id}' has been archived"
|
|
DevopsLogger.logger.info msg
|
|
msg
|
|
end
|
|
|
|
def unarchive_project id
|
|
project = Devops::Db.connector.project(id)
|
|
Devops::Db.connector.unarchive_project(id)
|
|
msg = "Project '#{id}' has been unarchived"
|
|
DevopsLogger.logger.info msg
|
|
msg
|
|
end
|
|
|
|
def test_project id, deploy_env
|
|
project = Devops::Db.connector.project(id)
|
|
env = project.deploy_env deploy_env
|
|
DevopsLogger.logger.info "Test project '#{project.id}' and environment '#{env.identifier}'"
|
|
if env.provider == ::Provider::Static::PROVIDER
|
|
msg = "Can not test environment with provider '#{::Provider::Static::PROVIDER}'"
|
|
Logger.warn msg
|
|
raise InvalidRecord.new(msg)
|
|
end
|
|
|
|
jid = Worker.start_async(ProjectTestWorker,
|
|
project: project.id,
|
|
deploy_env: env.identifier,
|
|
user: @request.env['REMOTE_USER']
|
|
)
|
|
|
|
sleep 1
|
|
return [jid]
|
|
end
|
|
|
|
def delete_project_servers(project_id)
|
|
env_id, dry_run = parser.delete_project_servers
|
|
Devops::Db.connector.project(project_id)
|
|
servers = Devops::Db.connector.servers(project_id, env_id)
|
|
info = {to_delete: servers.map(&:id)}
|
|
if !dry_run
|
|
info.merge!(delete_chosen_servers!(servers))
|
|
end
|
|
info
|
|
end
|
|
|
|
private
|
|
|
|
def delete_chosen_servers!(servers)
|
|
current_user = parser.current_user
|
|
reports = servers.map do |server|
|
|
Worker.start_async(DeleteServerWorker, 'server_id' => server.id, 'current_user' => current_user)
|
|
end
|
|
{reports: reports}
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|