stack deploy

This commit is contained in:
amartynov 2015-08-14 13:28:03 +03:00
parent 511f689414
commit e24aa8765b
8 changed files with 155 additions and 28 deletions

View File

@ -85,9 +85,9 @@ module Devops
p = Devops::Db.connector.check_project_auth(body["project"], body["deploy_env"], user) p = Devops::Db.connector.check_project_auth(body["project"], body["deploy_env"], user)
env = p.deploy_env(body["deploy_env"]) env = p.deploy_env(body["deploy_env"])
provider = ::Provider::ProviderFactory.get(env.provider) provider = env.provider_instance
server_name = body["name"] server_name = body["name"]
check_chef_node_name(server_name, provider) unless server_name.nil? check_chef_node_name(server_name, provider, KnifeFactory.instance) unless server_name.nil?
groups = body["groups"] groups = body["groups"]
unless groups.nil? unless groups.nil?
buf = groups - provider.groups.keys buf = groups - provider.groups.keys
@ -95,15 +95,13 @@ module Devops
end end
yield p, env, user, body yield p, env, user, body
#Server.extract_servers(provider, p, env, body, user)
end end
def pause_server node_name def pause_server node_name
s = Server.get_server_by_key(node_name, parser.instance_key) s = Server.get_server_by_key(node_name, parser.instance_key)
## Authorization ## Authorization
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
provider = ::Provider::ProviderFactory.get(s.provider) provider = s.provider_instance
r = provider.pause_server s r = provider.pause_server s
if r.nil? if r.nil?
"Server with instance ID '#{s.id}' and node name '#{node_name}' is paused" "Server with instance ID '#{s.id}' and node name '#{node_name}' is paused"
@ -116,7 +114,7 @@ module Devops
s = Server.get_server_by_key(node_name, parser.instance_key) s = Server.get_server_by_key(node_name, parser.instance_key)
## Authorization ## Authorization
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
provider = ::Provider::ProviderFactory.get(s.provider) provider = s.provider_instance
r = provider.unpause_server s r = provider.unpause_server s
if r.nil? if r.nil?
"Server with instance ID '#{s.id}' and node name '#{node_name}' is unpaused" "Server with instance ID '#{s.id}' and node name '#{node_name}' is unpaused"
@ -201,9 +199,9 @@ module Devops
p = Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user p = Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user
d = p.deploy_env(s.deploy_env) d = p.deploy_env(s.deploy_env)
provider = ::Provider::ProviderFactory.get(s.provider) provider = s.provider_instance
check_chef_node_name(name, provider) unless name.nil? check_chef_node_name(name, provider, KnifeFactory.instance) unless name.nil?
unless t.nil? unless t.nil?
templates = get_templates templates = get_templates
halt_response("Invalid bootstrap template '#{t}', available values: #{templates.join(", ")}", 400) unless templates.include?(t) halt_response("Invalid bootstrap template '#{t}', available values: #{templates.join(", ")}", 400) unless templates.include?(t)
@ -249,16 +247,14 @@ module Devops
def prepare_tags node_name def prepare_tags node_name
s = get_server_by_key(node_name, parser.instance_key) s = get_server_by_key(node_name, parser.instance_key)
user = parser.current_user 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, user
provider = ::Provider::ProviderFactory.get(s.provider) provider = ::Provider::ProviderFactory.get(s.provider)
yield s.id, provider yield s.id, provider
end end
def set_run_list node_name def set_run_list node_name
s = get_server_by_key(node_name, parser.instance_key) s = get_server_by_key(node_name, parser.instance_key)
user = parser.current_user 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, user
Devops::Db.connector.set_server_run_list(s.id, parser.run_list) Devops::Db.connector.set_server_run_list(s.id, parser.run_list)
end end
@ -267,18 +263,17 @@ module Devops
key == "instance" ? mongo.server_by_instance_id(id) : mongo.server_by_chef_node_name(id) key == "instance" ? mongo.server_by_instance_id(id) : mongo.server_by_chef_node_name(id)
end end
def check_chef_node_name name, provider def check_chef_node_name name, provider, knife
mongo = Devops::Db.connector Devops::Db.connector.server_by_chef_node_name(name)
mongo.server_by_chef_node_name name raise InvalidRecord.new("Server with name '#{name}' already exist")
halt(400, "Server with name '#{name}' already exist")
rescue RecordNotFound => e rescue RecordNotFound => e
# server not found - OK # server not found - OK
s = provider.servers.detect {|s| s["name"] == name} s = provider.servers.detect {|s| s["name"] == name}
halt(400, "#{provider.name} node with name '#{name}' already exist") unless s.nil? raise InvalidRecord.new("#{provider.name} node with name '#{name}' already exist") unless s.nil?
s = KnifeFactory.instance.chef_node_list.detect {|n| n == name} s = knife.chef_node_list.detect {|n| n == name}
halt(400, "Chef node with name '#{name}' already exist") unless s.nil? raise InvalidRecord.new("Chef node with name '#{name}' already exist") unless s.nil?
s = KnifeFactory.instance.chef_client_list.detect {|c| c == name} s = knife.chef_client_list.detect {|c| c == name}
halt(400, "Chef client with name '#{name}' already exist") unless s.nil? raise InvalidRecord.new("Chef client with name '#{name}' already exist") unless s.nil?
end end
end end

View File

