#730: Detailed stack creating logs
This commit is contained in:
parent
f01973ce92
commit
d7103c572b
@ -79,6 +79,7 @@ module Devops
|
|||||||
def add_or_update_deploy_env id, deploy_env
|
def add_or_update_deploy_env id, deploy_env
|
||||||
project = Devops::Db.connector.project(id)
|
project = Devops::Db.connector.project(id)
|
||||||
env = parser.add_or_update_deploy_env
|
env = parser.add_or_update_deploy_env
|
||||||
|
env.identifier = deploy_env if env.identifier.nil?
|
||||||
begin
|
begin
|
||||||
db_env = project.deploy_env(deploy_env)
|
db_env = project.deploy_env(deploy_env)
|
||||||
unless env.identifier == deploy_env
|
unless env.identifier == deploy_env
|
||||||
@ -90,6 +91,7 @@ module Devops
|
|||||||
raise InvalidRecord.new("Can not change environment '#{deploy_env}' to '#{env.identifier}', environment '#{env.identifier}' already exist") unless deploy_env == env.identifier
|
raise InvalidRecord.new("Can not change environment '#{deploy_env}' to '#{env.identifier}', environment '#{env.identifier}' already exist") unless deploy_env == env.identifier
|
||||||
rescue RecordNotFound => e
|
rescue RecordNotFound => e
|
||||||
end
|
end
|
||||||
|
env.validate!
|
||||||
project.delete_deploy_env(deploy_env)
|
project.delete_deploy_env(deploy_env)
|
||||||
project.add_deploy_env(env)
|
project.add_deploy_env(env)
|
||||||
"Deploy environment '#{deploy_env}' has been updated in project '#{project.id}'"
|
"Deploy environment '#{deploy_env}' has been updated in project '#{project.id}'"
|
||||||
@ -165,42 +167,56 @@ module Devops
|
|||||||
end
|
end
|
||||||
|
|
||||||
def deploy_project_stream out, id
|
def deploy_project_stream out, id
|
||||||
|
# check if project exist
|
||||||
|
project = Devops::Db.connector.project(id)
|
||||||
deploy_env, servers = parser.deploy
|
deploy_env, servers = parser.deploy
|
||||||
keys = {}
|
keys = {}
|
||||||
dbserver = servers(id, deploy_env, servers)
|
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")
|
out << (dbservers.empty? ? "No reserved servers to deploy\n" : "Deploy servers: '#{dbservers.map{|s| s.chef_node_name}.join("', '")}'\n")
|
||||||
status = []
|
status = []
|
||||||
servers.each do |s|
|
deploy_info_buf = {}
|
||||||
project = begin
|
dbservers.each do |s|
|
||||||
|
begin
|
||||||
Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user
|
Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user
|
||||||
rescue InvalidPrivileges, RecordNotFound => e
|
rescue InvalidPrivileges, RecordNotFound => e
|
||||||
out << e.message + "\n"
|
out << e.message + "\n"
|
||||||
status.push 2
|
status.push 2
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
deploy_info = project.deploy_info(s.deploy_env, nil)
|
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).deploy_server(deploy_info))
|
status.push(Devops::Executor::ServerExecutor.new(s, out).deploy_server(deploy_info))
|
||||||
end
|
end
|
||||||
status
|
status
|
||||||
end
|
end
|
||||||
|
|
||||||
def deploy_project id
|
def deploy_project id
|
||||||
|
# check if project exist
|
||||||
|
project_model = Devops::Db.connector.project(id)
|
||||||
deploy_env, servers = parser.deploy
|
deploy_env, servers = parser.deploy
|
||||||
files = []
|
files = []
|
||||||
servers(id, deploy_env, servers).each do |s|
|
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
|
begin
|
||||||
Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user
|
Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user
|
||||||
rescue InvalidPrivileges, RecordNotFound => e
|
rescue InvalidPrivileges, RecordNotFound => e
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
project_model = project(s.project)
|
deploy_env_model = project_model.deploy_env(s.deploy_env)
|
||||||
deploy_env_model = project_model.deploy_env(deploy_env)
|
deploy_info = if deploy_info_buf[s.deploy_env]
|
||||||
|
deploy_info_buf[s.deploy_env]
|
||||||
puts '!!! WARNING !!!'
|
else
|
||||||
puts 'build_number is set to empty string'
|
# мы не можем указать один build_number для всех окружений, поэтому nil
|
||||||
build_number = ''
|
deploy_info_buf[s.deploy_env] = project_model.deploy_info(deploy_env_model, nil)
|
||||||
deploy_info = project_model.deploy_info(deploy_env_model, build_number)
|
end
|
||||||
|
|
||||||
uri = Worker.start_async(DeployWorker, @request,
|
uri = Worker.start_async(DeployWorker, @request,
|
||||||
server_attrs: s.to_hash,
|
server_attrs: s.to_hash,
|
||||||
@ -213,11 +229,6 @@ module Devops
|
|||||||
files
|
files
|
||||||
end
|
end
|
||||||
|
|
||||||
def servers project_id, deploy_env, servers
|
|
||||||
project = Devops::Db.connector.project(project_id)
|
|
||||||
dbservers = Devops::Db.connector.servers(project_id, deploy_env, servers, true)
|
|
||||||
end
|
|
||||||
|
|
||||||
def archive_project id
|
def archive_project id
|
||||||
project = Devops::Db.connector.project(id)
|
project = Devops::Db.connector.project(id)
|
||||||
Devops::Db.connector.archive_project(id)
|
Devops::Db.connector.archive_project(id)
|
||||||
|
|||||||
@ -52,7 +52,6 @@ module Devops
|
|||||||
|
|
||||||
def update
|
def update
|
||||||
body = create_object_from_json_body
|
body = create_object_from_json_body
|
||||||
check_string(body["name"], "Parameter 'name' must be a not empty string", true, false)
|
|
||||||
check_string(body["description"], "Parameter 'description' must be a string", true, true)
|
check_string(body["description"], "Parameter 'description' must be a string", true, true)
|
||||||
#check_array(body["deploy_envs"], "Parameter 'deploy_envs' must be a not empty array of objects", Hash)
|
#check_array(body["deploy_envs"], "Parameter 'deploy_envs' must be a not empty array of objects", Hash)
|
||||||
rl = check_array(body["run_list"], "Parameter 'run_list' must be an array of string", String, true, true)
|
rl = check_array(body["run_list"], "Parameter 'run_list' must be an array of string", String, true, true)
|
||||||
|
|||||||
@ -1,10 +1,23 @@
|
|||||||
module StackCommands
|
module StackCommands
|
||||||
extend self
|
extend self
|
||||||
|
|
||||||
|
def self.result_codes
|
||||||
|
{
|
||||||
|
stack_rolled_back: 1,
|
||||||
|
unkown_status: 2,
|
||||||
|
timeout: 3,
|
||||||
|
error: 5
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.result_code(code)
|
||||||
|
result_codes.fetch(code)
|
||||||
|
end
|
||||||
|
|
||||||
def sync_stack_proc
|
def sync_stack_proc
|
||||||
lambda do |out, stack, mongo|
|
lambda do |out, stack, mongo|
|
||||||
# two tries each 4 seconds, then 5 tries each 10 seconds, then 10 tries each 30 seconds.
|
# 5 tries each 5 seconds, then 200 tries each 10 seconds
|
||||||
sleep_times = [4]*2 + [10]*5 + [30]*10
|
sleep_times = [5]*5 + [10]*200
|
||||||
|
|
||||||
begin
|
begin
|
||||||
out << "Syncing stack '#{stack.id}'...\n"
|
out << "Syncing stack '#{stack.id}'...\n"
|
||||||
@ -22,27 +35,20 @@ module StackCommands
|
|||||||
return 0
|
return 0
|
||||||
when 'ROLLBACK_COMPLETE'
|
when 'ROLLBACK_COMPLETE'
|
||||||
out << "\nStack '#{stack.id}' status is rolled back\n"
|
out << "\nStack '#{stack.id}' status is rolled back\n"
|
||||||
return 1
|
return StackCommands.result_code(:stack_rolled_back)
|
||||||
else
|
else
|
||||||
out << "\nUnknown status: '#{stack.stack_status}'"
|
out.puts "\nUnknown stack status: '#{stack.stack_status}'"
|
||||||
return 2
|
return StackCommands.result_code(:unkown_status)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
out.puts "Stack hasn't synced in #{sleep_times.inject(&:+)} seconds."
|
||||||
|
return StackCommands.result_code(:timeout)
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
logger.error e.message
|
logger.error e.message
|
||||||
out << "Error: #{e.message}\n"
|
out << "Error: #{e.message}\n"
|
||||||
return 5
|
return StackCommands.result_code(:error)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
|
||||||
def bootstrap_stack_servers_proc(out, stack, mongo, provider, logger)
|
|
||||||
mongo.stack_servers(stack.id).each do |server|
|
|
||||||
key = mongo.key(server.key)
|
|
||||||
two_phase_bootstrap(server, out, provider, mongo, key.path, logger)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
=end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -6,10 +6,24 @@ require "exceptions/invalid_privileges"
|
|||||||
module Connectors
|
module Connectors
|
||||||
class Base
|
class Base
|
||||||
|
|
||||||
|
# если хотим создавать индексы при старте приложения, нужно сначала создать коллекцию
|
||||||
|
def initialize db
|
||||||
|
names = db.collection_names
|
||||||
|
unless names.include?(self.collection_name)
|
||||||
|
db.create_collection(self.collection_name)
|
||||||
|
puts "Collection '#{self.collection_name}' has been created"
|
||||||
|
end
|
||||||
|
self.collection = db.collection(self.collection_name)
|
||||||
|
end
|
||||||
|
|
||||||
def create_indexes
|
def create_indexes
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def collection_name
|
||||||
|
raise "owerride me"
|
||||||
|
end
|
||||||
|
|
||||||
# Yes, we can implement connectors without attr_accessor, storing collection directly
|
# Yes, we can implement connectors without attr_accessor, storing collection directly
|
||||||
# in instance variable like
|
# in instance variable like
|
||||||
# @collection = db.collection('users')
|
# @collection = db.collection('users')
|
||||||
|
|||||||
@ -2,7 +2,11 @@ module Connectors
|
|||||||
class Filter < Base
|
class Filter < Base
|
||||||
|
|
||||||
def initialize(db)
|
def initialize(db)
|
||||||
self.collection = db.collection('filters')
|
super(db)
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_name
|
||||||
|
'filters'
|
||||||
end
|
end
|
||||||
|
|
||||||
def available_images provider
|
def available_images provider
|
||||||
|
|||||||
@ -9,7 +9,11 @@ module Connectors
|
|||||||
Helpers::UpdateCommand
|
Helpers::UpdateCommand
|
||||||
|
|
||||||
def initialize(db)
|
def initialize(db)
|
||||||
self.collection = db.collection('images')
|
super(db)
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_name
|
||||||
|
'images'
|
||||||
end
|
end
|
||||||
|
|
||||||
def images(provider=nil)
|
def images(provider=nil)
|
||||||
|
|||||||
@ -7,7 +7,11 @@ module Connectors
|
|||||||
Helpers::DeleteCommand
|
Helpers::DeleteCommand
|
||||||
|
|
||||||
def initialize(db)
|
def initialize(db)
|
||||||
self.collection = db.collection('keys')
|
super(db)
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_name
|
||||||
|
'keys'
|
||||||
end
|
end
|
||||||
|
|
||||||
def key(id, scope=nil)
|
def key(id, scope=nil)
|
||||||
|
|||||||
@ -8,7 +8,11 @@ module Connectors
|
|||||||
|
|
||||||
|
|
||||||
def initialize(db)
|
def initialize(db)
|
||||||
@collection = db.collection('projects')
|
super(db)
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_name
|
||||||
|
'projects'
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_project_exists?(project)
|
def is_project_exists?(project)
|
||||||
@ -104,7 +108,6 @@ module Connectors
|
|||||||
end
|
end
|
||||||
|
|
||||||
def add_deploy_env_to_project id, env
|
def add_deploy_env_to_project id, env
|
||||||
env.validate!
|
|
||||||
@collection.update({"_id" => id}, {'$push' => {deploy_envs: env.to_hash} })
|
@collection.update({"_id" => id}, {'$push' => {deploy_envs: env.to_hash} })
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -119,7 +122,7 @@ module Connectors
|
|||||||
end
|
end
|
||||||
|
|
||||||
def project_update id, params
|
def project_update id, params
|
||||||
raise InvalidRecord.new("You can not change project name for '#{id}'.") if params["name"]
|
#raise InvalidRecord.new("You can not change project name for '#{id}'.") if params["name"]
|
||||||
keys = %w(run_list description)
|
keys = %w(run_list description)
|
||||||
params.delete_if{|k,v| !keys.include?(k)}
|
params.delete_if{|k,v| !keys.include?(k)}
|
||||||
@collection.update({"_id" => id}, {'$set' => params })
|
@collection.update({"_id" => id}, {'$set' => params })
|
||||||
|
|||||||
@ -8,7 +8,11 @@ module Connectors
|
|||||||
|
|
||||||
|
|
||||||
def initialize(db)
|
def initialize(db)
|
||||||
@collection = db.collection('project_templates')
|
super(db)
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_name
|
||||||
|
'project_templates'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -6,7 +6,11 @@ module Connectors
|
|||||||
Helpers::ListCommand
|
Helpers::ListCommand
|
||||||
|
|
||||||
def initialize(db)
|
def initialize(db)
|
||||||
self.collection = db.collection('reports')
|
super(db)
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_name
|
||||||
|
'reports'
|
||||||
end
|
end
|
||||||
|
|
||||||
def save_report r
|
def save_report r
|
||||||
|
|||||||
@ -5,7 +5,11 @@ module Connectors
|
|||||||
|
|
||||||
|
|
||||||
def initialize(db)
|
def initialize(db)
|
||||||
self.collection = db.collection('servers')
|
super(db)
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_name
|
||||||
|
'servers'
|
||||||
end
|
end
|
||||||
|
|
||||||
def servers_find(query, fields=nil)
|
def servers_find(query, fields=nil)
|
||||||
|
|||||||
@ -7,7 +7,11 @@ module Connectors
|
|||||||
Helpers::UpdateCommand
|
Helpers::UpdateCommand
|
||||||
|
|
||||||
def initialize(db)
|
def initialize(db)
|
||||||
self.collection = db.collection('stacks')
|
super(db)
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_name
|
||||||
|
'stacks'
|
||||||
end
|
end
|
||||||
|
|
||||||
def stacks(options={})
|
def stacks(options={})
|
||||||
|
|||||||
@ -8,7 +8,11 @@ module Connectors
|
|||||||
Helpers::UpdateCommand
|
Helpers::UpdateCommand
|
||||||
|
|
||||||
def initialize(db)
|
def initialize(db)
|
||||||
self.collection = db.collection('stack_templates')
|
super(db)
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_name
|
||||||
|
"stack_templates"
|
||||||
end
|
end
|
||||||
|
|
||||||
def stack_templates(provider=nil)
|
def stack_templates(provider=nil)
|
||||||
|
|||||||
@ -2,7 +2,11 @@ module Connectors
|
|||||||
class Statistic < Base
|
class Statistic < Base
|
||||||
|
|
||||||
def initialize(db)
|
def initialize(db)
|
||||||
self.collection = db.collection('statistic')
|
super(db)
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_name
|
||||||
|
'statistic'
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert_statistic(user, path, method, body, response_code)
|
def insert_statistic(user, path, method, body, response_code)
|
||||||
@ -45,7 +49,8 @@ module Connectors
|
|||||||
private
|
private
|
||||||
|
|
||||||
def mongo_sort_order(order)
|
def mongo_sort_order(order)
|
||||||
raise "Wrong sort order" unless %w(asc desc).include?(order)
|
# asc by default and if order id invalid value, it is not a reason for response with code 500
|
||||||
|
#raise "Wrong sort order" unless %w(asc desc).include?(order)
|
||||||
order == 'asc' ? 1 : -1
|
order == 'asc' ? 1 : -1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,11 @@ module Connectors
|
|||||||
Helpers::UpdateCommand
|
Helpers::UpdateCommand
|
||||||
|
|
||||||
def initialize(db)
|
def initialize(db)
|
||||||
self.collection = db.collection('users')
|
super(db)
|
||||||
|
end
|
||||||
|
|
||||||
|
def collection_name
|
||||||
|
'users'
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_auth user, password
|
def user_auth user, password
|
||||||
|
|||||||
@ -35,6 +35,25 @@ module Devops
|
|||||||
@out.class.send(:define_method, :flush) { } unless @out.respond_to?(:flush)
|
@out.class.send(:define_method, :flush) { } unless @out.respond_to?(:flush)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def result_codes
|
||||||
|
self.class.result_codes
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.result_codes
|
||||||
|
{
|
||||||
|
server_bootstrap_fail: 2,
|
||||||
|
server_not_in_chef_nodes: 5
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.result_code(code)
|
||||||
|
result_codes.fetch(code)
|
||||||
|
end
|
||||||
|
|
||||||
|
def result_code(code)
|
||||||
|
self.class.result_code(code)
|
||||||
|
end
|
||||||
|
|
||||||
def report= r
|
def report= r
|
||||||
@report = r
|
@report = r
|
||||||
end
|
end
|
||||||
@ -95,7 +114,8 @@ module Devops
|
|||||||
DevopsLogger.logger.error e.message
|
DevopsLogger.logger.error e.message
|
||||||
roll_back
|
roll_back
|
||||||
mongo.server_delete @server.id
|
mongo.server_delete @server.id
|
||||||
return 5
|
# return 5
|
||||||
|
return result_code(:server_not_in_chef_nodes)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -127,12 +147,13 @@ module Devops
|
|||||||
cmd = 'ssh '
|
cmd = 'ssh '
|
||||||
cmd << "-i #{cert_path} "
|
cmd << "-i #{cert_path} "
|
||||||
cmd << '-q '
|
cmd << '-q '
|
||||||
|
cmd << '-o StrictHostKeyChecking=no '
|
||||||
cmd << '-o ConnectTimeout=2 -o ConnectionAttempts=1 '
|
cmd << '-o ConnectTimeout=2 -o ConnectionAttempts=1 '
|
||||||
cmd << "#{address} 'exit'"
|
cmd << "#{address} 'exit'"
|
||||||
cmd << " 2>&1"
|
cmd << " 2>&1"
|
||||||
|
|
||||||
@out << "\nWaiting for SSH..."
|
@out.puts "\nWaiting for SSH..."
|
||||||
@out << "Test command: '#{cmd}'\n"
|
@out.puts "Test command: '#{cmd}'"
|
||||||
@out.flush
|
@out.flush
|
||||||
|
|
||||||
retries_amount = 0
|
retries_amount = 0
|
||||||
@ -140,14 +161,17 @@ module Devops
|
|||||||
sleep(5)
|
sleep(5)
|
||||||
res = `#{cmd}`
|
res = `#{cmd}`
|
||||||
retries_amount += 1
|
retries_amount += 1
|
||||||
if retries_amount == max_retries_amount
|
if retries_amount > max_retries_amount
|
||||||
@out << "\nCan not connect to #{address}"
|
@out.puts "Can not connect to #{address}"
|
||||||
@out << "\n" + res
|
@out.puts res
|
||||||
|
@out.flush
|
||||||
DevopsLogger.logger.error "Can not connect with command '#{cmd}':\n#{res}"
|
DevopsLogger.logger.error "Can not connect with command '#{cmd}':\n#{res}"
|
||||||
return false
|
return result_code(:server_bootstrap_fail)
|
||||||
end
|
end
|
||||||
raise ArgumentError.new("Can not connect with command '#{cmd}' ") unless $?.success?
|
raise ArgumentError.new("Can not connect with command '#{cmd}' ") unless $?.success?
|
||||||
rescue ArgumentError => e
|
rescue ArgumentError => e
|
||||||
|
@out.puts "SSH command failed, retry (#{retries_amount}/#{max_retries_amount})"
|
||||||
|
@out.flush
|
||||||
retry
|
retry
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -195,7 +219,8 @@ module Devops
|
|||||||
else
|
else
|
||||||
@out << roll_back
|
@out << roll_back
|
||||||
mongo.server_delete @server.id
|
mongo.server_delete @server.id
|
||||||
return 5
|
# return 5
|
||||||
|
return result_code(:server_not_in_chef_nodes)
|
||||||
end
|
end
|
||||||
@out << "\n"
|
@out << "\n"
|
||||||
@out.flush
|
@out.flush
|
||||||
@ -284,7 +309,7 @@ module Devops
|
|||||||
cmd = "chef-client --no-color"
|
cmd = "chef-client --no-color"
|
||||||
if deploy_info["use_json_file"]
|
if deploy_info["use_json_file"]
|
||||||
deploy_info.delete("use_json_file")
|
deploy_info.delete("use_json_file")
|
||||||
@out << "Build information:\n"
|
@out << "Deploy Input Parameters:\n"
|
||||||
json = JSON.pretty_generate(deploy_info)
|
json = JSON.pretty_generate(deploy_info)
|
||||||
@out << json
|
@out << json
|
||||||
@out << "\n"
|
@out << "\n"
|
||||||
@ -394,7 +419,7 @@ module Devops
|
|||||||
private
|
private
|
||||||
|
|
||||||
def max_retries_amount
|
def max_retries_amount
|
||||||
120
|
20
|
||||||
end
|
end
|
||||||
|
|
||||||
def schedule_expiration(server)
|
def schedule_expiration(server)
|
||||||
|
|||||||
@ -103,7 +103,14 @@ module Provider
|
|||||||
options = {
|
options = {
|
||||||
"InstanceType" => flavor,
|
"InstanceType" => flavor,
|
||||||
# "Placement.AvailabilityZone" => s.options[:availability_zone],
|
# "Placement.AvailabilityZone" => s.options[:availability_zone],
|
||||||
"KeyName" => self.ssh_key
|
"KeyName" => self.ssh_key,
|
||||||
|
"Tags" => {
|
||||||
|
"Name" => s.chef_node_name,
|
||||||
|
"cid:project" => s.project,
|
||||||
|
"cid:deployEnv" => s.deploy_env,
|
||||||
|
"cid:user" => s.created_by,
|
||||||
|
"cid:remoteUser" => s.remote_user
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vpcId = nil
|
vpcId = nil
|
||||||
unless subnets.empty?
|
unless subnets.empty?
|
||||||
@ -150,7 +157,7 @@ module Provider
|
|||||||
end
|
end
|
||||||
s.public_ip = details["ipAddress"]
|
s.public_ip = details["ipAddress"]
|
||||||
s.private_ip = details["privateIpAddress"]
|
s.private_ip = details["privateIpAddress"]
|
||||||
set_server_tags(s)
|
# set_server_tags(s)
|
||||||
out << "\nDone\n\n"
|
out << "\nDone\n\n"
|
||||||
out << s.info
|
out << s.info
|
||||||
|
|
||||||
@ -159,11 +166,6 @@ module Provider
|
|||||||
|
|
||||||
def set_server_tags s
|
def set_server_tags s
|
||||||
tags = {
|
tags = {
|
||||||
"Name" => s.chef_node_name,
|
|
||||||
"cid:project" => s.project,
|
|
||||||
"cid:deployEnv" => s.deploy_env,
|
|
||||||
"cid:user" => s.created_by,
|
|
||||||
"cid:remoteUser" => s.remote_user
|
|
||||||
}
|
}
|
||||||
compute.create_tags(s.id, tags)
|
compute.create_tags(s.id, tags)
|
||||||
end
|
end
|
||||||
@ -226,12 +228,18 @@ module Provider
|
|||||||
{
|
{
|
||||||
'TemplateBody' => stack.template_body,
|
'TemplateBody' => stack.template_body,
|
||||||
'Parameters' => stack.parameters || {},
|
'Parameters' => stack.parameters || {},
|
||||||
'Capabilities' => ['CAPABILITY_IAM']
|
'Capabilities' => ['CAPABILITY_IAM'],
|
||||||
|
'Tags' => {
|
||||||
|
"StackName" => stack.name,
|
||||||
|
"cid:project" => stack.project,
|
||||||
|
"cid:deployEnv" => stack.deploy_env,
|
||||||
|
"cid:user" => stack.owner
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
stack.id = response.body['StackId']
|
stack.id = response.body['StackId']
|
||||||
out << "Stack id: #{stack.id}\n"
|
out << "Stack id: #{stack.id}\n"
|
||||||
set_stack_tags(stack, out)
|
#set_stack_tags(stack, out)
|
||||||
out.flush
|
out.flush
|
||||||
rescue Excon::Errors::Conflict => e
|
rescue Excon::Errors::Conflict => e
|
||||||
raise ProviderErrors::NameConflict
|
raise ProviderErrors::NameConflict
|
||||||
@ -251,10 +259,6 @@ module Provider
|
|||||||
|
|
||||||
def set_stack_tags stack, out=""
|
def set_stack_tags stack, out=""
|
||||||
tags = {
|
tags = {
|
||||||
"StackName" => stack.name,
|
|
||||||
"cid:project" => stack.project,
|
|
||||||
"cid:deployEnv" => stack.deploy_env,
|
|
||||||
"cid:user" => stack.owner
|
|
||||||
# "cid:remoteUser" => s.remote_user
|
# "cid:remoteUser" => s.remote_user
|
||||||
}
|
}
|
||||||
#ids = stack_resources(stack).map {|resource| resource['PhysicalResourceId']}
|
#ids = stack_resources(stack).map {|resource| resource['PhysicalResourceId']}
|
||||||
@ -279,7 +283,11 @@ module Provider
|
|||||||
end
|
end
|
||||||
|
|
||||||
def stack_details(stack)
|
def stack_details(stack)
|
||||||
cloud_formation.describe_stacks({'StackName' => stack.name}).body['Stacks'][0]
|
response = cloud_formation.describe_stacks({'StackName' => stack.name}).body['Stacks']
|
||||||
|
# somewhy it sometimes returns blank results
|
||||||
|
response.detect do |t|
|
||||||
|
t.has_key?('StackName')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def stack_resources(stack)
|
def stack_resources(stack)
|
||||||
|
|||||||
@ -4,6 +4,10 @@ require "db/mongo/models/stack/stack_factory"
|
|||||||
require "db/mongo/models/project"
|
require "db/mongo/models/project"
|
||||||
require "db/mongo/models/report"
|
require "db/mongo/models/report"
|
||||||
|
|
||||||
|
class StackCreatingError < StandardError; end
|
||||||
|
class BootstrapingStackServerError < StandardError; end
|
||||||
|
class DeployingStackServerError < StandardError; end
|
||||||
|
|
||||||
class StackBootstrapWorker < Worker
|
class StackBootstrapWorker < Worker
|
||||||
include StackCommands
|
include StackCommands
|
||||||
|
|
||||||
@ -12,31 +16,98 @@ class StackBootstrapWorker < Worker
|
|||||||
stack_attrs = options.fetch('stack_attributes')
|
stack_attrs = options.fetch('stack_attributes')
|
||||||
|
|
||||||
call(provider_name) do |provider, out, file|
|
call(provider_name) do |provider, out, file|
|
||||||
|
@out = out
|
||||||
without_bootstrap = stack_attrs.delete('without_bootstrap')
|
without_bootstrap = stack_attrs.delete('without_bootstrap')
|
||||||
report = save_report(file, stack_attrs)
|
report = save_report(file, stack_attrs)
|
||||||
|
|
||||||
stack = Devops::Model::StackFactory.create(provider_name, stack_attrs, out)
|
begin
|
||||||
mongo.stack_insert(stack)
|
stack = create_stack(provider_name, stack_attrs)
|
||||||
|
rescue StackCreatingError
|
||||||
operation_result = sync_stack_proc.call(out, stack, mongo)
|
return 1
|
||||||
if operation_result == 0
|
end
|
||||||
out << "\nStack '#{stack.name}' has been created\n"
|
|
||||||
out.flush
|
begin
|
||||||
servers = persist_stack_servers!(stack, provider)
|
servers = persist_stack_servers!(stack, provider)
|
||||||
bootstrap_servers(servers, out, report) unless without_bootstrap
|
bootstrap_servers!(servers, report) unless without_bootstrap
|
||||||
|
rescue BootstrapingStackServerError
|
||||||
|
@out.puts "An error occured during bootstraping stack servers. Initiating stack rollback.\n\n"
|
||||||
|
rollback_stack!(stack)
|
||||||
|
1
|
||||||
|
rescue DeployingStackServerError => e
|
||||||
|
@out.puts "Stack was launched, but an error occured during deploying stack servers."
|
||||||
|
@out.puts "You can redeploy stack after fixing the error.\n\n"
|
||||||
|
1
|
||||||
|
rescue StandardError => e
|
||||||
|
@out.puts "An error occured. Initiating stack rollback.\n\n"
|
||||||
|
rollback_stack!(stack)
|
||||||
|
raise e
|
||||||
end
|
end
|
||||||
operation_result
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def bootstrap_servers(servers, out, report)
|
def rollback_stack!(stack)
|
||||||
out << "\n"
|
@out.puts "\nStart rollback of a stack"
|
||||||
servers.map do |server|
|
stack.delete_stack_in_cloud!
|
||||||
executor = Devops::Executor::ServerExecutor.new(server, out)
|
Devops::Db.connector.stack_servers_delete(stack.name)
|
||||||
|
Devops::Db.connector.stack_delete(stack.id)
|
||||||
|
@out.puts "\nRollback has been completed"
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_stack(provider_name, stack_attrs)
|
||||||
|
stack = Devops::Model::StackFactory.create(provider_name, stack_attrs, @out)
|
||||||
|
mongo.stack_insert(stack)
|
||||||
|
operation_result = sync_stack_proc.call(@out, stack, mongo)
|
||||||
|
|
||||||
|
if operation_result == 0
|
||||||
|
@out.puts "\nStack '#{stack.name}' has been created"
|
||||||
|
@out.flush
|
||||||
|
stack
|
||||||
|
else
|
||||||
|
human_readable_code = StackCommands.result_codes.key(operation_result)
|
||||||
|
@out.puts "An error ocurred during stack creating"
|
||||||
|
@out.puts "Stack creating operation result was #{human_readable_code}"
|
||||||
|
raise StackCreatingError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def bootstrap_servers!(servers, report)
|
||||||
|
@out << "\nStart bootstraping stack servers\n"
|
||||||
|
bootstraping_results = {}
|
||||||
|
servers.each do |server|
|
||||||
|
executor = Devops::Executor::ServerExecutor.new(server, @out)
|
||||||
executor.report = report
|
executor.report = report
|
||||||
executor.two_phase_bootstrap({})
|
bootstraping_results[server.chef_node_name] = executor.two_phase_bootstrap({})
|
||||||
|
end
|
||||||
|
check_bootstrap_results!(bootstraping_results)
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_bootstrap_results!(results)
|
||||||
|
if results.values.all?(&:zero?)
|
||||||
|
# everything is OK
|
||||||
|
@out.puts "Stack servers have been bootstraped"
|
||||||
|
@out.flush
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
results.each do |chef_node_name, code|
|
||||||
|
human_readable_code = Devops::Executor::ServerExecutor.result_codes.key(code)
|
||||||
|
@out.puts "Operation result for #{chef_node_name}: #{human_readable_code}"
|
||||||
|
end
|
||||||
|
|
||||||
|
if errors_in_bootstrapping_present?(results)
|
||||||
|
# An error occured during servers bootsraping, so rollback stack
|
||||||
|
raise BootstrapingStackServerError
|
||||||
|
else
|
||||||
|
# An error occured during servers deploying, rollback isn't needed
|
||||||
|
raise DeployingStackServerError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def errors_in_bootstrapping_present?(results)
|
||||||
|
results.values.any? do |result|
|
||||||
|
result == Devops::Executor::ServerExecutor.result_code(:server_bootstrap_fail)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -54,10 +125,12 @@ class StackBootstrapWorker < Worker
|
|||||||
end
|
end
|
||||||
|
|
||||||
def persist_stack_servers!(stack, provider)
|
def persist_stack_servers!(stack, provider)
|
||||||
|
@out.puts "Start syncing stack servers with CID"
|
||||||
|
@out.flush
|
||||||
project = mongo.project(stack.project)
|
project = mongo.project(stack.project)
|
||||||
deploy_env = project.deploy_env(stack.deploy_env)
|
deploy_env = project.deploy_env(stack.deploy_env)
|
||||||
|
|
||||||
provider.stack_servers(stack).map do |extended_info|
|
servers = provider.stack_servers(stack).map do |extended_info|
|
||||||
server_attrs = {
|
server_attrs = {
|
||||||
'provider' => provider.name,
|
'provider' => provider.name,
|
||||||
'project' => project.id,
|
'project' => project.id,
|
||||||
@ -78,6 +151,9 @@ class StackBootstrapWorker < Worker
|
|||||||
# server.chef_node_name = provider.create_default_chef_node_name(server)
|
# server.chef_node_name = provider.create_default_chef_node_name(server)
|
||||||
server
|
server
|
||||||
end
|
end
|
||||||
|
@out.puts "Stack servers have been synced with CID"
|
||||||
|
@out.flush
|
||||||
|
servers
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user