@ -1,3 +1,4 @@
require "lib/executors/server_executor"
require 'db/mongo/models/stack/stack_factory' require 'db/mongo/models/stack/stack_factory'
require "app/api2/parsers/stack" require "app/api2/parsers/stack"
require_relative "request_handler" require_relative "request_handler"
@ -77,6 +78,86 @@ module Devops
def set_run_list id def set_run_list id
Devops::Db.connector.set_stack_run_list(id, parser.run_list) Devops::Db.connector.set_stack_run_list(id, parser.run_list)
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)
body = parser.deploy
names = body["names"]
tags = body["tags"] || []
dir = DevopsConfig.config[:report_dir_v2]
files = []
jid = nil
uri = URI.parse(parser.request.url)
servers = Devops::Db.connector.stack_servers(stack_id, true)
deploy_info = project.deploy_info(stack.deploy_env, nil)
servers.each do |s|
begin
jid = DeployWorker.perform_async(dir, s.to_hash, tags, owner, DevopsConfig.config, deploy_info)
Worker.set_status jid, Worker::STATUS::IN_QUEUE
DevopsLogger.logger.info "Job '#{jid}' has been queued"
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}"
file = File.jon(dir, jid)
File.open(file, "w") do |out|
#unless attributes.nil?
# out << "Report attributes: #{attributes.inspect}\n"
#end
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
# "attributes" => attributes
}
Devops::Db.connector.save_report(Report.new(o))
end
uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid
files.push uri.to_s
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
end end
end end
end end

View File

@ -16,13 +16,13 @@ module Devops
end end
def tags node_name def tags node_name
KnifeCommands.tags_list(node_name) KnifeFactory.instance.tags_list(node_name)
end end
def set_tags node_name def set_tags node_name
tags = parser.tags tags = parser.tags
tagsStr = tags.join(" ") tagsStr = tags.join(" ")
cmd = KnifeCommands.tags_create(node_name, tagsStr) cmd = KnifeFactory.instance.tags_create(node_name, tagsStr)
halt_response("Cannot add tags #{tagsStr} to server #{node_name}", 500) unless cmd[1] halt_response("Cannot add tags #{tagsStr} to server #{node_name}", 500) unless cmd[1]
tags tags
end end
@ -30,7 +30,7 @@ module Devops
def unset_tags node_name def unset_tags node_name
tags = parser.tags tags = parser.tags
tagsStr = tags.join(" ") tagsStr = tags.join(" ")
cmd = KnifeCommands.tags_delete(node_name, tagsStr) cmd = KnifeFactory.instance.tags_delete(node_name, tagsStr)
halt_response("Cannot delete tags #{tagsStr} from server #{node_name}: #{cmd[0]}", 500) unless cmd[1] halt_response("Cannot delete tags #{tagsStr} from server #{node_name}: #{cmd[0]}", 500) unless cmd[1]
tags tags
end end

View File

@ -21,6 +21,13 @@ module Devops
list list
end end
def deploy
@body ||= create_object_from_json_body
names = check_array(@body["names"], "Parameter 'names' should be a not empty array of strings", String, true)
tags = check_array(@body["tags"], "Parameter 'tags' should be an array of strings", String, true)
@body
end
end end
end end
end end

View File

@ -72,6 +72,39 @@ module Devops
create_response(info) create_response(info)
end end
# Deploy stack instances
#
# * *Request*
# - method : POST
# - headers :
# - Accept: application/json
# - Content-Type: application/json
# - body :
# {
# "tags" : ["tag1", "tag2"]
# }
#
# * *Returns* :
# 200 - Updated
app.patch_with_headers "/stack/:id/deploy", :headers => [:accept, :content_type] do |id|
check_privileges("stack", "x")
if request["X-Stream"]
stream() do |out|
status = []
begin
status = Devops::API2_0::Handler::Stack.new(request).deploy_stream(id, out)
out << create_status(status)
rescue IOError => e
logger.error e.message
break
end
end # stream
else
files = Devops::API2_0::Handler::Stack.new(request).deploy(id)
sleep 1
json files
end
end
puts "Stack routes initialized" puts "Stack routes initialized"
end end

View File

@ -29,8 +29,10 @@ module Connectors
servers_find(q, f) servers_find(q, f)
end end
def stack_servers(stack_id) def stack_servers(stack_id, reserver=nil, options={})
list('stack' => stack_id) q = {'stack' => stack_id}
q['reserved_by'] = {'$ne' => nil} unless reserved.nil?
list(q, options)
end end
def servers_by_names(names) def servers_by_names(names)
@ -72,7 +74,7 @@ module Connectors
end end
def set_server_run_list(id, run_list) def set_server_run_list(id, run_list)
@collection.update({"_id" => id}, {"$set" => {"run_list" => run_list}}) collection.update({"_id" => id}, {"$set" => {"run_list" => run_list}})
end end
private private

View File

@ -134,7 +134,15 @@ module Devops
end end
def deploy_info deploy_env, build_number def deploy_info deploy_env, build_number
{} {
"run_list" => deploy_env.run_list,
"project" => self.id,
"project_info" => {
"project" => self.id,
"deploy_env" => deploy_env.identifier,
"deployers" => deploy_env.users
}
}
end end
def to_hash_without_id def to_hash_without_id

View File

@ -10,6 +10,7 @@ module Devops
include ProjectType include ProjectType
def prepare project def prepare project
#TODO: without creating roles
#project.before_create create_roles #project.before_create create_roles
end end