request parsers

This commit is contained in:
Anton Martynov 2015-07-30 15:37:43 +03:00
parent d053ffea0f
commit 2f67f18bc3
62 changed files with 1035 additions and 573 deletions

View File

@ -1,9 +1,13 @@
require "commands/bootstrap_templates" require "commands/bootstrap_templates"
require "app/api2/parsers/bootstrap_template"
require_relative "request_handler"
module Devops module Devops
module API2_0 module API2_0
module Handler module Handler
class BootstrapTemplates class BootstrapTemplates < RequestHandler
set_parser Devops::API2_0::Parser::BootstrapTemplateParser
include BootstrapTemplatesCommands include BootstrapTemplatesCommands

View File

@ -1,51 +1,100 @@
require "commands/deploy" require "commands/deploy"
require "commands/status" require "commands/status"
require "workers/deploy_worker" require "workers/deploy_worker"
require "exceptions/deploy_info_error"
require "app/api2/parsers/deploy"
require_relative "request_handler"
module Devops module Devops
module API2_0 module API2_0
module Handler module Handler
class Deploy class Deploy < RequestHandler
extend DeployCommands extend DeployCommands
extend StatusCommands extend StatusCommands
def initialize req, params set_parser Devops::API2_0::Parser::DeployParser
@request = req
@params = params
end
def deploy names, tags def deploy
body = parser.deploy
names = body["names"]
tags = body["tags"] || []
dir = DevopsConfig.config[:report_dir_v2] dir = DevopsConfig.config[:report_dir_v2]
files = [] files = []
uri = URI.parse(@request.url) jid = nil
uri = URI.parse(parser.request.url)
owner = parser.current_user
@deploy_info_buf = {}
servers(names).each do |s| servers(names).each do |s|
project = begin project = begin
Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER'] Devops::Db.connector.check_project_auth s.project, s.deploy_env, owner
rescue InvalidPrivileges, RecordNotFound => e rescue InvalidPrivileges, RecordNotFound => e
DevopsLogger.logger.warn e.message
next next
end end
jid = DeployWorker.perform_async(dir, s.to_hash, tags, @request.env['REMOTE_USER'], DevopsConfig.config) begin
deploy_info = create_deploy_info(s, project, body["build_number"])
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
files.push jid files.push jid
end end
files files
end end
def deploy_stream out, names, tags def deploy_stream out
body = parser.deploy
names = body["names"]
tags = body["tags"] || []
status = [] status = []
owner = parser.current_user
@deploy_info_buf = {}
servers(names).each do |s| servers(names).each do |s|
project = begin project = begin
Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER'] Devops::Db.connector.check_project_auth s.project, s.deploy_env, owner
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
res = deploy_server_proc.call(out, s, tags) begin
deploy_info = create_deploy_info(s, project, body["build_number"])
res = deploy_server_proc.call(out, s, tags, deploy_info)
status.push(res) 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
out << create_status(status) end
status
rescue RecordNotFound => e rescue RecordNotFound => e
out << e.message out << e.message
[-10]
end end
def servers names def servers names
@ -54,6 +103,15 @@ module Devops
servers.sort_by!{|s| names.index(s.chef_node_name)} servers.sort_by!{|s| names.index(s.chef_node_name)}
servers servers
end end
def create_deploy_info server, project, build_number
buf_key = "#{server.project}_#{server.deploy_env}"
deploy_info = if @deploy_info_buf.key?(buf_key)
@deploy_info_buf[buf_key]
else
@deploy_info_buf[buf_key] = project.deploy_info(server.deploy_env, build_number)
end
end
end end
end end
end end

View File

@ -1,3 +1,4 @@
require "app/api2/parsers/filter"
require_relative "request_handler" require_relative "request_handler"
module Devops module Devops
@ -5,16 +6,18 @@ module Devops
module Handler module Handler
class Filter < RequestHandler class Filter < RequestHandler
set_parser Devops::API2_0::Parser::FilterParser
def available_images provider def available_images provider
Devops::Db.connector.available_images(provider) Devops::Db.connector.available_images(provider)
end end
def add_images images, provider def add_images provider
Devops::Db.connector.add_available_images(images, provider) Devops::Db.connector.add_available_images(parser.images, provider)
end end
def delete_images images, provider def delete_images provider
Devops::Db.connector.delete_available_images(images, provider) Devops::Db.connector.delete_available_images(parser.images, provider)
end end
end end

View File

@ -6,13 +6,8 @@ module Devops
module Handler module Handler
class Flavor < RequestHandler class Flavor < RequestHandler
def initialize request, params def flavors provider
@provider = params[:provider] ::Provider::ProviderFactory.get(provider).flavors
end
def flavors
p = ::Provider::ProviderFactory.get @provider
p.flavors
end end
end end

View File

@ -1,17 +1,14 @@
require "providers/provider_factory" require "providers/provider_factory"
require_relative "request_handler"
module Devops module Devops
module API2_0 module API2_0
module Handler module Handler
class Group class Group < RequestHandler
def initialize provider # TODO: vpc support for ec2
@provider = provider def groups provider
end ::Provider::ProviderFactory.get(provider).groups()#params
def groups params
p = ::Provider::ProviderFactory.get @provider
p.groups(params)
end end
end end
end end

View File

@ -1,5 +1,6 @@
require "providers/provider_factory" require "providers/provider_factory"
require "commands/image" require "commands/image"
require "app/api2/parsers/image"
require_relative "request_handler" require_relative "request_handler"
module Devops module Devops
@ -7,10 +8,12 @@ module Devops
module Handler module Handler
class Image < RequestHandler class Image < RequestHandler
set_parser Devops::API2_0::Parser::ImageParser
extend ImageCommands extend ImageCommands
def images provider def images
Devops::Db.connector.images(provider) Devops::Db.connector.images(parser.images)
end end
def provider_images provider def provider_images provider
@ -21,13 +24,13 @@ module Devops
Devops::Db.connector.image(id) Devops::Db.connector.image(id)
end end
def create_image image def create_image
Devops::Db.connector.image_insert Devops::Model::Image.new(image) Devops::Db.connector.image_insert parser.image
end end
def update_image id, image def update_image id
Devops::Db.connector.image id Devops::Db.connector.image id
obj = Devops::Model::Image.new(image) obj = parser.image
obj.id = id obj.id = id
Devops::Db.connector.image_update obj Devops::Db.connector.image_update obj
end end

View File

@ -1,17 +1,24 @@
require "db/mongo/models/key" require "db/mongo/models/key"
require "fileutils" require "fileutils"
require "app/api2/parsers/key"
require_relative "request_handler"
module Devops module Devops
module API2_0 module API2_0
module Handler module Handler
class Key class Key < RequestHandler
set_parser Devops::API2_0::Parser::KeyParser
def keys def keys
keys = Devops::Db.connector.keys.map {|i| i.to_hash} Devops::Db.connector.keys({}, {path: false})
keys.each {|k| k.delete("path")} # We should not return path to the key
end end
def create body, file_name def create
body = parser.create
fname = body["file_name"]
file_name = File.join(settings.keys_dir, fname)
raise InvalidRecord.new("File '#{fname}' already exist") if File.exists?(file_name)
File.open(file_name, "w") do |f| File.open(file_name, "w") do |f|
f.write(body["content"]) f.write(body["content"])
f.chmod(0400) f.chmod(0400)

View File

@ -3,6 +3,7 @@ require "commands/status"
require "commands/server" require "commands/server"
require "db/mongo/models/project" require "db/mongo/models/project"
require "workers/project_test_worker" require "workers/project_test_worker"
require "app/api2/parsers/project"
require_relative "../helpers/version_2.rb" require_relative "../helpers/version_2.rb"
require_relative "request_handler" require_relative "request_handler"
@ -10,6 +11,9 @@ module Devops
module API2_0 module API2_0
module Handler module Handler
class Project < RequestHandler class Project < RequestHandler
set_parser Devops::API2_0::Parser::ProjectParser
include Devops::API2_0::Helpers include Devops::API2_0::Helpers
extend DeployCommands extend DeployCommands
@ -34,44 +38,46 @@ module Devops
def project_servers id def project_servers id
# check if project exists # check if project exists
Devops::Db.connector.project(id) Devops::Db.connector.project(id)
Devops::Db.connector.servers(id, @params[:deploy_env]) Devops::Db.connector.servers(id, parser.project_servers)
end end
def project_stacks id def project_stacks id
# check if project exists # check if project exists
Devops::Db.connector.project(id) Devops::Db.connector.project(id)
options = {project: @params[:project]} options = {project: id}
options[:deploy_env] = @params[:deploy_env] if @params[:deploy_env] deploy_env = parser.project_stacks
options[:deploy_env] = deploy_env if deploy_env
Devops::Db.connector.stacks(options) Devops::Db.connector.stacks(options)
end end
# TODO: multi project # TODO: multi project
def create_project body def create_project
p = Devops::Model::Project.new(body) p = parser.create_project
raise InvalidRecord.new("Project '#{p.id}' already exist") if Devops::Db.connector.is_project_exists?(p) raise InvalidRecord.new("Project '#{p.id}' already exist") if Devops::Db.connector.is_project_exists?(p)
p.add_authorized_user [@request.env['REMOTE_USER']] p.add_authorized_user [parser.current_user]
p.create p.create
if p.multi? if p.multi?
"Project '#{p.id}' with type 'multi' created" "Project '#{p.id}' with type 'multi' created"
else else
roles = create_roles p.id, p.deploy_envs, DevopsLogger.logger roles = create_roles p.id, p.deploy_envs
"Project '#{p.id}' created. " + create_roles_response(roles) "Project '#{p.id}' created. " + create_roles_response(roles)
end end
end end
# TODO: multi project # TODO: multi project
def update_project id, body def update_project id
project = Devops::Model::Project.new(body) project = parser.update
project.id = id project.id = id
old_project = Devops::Db.connector.project id old_project = Devops::Db.connector.project id
Devops::Db.connector.project_update project Devops::Db.connector.project_update project
roles = create_new_roles(old_project, project, DevopsLogger.logger) roles = create_new_roles(old_project, project)
create_roles_response(roles) create_roles_response(roles)
end end
# TODO: multi project # TODO: multi project
def update_project_users id, deploy_env, users def update_project_users id
deploy_env, users = parser.project_users
project = Devops::Db.connector.project(id) project = Devops::Db.connector.project(id)
dbusers = Devops::Db.connector.users(users).map{|u| u.id} dbusers = Devops::Db.connector.users(users).map{|u| u.id}
buf = dbusers - users buf = dbusers - users
@ -83,7 +89,8 @@ module Devops
end end
# TODO: multi project # TODO: multi project
def delete_project_users id, deploy_env, users def delete_project_users id
deploy_env, users = parser.project_users
project = Devops::Db.connector.project(id) project = Devops::Db.connector.project(id)
project.remove_authorized_user users, deploy_env project.remove_authorized_user users, deploy_env
Devops::Db.connector.project_update project Devops::Db.connector.project_update project
@ -91,7 +98,8 @@ module Devops
end end
# TODO: multi project # TODO: multi project
def set_project_env_run_list id, deploy_env, list def set_project_env_run_list id, deploy_env
list = parser.run_list
project = Devops::Db.connector.project(id) project = Devops::Db.connector.project(id)
env = project.deploy_env deploy_env env = project.deploy_env deploy_env
env.run_list = list env.run_list = list
@ -99,7 +107,8 @@ module Devops
"Updated environment '#{env.identifier}' with run_list '#{env.run_list.inspect}' in project '#{project.id}'" "Updated environment '#{env.identifier}' with run_list '#{env.run_list.inspect}' in project '#{project.id}'"
end end
def delete_project id, deploy_env def delete_project id
deploy_env = parser.delete
servers = Devops::Db.connector.servers id servers = Devops::Db.connector.servers id
raise DependencyError.new "Deleting #{id} is forbidden: Project has servers" if !servers.empty? raise DependencyError.new "Deleting #{id} is forbidden: Project has servers" if !servers.empty?
project = Devops::Db.connector.project(id) project = Devops::Db.connector.project(id)
@ -113,7 +122,8 @@ module Devops
end end
end end
def deploy_project_stream out, id, deploy_env, servers, body def deploy_project_stream out, id
deploy_env, servers = parser.deploy
keys = {} keys = {}
dbserver = servers(id, deploy_env, servers) dbserver = servers(id, deploy_env, servers)
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")
@ -135,7 +145,8 @@ module Devops
status status
end end
def deploy_project id, deploy_env, servers, body def deploy_project id
deploy_env, servers = parser.deploy
dir = DevopsConfig[:report_dir_v2] dir = DevopsConfig[:report_dir_v2]
files = [] files = []
uri = URI.parse(request.url) uri = URI.parse(request.url)
@ -173,7 +184,7 @@ module Devops
def test_project id, deploy_env def test_project id, deploy_env
project = Devops::Db.connector.project(id) project = Devops::Db.connector.project(id)
env = project.deploy_env deploy_env env = project.deploy_env deploy_env
#logger.info "Test project '#{project.id}' and environment '#{env.identifier}'" DevopsLogger.logger.info "Test project '#{project.id}' and environment '#{env.identifier}'"
if env.provider == ::Provider::Static::PROVIDER if env.provider == ::Provider::Static::PROVIDER
msg = "Can not test environment with provider '#{::Provider::Static::PROVIDER}'" msg = "Can not test environment with provider '#{::Provider::Static::PROVIDER}'"
Logger.warn msg Logger.warn msg
@ -189,13 +200,13 @@ module Devops
} }
jid = ProjectTestWorker.perform_async(dir, p, DevopsConfig.config) jid = ProjectTestWorker.perform_async(dir, p, DevopsConfig.config)
Worker.set_status jid, Worker::STATUS::IN_QUEUE Worker.set_status jid, Worker::STATUS::IN_QUEUE
#logger.info "Job '#{jid}' has been created" DevopsLogger.logger.info "Job '#{jid}' has been created"
uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid
sleep 1 sleep 1
return [uri.to_s] return [uri.to_s]
end end
def create_roles project_id, envs, logger def create_roles project_id, envs
all_roles = KnifeCommands.roles all_roles = KnifeCommands.roles
return " Can't get roles list" if all_roles.nil? return " Can't get roles list" if all_roles.nil?
roles = {:new => [], :error => [], :exist => []} roles = {:new => [], :error => [], :exist => []}
@ -207,21 +218,21 @@ module Devops
else else
KnifeCommands.create_role role_name, project_id, e.identifier KnifeCommands.create_role role_name, project_id, e.identifier
roles[:new].push role_name roles[:new].push role_name
logger.info "Role '#{role_name}' created" DevopsLogger.logger.info "Role '#{role_name}' created"
end end
rescue => er rescue => er
roles[:error].push role_name roles[:error].push role_name
logger.error "Role '#{role_name}' can not be created: #{er.message}" DevopsLogger.logger.error "Role '#{role_name}' can not be created: #{er.message}"
end end
end end
roles roles
end end
def create_new_roles old_project, new_project, logger def create_new_roles old_project, new_project
old_project.deploy_envs.each do |e| old_project.deploy_envs.each do |e|
new_project.remove_env(e.identifier) new_project.remove_env(e.identifier)
end end
create_roles new_project.id, new_project.deploy_envs, logger create_roles new_project.id, new_project.deploy_envs
end end
def create_roles_response roles def create_roles_response roles

View File

@ -5,19 +5,16 @@ module Devops
module Handler module Handler
class Report < RequestHandler class Report < RequestHandler
def initialize request, params
@params = params
end
def options def options
params = @request.params
options = {} options = {}
["project", "deploy_env", "type", "created_by", "date_from", "date_to", "sort", "status", "chef_node_name", "max_number"].each do |k| ["project", "deploy_env", "type", "created_by", "date_from", "date_to", "sort", "status", "chef_node_name", "max_number"].each do |k|
options[k] = @params[k] unless @params[k].nil? options[k] = params[k] unless params[k].nil?
end
attributes_keys = @params.keys.select{|k| k =~ /attributes\.*/}
attributes_keys.each do |ak|
options[ak] = @params[ak]
end end
#attributes_keys = params.keys.select{|k| k =~ /attributes\.*/}
#attributes_keys.each do |ak|
# options[ak] = params[ak]
#end
options options
end end

View File

@ -2,10 +2,19 @@ module Devops
module API2_0 module API2_0
module Handler module Handler
class RequestHandler class RequestHandler
def initialize request, params
class << self
def set_parser parser
define_method("parser") do
@request_parser ||= parser.new(@request)
end
end
end
def initialize request
@request = request @request = request
@params = params end
end
end end
end end
end end

View File

@ -1,6 +1,7 @@
require "providers/provider_factory" require "providers/provider_factory"
require "fileutils" require "fileutils"
require "commands/status" require "commands/status"
require "app/api2/parsers/script"
require_relative "request_handler" require_relative "request_handler"
module Devops module Devops
@ -8,13 +9,16 @@ module Devops
module Handler module Handler
class Script < RequestHandler class Script < RequestHandler
set_parser Devops::API2_0::Parser::ScriptParser
def scripts def scripts
res = [] res = []
Dir.foreach(DevopsConfig.config[:scripts_dir]) {|f| res.push(f) unless f.start_with?(".")} Dir.foreach(DevopsConfig.config[:scripts_dir]) {|f| res.push(f) unless f.start_with?(".")}
end end
def execute_command out, cmd, node_name def execute_command out, node_name
user = @request.env['REMOTE_USER'] cmd = parse.execute_command
user = parser.current_user
s = ::Devops::Db.connector.server_by_chef_node_name node_name s = ::Devops::Db.connector.server_by_chef_node_name node_name
::Devops::Db.connector.check_project_auth s.project, s.deploy_env, user ::Devops::Db.connector.check_project_auth s.project, s.deploy_env, user
cert = ::Devops::Db.connector.key s.key cert = ::Devops::Db.connector.key s.key
@ -30,8 +34,9 @@ module Devops
out << "\nDone" out << "\nDone"
end end
def run_script out, file_name, nodes, script_params def run_script out, script_name
file = File.join(DevopsConfig.config[:scripts_dir], file_name) nodes, script_params = parser.run_script
file = File.join(DevopsConfig.config[:scripts_dir], script_name)
unless File.exists?(file) unless File.exists?(file)
out << "File '#{file_name}' does not exist\n" out << "File '#{file_name}' does not exist\n"
return return
@ -76,18 +81,18 @@ module Devops
status.push 3 status.push 3
end end
end end
out << create_status(status) status
end end
def create_script file_name def create_script file_name
file = File.join(Devops::Api2.settings.scripts_dir, file_name) file = File.join(Devops::Api2.settings.scripts_dir, file_name)
raise RecordNotFound.new("File '#{file_name}' already exist") if File.exists?(file) raise RecordNotFound.new("File '#{file_name}' already exist") if File.exists?(file)
File.open(file, "w") {|f| f.write(@request.body.read)} File.open(file, "w") {|f| f.write(parser.create_script)}
end end
def delete_script file_name def delete_script file_name
file = File.join(Devops::Api2.settings.scripts_dir, file_name) file = File.join(Devops::Api2.settings.scripts_dir, file_name)
raise RecordNotFound.new("File '#{file_name}' does not exist", 404) unless File.exists?(file) raise RecordNotFound.new("File '#{file_name}' does not exist") unless File.exists?(file)
FileUtils.rm(file) FileUtils.rm(file)
end end

View File

@ -12,11 +12,15 @@ require "db/mongo/models/server"
require "workers/create_server_worker" require "workers/create_server_worker"
require "workers/bootstrap_worker" require "workers/bootstrap_worker"
require "app/api2/parsers/server"
require_relative "request_handler"
module Devops module Devops
module API2_0 module API2_0
module Handler module Handler
class Server class Server < RequestHandler
set_parser Devops::API2_0::Parser::ServerParser
extend StatusCommands extend StatusCommands
extend ServerCommands extend ServerCommands
@ -24,7 +28,8 @@ module Devops
scheduler = Rufus::Scheduler.new scheduler = Rufus::Scheduler.new
def servers fields, reserved def servers
fields, reserved = parser.servers
Devops::DB.connector.servers(nil, nil, nil, reserved, fields).map {|s| s.to_hash} Devops::DB.connector.servers(nil, nil, nil, reserved, fields).map {|s| s.to_hash}
end end
@ -37,14 +42,14 @@ module Devops
end end
def server id def server id
get_server_by_key(id, @params[:key]) get_server_by_key(id, parse.server)
end end
def delete id, key def delete id
s = get_server_by_key(params[:id], key) s = get_server_by_key(id, parser.instance_key)
### Authorization ### Authorization
Devops::Db.connector.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user
delete_server(s, Devops::Db.connector, logger) delete_server(s, Devops::Db.connector, DevopsLogger.logger)
end end
def create_server_stream out, body def create_server_stream out, body
@ -56,14 +61,14 @@ module Devops
status status
end end
def create_server body def create_server
dir = DevopsConfig[:report_dir_v2] dir = DevopsConfig[:report_dir_v2]
files = [] files = []
uri = URI.parse(request.url) uri = URI.parse(request.url)
prepare_create_server(body).each do |s| prepare_create_server.each do |s|
h = s.to_hash h = s.to_hash
h["options"] = s.options h["options"] = s.options
jid = CreateServerWorker.perform_async(dir, env.provider, h, @request.env['REMOTE_USER'], DevopsConfig.config) jid = CreateServerWorker.perform_async(dir, env.provider, h, parser.current_user, DevopsConfig.config)
Worker.set_status jid, Worker::STATUS::IN_QUEUE Worker.set_status jid, Worker::STATUS::IN_QUEUE
#logger.info "Job '#{jid}' has been started" #logger.info "Job '#{jid}' has been started"
uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid
@ -73,8 +78,9 @@ module Devops
files files
end end
def prepare_create_server body def prepare_create_server
user = @request.env['REMOTE_USER'] body = parser.create
user = parser.current_user
key_name = body["key"] key_name = body["key"]
new_key = Devops::Db.connector.key(key_name) unless key_name.nil? new_key = Devops::Db.connector.key(key_name) unless key_name.nil?
@ -93,10 +99,10 @@ module Devops
Server.extract_servers(provider, p, env, body, user, Devops::Db.connector) Server.extract_servers(provider, p, env, body, user, Devops::Db.connector)
end end
def pause_server node_name, key def pause_server node_name
s = Server.get_server_by_key(node_name, 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, @request.env['REMOTE_USER'] Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user
provider = ::Provider::ProviderFactory.get(s.provider) provider = ::Provider::ProviderFactory.get(s.provider)
r = provider.pause_server s r = provider.pause_server s
if r.nil? if r.nil?
@ -106,10 +112,10 @@ module Devops
end end
end end
def unpause_server node_name, key def unpause_server node_name
s = Server.get_server_by_key(params[:node_name], 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, @request.env['REMOTE_USER'] Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user
provider = ::Provider::ProviderFactory.get(s.provider) provider = ::Provider::ProviderFactory.get(s.provider)
r = provider.unpause_server s r = provider.unpause_server s
if r.nil? if r.nil?
@ -119,25 +125,26 @@ module Devops
end end
end end
def reserve_server node_name, key def reserve_server node_name
s = get_server_by_key(node_name, key) s = get_server_by_key(node_name, parser.instance_key)
Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER'] user = parser.current_user
Devops::Db.connector.check_project_auth s.project, s.deploy_env, user
raise ConflictException.new("Server '#{node_name}' already reserved") unless s.reserved_by.nil? raise ConflictException.new("Server '#{node_name}' already reserved") unless s.reserved_by.nil?
s.reserved_by = user s.reserved_by = user
Devops::Db.connector.server_update(s) Devops::Db.connector.server_update(s)
end end
def unreserve_server node_name, key def unreserve_server node_name
s = get_server_by_key(node_name, key) s = get_server_by_key(node_name, parser.instance_key)
Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER'] Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user
raise ConflictException.new("Server '#{node_name}' is not reserved") if s.reserved_by.nil? raise ConflictException.new("Server '#{node_name}' is not reserved") if s.reserved_by.nil?
s.reserved_by = nil s.reserved_by = nil
Devops::Db.connector.server_update(s) Devops::Db.connector.server_update(s)
end end
# TODO: check bootstrap template name # TODO: check bootstrap template name
def bootstrap_server_stream out, body def bootstrap_server_stream out
s = prepare_create_server body s = prepare_create_server
status = [] status = []
cert = Devops::Db.connector.key s.key cert = Devops::Db.connector.key s.key
logger.debug "Bootstrap certificate path: #{cert.path}" logger.debug "Bootstrap certificate path: #{cert.path}"
@ -159,15 +166,15 @@ module Devops
status status
end end
def bootstrap_server body def bootstrap_server
s = prepare_create_server body s = prepare_bootstrap_server
dir = DevopsConfig[:report_dir_v2] dir = DevopsConfig[:report_dir_v2]
files = [] files = []
uri = URI.parse(@request.url) uri = URI.parse(@request.url)
h = s.to_hash h = s.to_hash
h["options"] = s.options h["options"] = s.options
h["_id"] = s.id h["_id"] = s.id
jid = BootstrapWorker.perform_async(dir, d.provider, h, @request.env['REMOTE_USER'], DevopsConfig.config) jid = BootstrapWorker.perform_async(dir, d.provider, h, parser.current_user, DevopsConfig.config)
Worker.set_status jid, Worker::STATUS::IN_QUEUE Worker.set_status jid, Worker::STATUS::IN_QUEUE
logger.info "Job '#{jid}' has been started" logger.info "Job '#{jid}' has been started"
uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid
@ -178,12 +185,13 @@ module Devops
files files
end end
def prepare_bootstrap_server body def prepare_bootstrap_server
body = parser.bootstrap
id = body["instance_id"] id = body["instance_id"]
name = body["name"] name = body["name"]
s = Devops::Db.connector.server_by_instance_id(id) s = Devops::Db.connector.server_by_instance_id(id)
p = Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_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 = ::Provider::ProviderFactory.get(s.provider)
@ -201,10 +209,11 @@ module Devops
s s
end end
def add_server body def add_server
body = parser.add_server
project = body["project"] project = body["project"]
deploy_env = body["deploy_env"] deploy_env = body["deploy_env"]
p = Devops::Db.connector.check_project_auth project, deploy_env, @request.env['REMOTE_USER'] p = Devops::Db.connector.check_project_auth project, deploy_env, parser.current_user
d = p.deploy_env(deploy_env) d = p.deploy_env(deploy_env)

View File

@ -1,4 +1,5 @@
require 'db/mongo/models/stack/stack_factory' require 'db/mongo/models/stack/stack_factory'
require "app/api2/parsers/stack"
require_relative "request_handler" require_relative "request_handler"
module Devops module Devops
@ -6,6 +7,8 @@ module Devops
module Handler module Handler
class Stack < RequestHandler class Stack < RequestHandler
set_parser Devops::API2_0::Parser::StackParser
def stacks def stacks
Devops::Db.connector.stacks Devops::Db.connector.stacks
end end
@ -14,7 +17,8 @@ module Devops
Devops::Db.connector.stacks(provider) Devops::Db.connector.stacks(provider)
end end
def create_stack object def create_stack
object = parser.create
stack_model = Model::StackFactory.create(object['provider'], object) stack_model = Model::StackFactory.create(object['provider'], object)
Devops::Db.connector.stack_insert(stack_model) Devops::Db.connector.stack_insert(stack_model)
stack_model stack_model

View File

@ -7,6 +7,8 @@ module Devops
module Handler module Handler
class StackPreset < RequestHandler class StackPreset < RequestHandler
set_parser Devops::API2_0::Parser::StackPresetParser
def presets def presets
Devops::StackPresetsFactory.list Devops::StackPresetsFactory.list
end end
@ -15,7 +17,8 @@ module Devops
Devops::StackPresetsFactory.get(id) Devops::StackPresetsFactory.get(id)
end end
def apply id, body def apply id
body = parser.apply
preset = Devops::StackPresetsFactory.get(id) preset = Devops::StackPresetsFactory.get(id)
preset.create_stack_from_preset(body) preset.create_stack_from_preset(body)
Devops::Db.connector.stack_insert(stack) Devops::Db.connector.stack_insert(stack)

View File

@ -1,4 +1,5 @@
require 'db/mongo/models/stack_template/stack_template_factory' require 'db/mongo/models/stack_template/stack_template_factory'
require "app/api2/parsers/stack_template"
require_relative "request_handler" require_relative "request_handler"
module Devops module Devops
@ -6,6 +7,8 @@ module Devops
module Handler module Handler
class StackTemplate < RequestHandler class StackTemplate < RequestHandler
set_parser Devops::API2_0::Parser::StackTemplateParser
def stack_templates def stack_templates
Devops::Db.connector.stack_templates Devops::Db.connector.stack_templates
end end
@ -14,7 +17,8 @@ module Devops
Devops::Db.connector.stack_templates(provider) Devops::Db.connector.stack_templates(provider)
end end
def create_stack_template body def create_stack_template
body = parser.create
template_model = Model::StackTemplateFactory.create(body['provider'], body) template_model = Model::StackTemplateFactory.create(body['provider'], body)
Devops::Db.connector.stack_template_insert(template_model) Devops::Db.connector.stack_template_insert(template_model)
template_model template_model

View File

@ -1,9 +1,12 @@
require "commands/knife_commands" require "commands/knife_commands"
require "app/api2/parsers/tag"
require_relative "request_handler"
module Devops module Devops
module API2_0 module API2_0
module Handler module Handler
class Tag class Tag < RequestHandler
set_parser Devops::API2_0::Parser::TagParser
def initialize node_name def initialize node_name
@node_name = node_name @node_name = node_name
@ -12,20 +15,24 @@ module Devops
halt_response("No servers found for name '#{@node_name}'", 404) if @server.nil? halt_response("No servers found for name '#{@node_name}'", 404) if @server.nil?
end end
def tags def tags node_name
KnifeCommands.tags_list(@node_name) KnifeCommands.tags_list(node_name)
end end
def set_tags tags def set_tags node_name
tags = parser.tags
tagsStr = tags.join(" ") tagsStr = tags.join(" ")
cmd = KnifeCommands.tags_create(@node_name, tagsStr) cmd = KnifeCommands.tags_create(node_name, tagsStr)
halt_response("Error: 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
end end
def self.unset_tags def unset_tags node_name
tags = parser.tags
tagsStr = tags.join(" ") tagsStr = tags.join(" ")
cmd = KnifeCommands.tags_delete(@node_name, tagsStr) cmd = KnifeCommands.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
end end
end end
end end

View File

@ -1,39 +1,53 @@
require "db/mongo/models/user" require "db/mongo/models/user"
require "app/api2/parsers/user"
require_relative "request_handler"
module Devops module Devops
module API2_0 module API2_0
module Handler module Handler
class User class User < RequestHandler
set_parser Devops::API2_0::Parser::UserParser
def users def users
Devops::Db.connector.users Devops::Db.connector.users({}, {password: false})
end end
def create body def create
Devops::Db.connector.user_insert Devops::Model::User.new(body) body
Devops::Db.connector.user_insert parser.create
end end
def delete user_id def delete user_id
projects = Devops::Db.connector.projects_by_user user_id
if !projects.empty?
str = ""
projects.each do |p|
p.deploy_envs.each do |e|
str+="#{p.id}.#{e.identifier} " if e.users.include? user_id
end
end
raise DependencyError.new "Deleting is forbidden: User is included in #{str}"
end
Devops::Db.connector.user_delete user_id Devops::Db.connector.user_delete user_id
end end
def change_user_privileges user_id, cmd, privileges def change_user_privileges user_id
cmd, privileges = parser.user_privileges
change_user(user_id) do |user| change_user(user_id) do |user|
user.grant(cmd, privileges) user.grant(cmd, privileges)
end end
end end
def change_email options def change_email user_id
user_id, email = options.values_at('user_id', 'email')
change_user(user_id) do |user| change_user(user_id) do |user|
user.email = email user.email = parser.change_email
end end
end end
def change_password options def change_password user_id
user_id, password = options.values_at('user_id', 'password')
change_user(user_id) do |user| change_user(user_id) do |user|
user.password = password user.password = parser.change_password
end end
end end

View File

@ -0,0 +1,11 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class BootstrapTemplateParser < RequestParser
end
end
end
end

View File

@ -0,0 +1,19 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class DeployParser < RequestParser
def deploy
r = create_object_from_json_body
names = check_array(r["names"], "Parameter 'names' should be a not empty array of strings")
tags = check_array(r["tags"], "Parameter 'tags' should be an array of strings", String, true)
build_number = check_string(r["build_number"], "Parameter 'build_number' should be a not empty string", true)
r
end
end
end
end
end

View File

@ -0,0 +1,16 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class FilterParser < RequestParser
def images
images = create_object_from_json_body(Array)
check_array(images, "Request body should contains a not empty array with strings")
end
end
end
end
end

View File

@ -0,0 +1,23 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class ImageParser < RequestParser
def images
provider = @params[:provider]
check_provider(provider) if provider
provider
end
def image
image = create_object_from_json_body
Devops::Model::Image.new(image)
end
end
end
end
end

View File

@ -0,0 +1,19 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class KeyParser < RequestParser
def create
key = create_object_from_json_body
fname = check_filename(key["file_name"], "Parameter 'file_name' must be a not empty string")
kname = check_string(key["key_name"], "Parameter 'key_name' should be a not empty string")
content = check_string(key["content"], "Parameter 'content' should be a not empty string")
key
end
end
end
end
end

View File

@ -0,0 +1,57 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class ProjectParser < RequestParser
def project_servers
@params[:deploy_env]
end
def project_stacks
@params[:deploy_env]
end
def create_project
body = create_object_from_json_body
check_string(body["name"], "Parameter 'name' must be a not empty string")
check_array(body["deploy_envs"], "Parameter 'deploy_envs' must be a not empty array of objects", Hash)
Devops::Model::Project.new(body)
end
def update
body = create_object_from_json_body
check_array(body["deploy_envs"], "Parameter 'deploy_envs' must be a not empty array of objects", Hash)
Devops::Model::Project.new(body)
end
def delete
body = create_object_from_json_body(Hash, true)
deploy_env = unless body.nil?
check_string(body["deploy_env"], "Parameter 'deploy_env' should be a not empty string", true)
end
end
def project_users
body = create_object_from_json_body
users = check_array(body["users"], "Parameter 'users' must be a not empty array of strings")
deploy_env = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string", true)
return deploy_env, users
end
def run_list
list = create_object_from_json_body(Array)
check_array(list, "Body must contains not empty array of strings")
end
def deploy
obj = create_object_from_json_body
deploy_env = check_string(obj["deploy_env"], "Parameter 'deploy_env' should be a not empty string", true)
servers = check_array(obj["servers"], "Parameter 'servers' should be a not empty array of strings", String, true)
return deploy_env, servers
end
end
end
end
end

View File

@ -0,0 +1,26 @@
require "app/api2/helpers/version_2"
module Devops
module API2_0
module Parser
class RequestParser
include Devops::API2_0::Helpers
def initialize request
@request = request
@params = request.params
end
def current_user
@request.env['REMOTE_USER']
end
def request
@request
end
end
end
end
end

View File

@ -0,0 +1,26 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class ScriptParser < RequestParser
def execute_command
@request.body.read
end
def run_script
body = create_object_from_json_body
nodes = check_array(body["nodes"], "Parameter 'nodes' must be a not empty array of strings")
p = check_array(body["params"], "Parameter 'params' should be a not empty array of strings", String, true)
return nodes, p
end
def create_script
@request.body.read
end
end
end
end
end

View File

@ -0,0 +1,68 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class ServerParser < RequestParser
def servers
fields = []
if @params.key?("fields") and @params["fields"].is_a?(Array)
Devops::Model::Server.fields.each do |k|
fields.push k if @params["fields"].include?(k)
end
end
return fields, (@params.key?("reserved") ? true : nil)
end
def server
@params[:key]
end
def instance_key
body = create_object_from_json_body(Hash, true)
(body.nil? ? nil : body["key"])
end
def create
body = create_object_from_json_body
project_name = check_string(body["project"], "Parameter 'project' must be a not empty string")
env_name = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string")
server_name = check_string(body["name"], "Parameter 'name' should be null or not empty string", true)
without_bootstrap = body["without_bootstrap"]
force = body["force"]
raise InvalidRecord.new("Parameter 'without_bootstrap' should be a null or true") unless without_bootstrap.nil? or without_bootstrap == true
raise InvalidRecord.new("Parameter 'force' should be a null or true") unless force.nil? or force == true
groups = check_array(body["groups"], "Parameter 'groups' should be null or not empty array of string", String, true)
key_name = check_string(body["key"], "Parameter 'key' should be null or not empty string", true)
body
end
def bootstrap
body = create_object_from_json_body(Hash, true)
id = check_string(body["instance_id"], "Parameter 'instance_id' must be a not empty string")
name = check_string(body["name"], "Parameter 'name' should be a not empty string", true)
rl = check_array(body["run_list"], "Parameter 'run_list' should be a not empty array of string", String, true)
unless rl.nil?
validator = Validators::Helpers::RunList.new(rl)
halt_response(validator.message) unless validator.valid?
end
t = check_string(body["bootstrap_template"], "Parameter 'bootstrap_template' should be a not empty string", true)
body
end
def add_server
body = create_object_from_json_body
project = check_string(body["project"], "Parameter 'project' must be a not empty string")
deploy_env = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string")
key = check_string(body["key"], "Parameter 'key' must be a not empty string")
remote_user = check_string(body["remote_user"], "Parameter 'remote_user' must be a not empty string")
private_ip = check_string(body["private_ip"], "Parameter 'private_ip' must be a not empty string")
public_ip = check_string(body["public_ip"], "Parameter 'public_ip' should be a not empty string", true)
body
end
end
end
end
end

View File

@ -0,0 +1,15 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class StackParser < RequestParser
def create
create_object_from_json_body
end
end
end
end
end

View File

@ -0,0 +1,16 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class StackPresetParser < RequestParser
def apply
create_object_from_json_body
end
end
end
end
end

View File

@ -0,0 +1,15 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class StackTemplateParser < RequestParser
def create
create_object_from_json_body
end
end
end
end
end

View File

@ -0,0 +1,17 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class TagParser < RequestParser
def tags
tags = create_object_from_json_body(Array)
check_array(tags, "Request body should be a not empty array of strings")
end
end
end
end
end

View File

@ -0,0 +1,39 @@
require_relative "request_parser"
module Devops
module API2_0
module Parser
class UserParser < RequestParser
def create
user = create_object_from_json_body
["username", "password", "email"].each do |p|
check_string(user[p], "Parameter '#{p}' must be a not empty string")
end
Devops::Model::User.new(user)
end
def user_privileges
data = create_object_from_json_body
cmd = check_string(data["cmd"], "Parameter 'cmd' should be a not empty string", true)
privileges = check_string(data["privileges"], "Parameter 'privileges' should be a not empty string", true)
return cmd, privileges
end
def change_password
raise InvalidPrivileges.new("Access denied for '#{current_user}'") if user == Devops::Model::User::ROOT_USER_NAME and current_user != Devops::Model::User::ROOT_USER_NAME
body = create_object_from_json_body
check_string(body["password"], "Parameter 'password' must be a not empty string")
end
def change_email
raise InvalidPrivileges.new("Access denied for '#{current_user}'") if user == Devops::Model::User::ROOT_USER_NAME and current_user != Devops::Model::User::ROOT_USER_NAME
body = create_object_from_json_body
check_string(body["email"], "Parameter 'email' must be a not empty string")
end
end
end
end
end

View File

@ -3,8 +3,6 @@ module Devops
module Routes module Routes
module BootstrapTemplatesRoutes module BootstrapTemplatesRoutes
extend BootstrapTemplatesCommands
def self.registered(app) def self.registered(app)
# Get list of available bootstrap templates # Get list of available bootstrap templates
@ -20,7 +18,7 @@ module Devops
# ] # ]
app.get_with_headers "/templates", :headers => [:accept] do app.get_with_headers "/templates", :headers => [:accept] do
check_privileges("templates", "r") check_privileges("templates", "r")
json Devops::API2_0::Handler::BootstrapTemplates.new.get_templates json Devops::API2_0::Handler::BootstrapTemplates.new(request).get_templates
end end
puts "Bootstrap templates routes initialized" puts "Bootstrap templates routes initialized"

View File

@ -16,33 +16,29 @@ module Devops
# { # {
# "names": [], -> array of servers names to run chef-client # "names": [], -> array of servers names to run chef-client
# "tags": [], -> array of tags to apply on each server before running chef-client # "tags": [], -> array of tags to apply on each server before running chef-client
# "trace": true -> return output in stream # "build_number": "", -> string, build number to deploy
# "trace": true -> return output in stream if true
# } # }
# #
# * *Returns* : text stream # * *Returns* : text stream
app.post_with_headers "/deploy", :headers => [:content_type] do app.post_with_headers "/deploy", :headers => [:content_type] do
check_privileges("server", "x") check_privileges("server", "x")
# TODO: send message
#broadcast(:devops_deploy, "deploy")
r = create_object_from_json_body
names = check_array(r["names"], "Parameter 'names' should be a not empty array of strings")
tags = check_array(r["tags"], "Parameter 'tags' should be an array of strings", String, true) || []
if r.key?("trace") if r.key?("trace")
stream() do |out| stream() do |out|
status = [] status = []
begin begin
Devops::API2_0::Handler::Deploy.new(request, params).deploy_stream(out, names, tags) status = Devops::API2_0::Handler::Deploy.new(request).deploy_stream(out)
out << create_status(status)
rescue IOError => e rescue IOError => e
logger.error e.message logger.error e.message
break break
end end
end # stream end # stream
else else
ids = Devops::API2_0::Handler::Deploy.new(request, params).deploy(names, tags) ids = Devops::API2_0::Handler::Deploy.new(request).deploy()
sleep 1 sleep 1
ids.each do |jid| ids.each do |jid|
logger.info "Job '#{jid}' has been queued"
uri.path = "#{DevopsConfig.config[:url_prefix]}/v2.0/report/" + jid uri.path = "#{DevopsConfig.config[:url_prefix]}/v2.0/report/" + jid
files.push uri.to_s files.push uri.to_s
end end

View File

@ -26,7 +26,7 @@ module Devops
app.get_with_headers "/filter/:provider/images", :headers => [:accept] do |provider| app.get_with_headers "/filter/:provider/images", :headers => [:accept] do |provider|
check_privileges("filter", "r") check_privileges("filter", "r")
check_provider(provider) check_provider(provider)
json Devops::API2_0::Handler::Filter.new(request, params).available_images(provider) json Devops::API2_0::Handler::Filter.new(request).available_images(provider)
end end
hash = {} hash = {}
@ -47,10 +47,7 @@ module Devops
hash["PUT"] = lambda { |provider| hash["PUT"] = lambda { |provider|
check_privileges("filter", "w") check_privileges("filter", "w")
check_provider(provider) check_provider(provider)
images = create_object_from_json_body(Array) create_response("Updated", {:images => Devops::API2_0::Handler::Filter.new(request).add_images(provider)})
halt_response("Request body should not be an empty array") if images.empty?
check_array(images, "Request body should contains an array with strings")
create_response("Updated", {:images => Devops::API2_0::Handler::Filter.new(request, params).add_images(images, provider)})
} }
# Delete image ids from filter for :provider # Delete image ids from filter for :provider
@ -69,10 +66,7 @@ module Devops
hash["DELETE"] = lambda { |provider| hash["DELETE"] = lambda { |provider|
check_privileges("filter", "w") check_privileges("filter", "w")
check_provider(provider) check_provider(provider)
images = create_object_from_json_body(Array) create_response("Deleted", {:images => Devops::API2_0::Handler::Filter.new(request).delete_images(provider)})
halt_response("Request body should not be an empty array") if images.empty?
check_array(images, "Request body should contains an array with strings")
create_response("Deleted", {:images => Devops::API2_0::Handler::Filter.new(request, params).delete_images(images, provider)})
} }
app.multi_routes "/filter/:provider/image", {:headers => [:accept, :content_type]}, hash app.multi_routes "/filter/:provider/image", {:headers => [:accept, :content_type]}, hash

View File

@ -31,11 +31,10 @@ module Devops
# "disk": 20 # "disk": 20
# } # }
# ] # ]
app.get_with_headers "/flavors/:provider", :headers => [:accept] do app.get_with_headers "/flavors/:provider", :headers => [:accept] do |provider|
check_privileges("flavor", "r") check_privileges("flavor", "r")
provider = params[:provider]
check_provider(provider) check_provider(provider)
json Devops::API2_0::Handler::Flavor.new(request, params).flavors json Devops::API2_0::Handler::Flavor.new(request).flavors(provider)
end end
puts "Flavor routes initialized" puts "Flavor routes initialized"

View File

@ -44,11 +44,10 @@ module Devops
# } # }
# } # }
# TODO: vpc support for ec2 # TODO: vpc support for ec2
app.get_with_headers "/groups/:provider", :headers => [:accept] do#, &Devops::Version2_0::Handler::Group.get_groups app.get_with_headers "/groups/:provider", :headers => [:accept] do |provider|
check_privileges("group", "r") check_privileges("group", "r")
provider = params[:provider]
check_provider(provider) check_provider(provider)
json Devops::API2_0::Handler::Group.new(provider).groups(params) json Devops::API2_0::Handler::Group.new(request).groups(provider)
end end
puts "Group routes initialized" puts "Group routes initialized"

View File

@ -26,9 +26,7 @@ module Devops
# ] # ]
app.get_with_headers "/images", :headers => [:accept] do app.get_with_headers "/images", :headers => [:accept] do
check_privileges("image", "r") check_privileges("image", "r")
provider = params[:provider] json Devops::API2_0::Handler::Image.new(request).images.map(&:to_hash)
check_provider(provider) if provider
json Devops::API2_0::Handler::Image.new(request, params).images(provider).map(&:to_hash)
end end
# Get raw images for :provider # Get raw images for :provider
@ -58,7 +56,7 @@ module Devops
app.get_with_headers "/images/provider/:provider", :headers => [:accept] do |provider| app.get_with_headers "/images/provider/:provider", :headers => [:accept] do |provider|
check_privileges("image", "r") check_privileges("image", "r")
check_provider(provider) check_provider(provider)
json Devops::API2_0::Handler::Image.new(request, params).provider_images(provider) json Devops::API2_0::Handler::Image.new(request).provider_images(provider)
end end
# Create devops image # Create devops image
@ -81,8 +79,7 @@ module Devops
# 201 - Created # 201 - Created
app.post_with_headers "/image", :headers => [:accept, :content_type] do app.post_with_headers "/image", :headers => [:accept, :content_type] do
check_privileges("image", "w") check_privileges("image", "w")
image = create_object_from_json_body Devops::API2_0::Handler::Image.new(request).create_image()
Devops::API2_0::Handler::Image.new(request, params).create_image(image)
create_response "Created", nil, 201 create_response "Created", nil, 201
end end
@ -104,7 +101,7 @@ module Devops
# } # }
hash["GET"] = lambda { |image_id| hash["GET"] = lambda { |image_id|
check_privileges("image", "r") check_privileges("image", "r")
json Devops::API2_0::Handler::Image.new(request, params).image(image_id) json Devops::API2_0::Handler::Image.new(request).image(image_id)
} }
# Update devops image # Update devops image
@ -127,8 +124,7 @@ module Devops
# 200 - Updated # 200 - Updated
hash["PUT"] = lambda {|image_id| hash["PUT"] = lambda {|image_id|
check_privileges("image", "w") check_privileges("image", "w")
image = create_object_from_json_body Devops::API2_0::Handler::Image.new(request).update_image(image_id)
Devops::API2_0::Handler::Image.new(request, params).update_image(image_id, image)
create_response("Image '#{image_id}' has been updated") create_response("Image '#{image_id}' has been updated")
} }
@ -143,7 +139,7 @@ module Devops
# 200 - Deleted # 200 - Deleted
hash["DELETE"] = lambda {|image_id| hash["DELETE"] = lambda {|image_id|
check_privileges("image", "w") check_privileges("image", "w")
Devops::API2_0::Handler::Image.new(request, params).delete_image(image_id) Devops::API2_0::Handler::Image.new(request).delete_image(image_id)
create_response("Image '#{image_id}' has been removed") create_response("Image '#{image_id}' has been removed")
} }

View File

@ -22,7 +22,7 @@ module Devops
# ] # ]
app.get_with_headers "/keys", :headers => [:accept] do app.get_with_headers "/keys", :headers => [:accept] do
check_privileges("key", "r") check_privileges("key", "r")
json Devops::API2_0::Handler::Key.new.keys json Devops::API2_0::Handler::Key.new(request).keys.map(&:to_hash)
end end
# Create ssh key on devops server # Create ssh key on devops server
@ -43,13 +43,7 @@ module Devops
# 201 - Created # 201 - Created
app.post_with_headers "/key", :headers => [:accept, :content_type] do app.post_with_headers "/key", :headers => [:accept, :content_type] do
check_privileges("key", "w") check_privileges("key", "w")
key = create_object_from_json_body Devops::API2_0::Handler::Key.new(request).create
fname = check_filename(key["file_name"], "Parameter 'file_name' must be a not empty string")
kname = check_string(key["key_name"], "Parameter 'key_name' should be a not empty string")
content = check_string(key["content"], "Parameter 'content' should be a not empty string")
file_name = File.join(settings.keys_dir, fname)
halt(400, "File '#{fname}' already exist") if File.exists?(file_name)
Devops::API2_0::Handler::Key.new.create(key, file_name)
create_response("Created", nil, 201) create_response("Created", nil, 201)
end end
@ -62,13 +56,12 @@ module Devops
# #
# * *Returns* : # * *Returns* :
# 200 - Deleted # 200 - Deleted
app.delete_with_headers "/key/:key", :headers => [:accept] do app.delete_with_headers "/key/:key", :headers => [:accept] do |key|
check_privileges("key", "w") check_privileges("key", "w")
r = Devops::API2_0::Handler::Key.new.delete params[:key] r = Devops::API2_0::Handler::Key.new(request).delete key
return [500, r["err"].inspect] if r["err"] return [500, r["err"].inspect] if r["err"]
create_response("Key '#{params[:key]}' removed") create_response("Key '#{key}' removed")
end end
puts "Key routes initialized" puts "Key routes initialized"

View File

@ -35,7 +35,7 @@ module Devops
app.get_with_headers "/networks/:provider", :headers => [:accept] do |provider| app.get_with_headers "/networks/:provider", :headers => [:accept] do |provider|
check_privileges("network", "r") check_privileges("network", "r")
check_provider(provider) check_provider(provider)
json Devops::API2_0::Handler::Network.new(request, params).networks json Devops::API2_0::Handler::Network.new(request).networks
end end
puts "Network routes initialized" puts "Network routes initialized"

View File

@ -20,7 +20,7 @@ module Devops
# ] # ]
app.get_with_headers "/projects", :headers => [:accept] do app.get_with_headers "/projects", :headers => [:accept] do
check_privileges("project", "r") check_privileges("project", "r")
json Devops::API2_0::Handler::Project.new(request, params).projects.map(&:to_hash) json Devops::API2_0::Handler::Project.new(request).projects.map(&:to_hash)
end end
# Get project by id # Get project by id
@ -58,7 +58,7 @@ module Devops
hash = {} hash = {}
hash["GET"] = lambda {|project| hash["GET"] = lambda {|project|
check_privileges("project", "r") check_privileges("project", "r")
json Devops::API2_0::Handler::Project.new(request, params).project(project) json Devops::API2_0::Handler::Project.new(request).project(project)
} }
# Update project and create chef roles # Update project and create chef roles
@ -98,8 +98,7 @@ module Devops
# 200 - Updated # 200 - Updated
hash["PUT"] = lambda { |project| hash["PUT"] = lambda { |project|
check_privileges("project", "w") check_privileges("project", "w")
body = create_object_from_json_body r = Devops::API2_0::Handler::Project.new(request).update_project project
r = Devops::API2_0::Handler::Project.new(request, params).update_project project, body
info = "Project '#{project}' has been updated." + r info = "Project '#{project}' has been updated." + r
create_response(info) create_response(info)
} }
@ -120,11 +119,7 @@ module Devops
# 200 - Deleted # 200 - Deleted
hash["DELETE"] = lambda {|project| hash["DELETE"] = lambda {|project|
check_privileges("project", "w") check_privileges("project", "w")
body = create_object_from_json_body(Hash, true) info = Devops::API2_0::Handler::Project.new(request).delete_project(project)
deploy_env = unless body.nil?
check_string(body["deploy_env"], "Parameter 'deploy_env' should be a not empty string", true)
end
info = Devops::API2_0::Handler::Project.new(request, params).delete_project(project, deploy_env)
create_response(info) create_response(info)
} }
app.multi_routes "/project/:project", {}, hash app.multi_routes "/project/:project", {}, hash
@ -157,7 +152,7 @@ module Devops
# ] # ]
app.get_with_headers "/project/:project/servers", :headers => [:accept] do |project| app.get_with_headers "/project/:project/servers", :headers => [:accept] do |project|
check_privileges("project", "r") check_privileges("project", "r")
json Devops::API2_0::Handler::Project.new(request, params).project_servers(project).map(&:to_hash) json Devops::API2_0::Handler::Project.new(request).project_servers(project).map(&:to_hash)
end end
# Get project stacks # Get project stacks
@ -187,7 +182,7 @@ module Devops
# ] # ]
app.get_with_headers "/project/:project/stacks", :headers => [:accept] do |project| app.get_with_headers "/project/:project/stacks", :headers => [:accept] do |project|
check_privileges("project", "r") check_privileges("project", "r")
json Devops::API2_0::Handler::Project.new(request, params).project_stacks(project).map(&:to_hash) json Devops::API2_0::Handler::Project.new(request).project_stacks(project).map(&:to_hash)
end end
# Create project and chef roles # Create project and chef roles
@ -227,11 +222,8 @@ module Devops
# 201 - Created # 201 - Created
app.post_with_headers "/project", :headers => [:accept, :content_type] do app.post_with_headers "/project", :headers => [:accept, :content_type] do
check_privileges("project", "w") check_privileges("project", "w")
body = create_object_from_json_body
check_string(body["name"], "Parameter 'name' must be a not empty string")
check_array(body["deploy_envs"], "Parameter 'deploy_envs' must be a not empty array of objects", Hash)
begin begin
res = Devops::API2_0::Handler::Project.new(request, params).create_project body res = Devops::API2_0::Handler::Project.new(request).create_project
res = "Created. " + res res = "Created. " + res
create_response(res, nil, 201) create_response(res, nil, 201)
rescue InvalidRecord => e rescue InvalidRecord => e
@ -259,10 +251,7 @@ module Devops
# 200 - Updated # 200 - Updated
users_hash["PUT"] = lambda { |project| users_hash["PUT"] = lambda { |project|
check_privileges("project", "w") check_privileges("project", "w")
body = create_object_from_json_body info = Devops::API2_0::Handler::Project.new(request).update_project_users(project)
users = check_array(body["users"], "Parameter 'users' must be a not empty array of strings")
deploy_env = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string", true)
info = Devops::API2_0::Handler::Project.new(request, params).update_project_users(project, deploy_env, users)
create_response(info) create_response(info)
} }
@ -285,10 +274,7 @@ module Devops
# 200 - Updated # 200 - Updated
users_hash["DELETE"] = lambda {|project| users_hash["DELETE"] = lambda {|project|
check_privileges("project", "w") check_privileges("project", "w")
body = create_object_from_json_body info = Devops::API2_0::Handler::Project.new(request).delete_project_users(project)
users = check_array(body["users"], "Parameter 'users' must be a not empty array of strings")
deploy_env = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string", true)
info = Devops::API2_0::Handler::Project.new(request, params).delete_project_users(project, deploy_env, users)
create_response(info) create_response(info)
} }
app.multi_routes "/project/:id/user", {}, users_hash app.multi_routes "/project/:id/user", {}, users_hash
@ -310,9 +296,7 @@ module Devops
# 200 - Updated # 200 - Updated
app.put_with_headers "/project/:id/:env/run_list", :headers => [:accept, :content_type] do |project, deploy_env| app.put_with_headers "/project/:id/:env/run_list", :headers => [:accept, :content_type] do |project, deploy_env|
check_privileges("project", "w") check_privileges("project", "w")
list = create_object_from_json_body(Array) info = Devops::API2_0::Handler::Project.new(request).set_project_env_run_list(project, deploy_env)
check_array(list, "Body must contains not empty array of strings")
info = Devops::API2_0::Handler::Project.new(request, params).set_project_env_run_list(project, deploy_env, list)
create_response(info) create_response(info)
end end
@ -333,21 +317,18 @@ module Devops
# * *Returns* : text stream # * *Returns* : text stream
app.post_with_headers "/project/:id/deploy", :headers => [:content_type] do |project| app.post_with_headers "/project/:id/deploy", :headers => [:content_type] do |project|
check_privileges("project", "x") check_privileges("project", "x")
obj = create_object_from_json_body handler = Devops::API2_0::Handler::Project.new(request)
deploy_env = check_string(obj["deploy_env"], "Parameter 'deploy_env' should be a not empty string", true)
servers = check_array(obj["servers"], "Parameter 'servers' should be a not empty array of strings", String, true)
handler = Devops::API2_0::Handler::Project.new(request, params)
if obj.key?("trace") if obj.key?("trace")
stream() do |out| stream() do |out|
begin begin
status = handler.deploy_project_stream out, project, deploy_env, servers status = handler.deploy_project_stream out, project
out << create_status(status) out << create_status(status)
rescue IOError => e rescue IOError => e
logger.error e.message logger.error e.message
end end
end end
else else
json handler.deploy_project project, deploy_env, servers json handler.deploy_project project
end end
end end
@ -359,7 +340,7 @@ module Devops
# - Content-Type: application/json # - Content-Type: application/json
app.post_with_headers "/project/:project/archive", :headers => [:content_type] do |project| app.post_with_headers "/project/:project/archive", :headers => [:content_type] do |project|
check_privileges("project", "w") check_privileges("project", "w")
info = Devops::API2_0::Handler::Project.new(request, params).archive_project(project) info = Devops::API2_0::Handler::Project.new(request).archive_project(project)
create_response(info) create_response(info)
end end
@ -371,7 +352,7 @@ module Devops
# - Content-Type: application/json # - Content-Type: application/json
app.post_with_headers "/project/:project/unarchive", :headers => [:content_type] do |project| app.post_with_headers "/project/:project/unarchive", :headers => [:content_type] do |project|
check_privileges("project", "w") check_privileges("project", "w")
info = Devops::API2_0::Handler::Project.new(request, params).unarchive_project(project) info = Devops::API2_0::Handler::Project.new(request).unarchive_project(project)
create_response(info) create_response(info)
end end
@ -443,7 +424,7 @@ module Devops
# } # }
app.post_with_headers "/project/test/:id/:env", :headers => [:accept, :content_type] do |project, deploy_env| app.post_with_headers "/project/test/:id/:env", :headers => [:accept, :content_type] do |project, deploy_env|
check_privileges("project", "r") check_privileges("project", "r")
json Devops::API2_0::Handler::Project.new(request, params).test_project(project, deploy_env) json Devops::API2_0::Handler::Project.new(request).test_project(project, deploy_env)
end end
puts "Project routes initialized" puts "Project routes initialized"

View File

@ -23,7 +23,7 @@ module Devops
# ] # ]
app.get_with_headers "/providers", :headers => [:accept] do#, &Devops::Version2_0::Handler::Provider.get_providers app.get_with_headers "/providers", :headers => [:accept] do#, &Devops::Version2_0::Handler::Provider.get_providers
check_privileges("provider", "r") check_privileges("provider", "r")
json Devops::API2_0::Handler::Provider.new(request, params).providers json Devops::API2_0::Handler::Provider.new(request).providers
end end
puts "Provider routes initialized" puts "Provider routes initialized"

View File

@ -6,24 +6,24 @@ module Devops
def self.registered(app) def self.registered(app)
app.get_with_headers "/report/all", headers: [:accept] do app.get_with_headers "/report/all", headers: [:accept] do
json Devops::API2_0::Handler::Report.new(request, params).all.map{|r| r.to_hash} json Devops::API2_0::Handler::Report.new(request).all.map{|r| r.to_hash}
end end
app.get_with_headers "/report/all/latest", headers: [:accept] do app.get_with_headers "/report/all/latest", headers: [:accept] do
json Devops::API2_0::Handler::Report.new(request, params).all_latest.map{|r| r.to_hash} json Devops::API2_0::Handler::Report.new(request).all_latest.map{|r| r.to_hash}
end end
app.get_with_headers "/report/all/attributes/:name", headers: [:accept] do |name| app.get_with_headers "/report/all/attributes/:name", headers: [:accept] do |name|
json Devops::API2_0::Handler::Report.new(request, params).attributes(name) json Devops::API2_0::Handler::Report.new(request).attributes(name)
end end
app.get_with_headers "/report/:id", headers: [:accept] do |id| app.get_with_headers "/report/:id", headers: [:accept] do |id|
@text, @done = Devops::API2_0::Handler::Report.new(request, params).report(id) @text, @done = Devops::API2_0::Handler::Report.new(request).report(id)
erb :index erb :index
end end
app.get "/status/:id" do app.get "/status/:id" do |id|
r = Devops::API2_0::Handler::Report.new(request, params).status(params[:id]) r = Devops::API2_0::Handler::Report.new(request).status(id)
return [404, "Job with id '#{params[:id]}' not found"] if r.nil? return [404, "Job with id '#{params[:id]}' not found"] if r.nil?
r r
end end

View File

@ -17,7 +17,7 @@ module Devops
# ] # ]
app.get_with_headers "/scripts", :headers => [:accept] do app.get_with_headers "/scripts", :headers => [:accept] do
check_privileges("script", "r") check_privileges("script", "r")
json Devops::API2_0::Handler::Script.new(request, params).scripts json Devops::API2_0::Handler::Script.new(request).scripts
end end
# Run command on node :node_name # Run command on node :node_name
@ -32,7 +32,7 @@ module Devops
check_privileges("script", "x") check_privileges("script", "x")
stream() do |out| stream() do |out|
begin begin
Devops::API2_0::Handler::Script.new(request, params).execute_command(out, request.body.read, node_name) Devops::API2_0::Handler::Script.new(request).execute_command(out, node_name)
rescue IOError => e rescue IOError => e
logger.error e.message logger.error e.message
end end
@ -54,14 +54,10 @@ module Devops
# * *Returns* : text stream # * *Returns* : text stream
app.post_with_headers "/script/run/:script_name", :headers => [:content_type] do |script_name| app.post_with_headers "/script/run/:script_name", :headers => [:content_type] do |script_name|
check_privileges("script", "x") check_privileges("script", "x")
file_name = check_filename(script_name, "Parameter 'script_name' must be a not empty string", false)
body = create_object_from_json_body
nodes = check_array(body["nodes"], "Parameter 'nodes' must be a not empty array of strings")
p = check_array(body["params"], "Parameter 'params' should be a not empty array of strings", String, true)
stream() do |out| stream() do |out|
begin begin
Devops::API2_0::Handler::Script.new(request, params).run_script out, file_name, nodes, p status = Devops::API2_0::Handler::Script.new(request).run_script out, script_name
out << create_status(status)
rescue IOError => e rescue IOError => e
logger.error e.message logger.error e.message
end end
@ -79,12 +75,10 @@ module Devops
# #
# * *Returns* : # * *Returns* :
# 201 - Created # 201 - Created
hash["PUT"] = lambda { hash["PUT"] = lambda { |script_name|
check_privileges("script", "w") check_privileges("script", "w")
file_name = params[:script_name] Devops::API2_0::Handler::Script.new(request).create_script(script_name)
check_filename(file_name, "Parameter 'script_name' must be a not empty string") create_response("File '#{script_name}' created", nil, 201)
Devops::API2_0::Handler::Script.new(request, params).create_script(file_name)
create_response("File '#{file_name}' created", nil, 201)
} }
# Delete script :script_name # Delete script :script_name
@ -96,12 +90,10 @@ module Devops
# #
# * *Returns* : # * *Returns* :
# 200 - Deleted # 200 - Deleted
hash["DELETE"] = lambda { hash["DELETE"] = lambda { |script_name|
check_privileges("script", "w") check_privileges("script", "w")
file_name = params[:script_name] Devops::API2_0::Handler::Script.new(request).delete_script script_name
check_filename(file_name, "Parameter 'script_name' must be a not empty string") create_response("File '#{script_name}' deleted")
Devops::API2_0::Handler::Script.new(request, params).delete_script file_name
create_response("File '#{file_name}' deleted")
} }
app.multi_routes "/script/:script_name", {:headers => [:accept]}, hash app.multi_routes "/script/:script_name", {:headers => [:accept]}, hash

View File

@ -1,5 +1,3 @@
require "json"
module Devops module Devops
module API2_0 module API2_0
module Routes module Routes
@ -25,14 +23,7 @@ module Devops
# ] # ]
app.get_with_headers "/servers", :headers => [:accept] do app.get_with_headers "/servers", :headers => [:accept] do
check_privileges("server", "r") check_privileges("server", "r")
fields = [] json Devops::API2_0::Handler::Server.new(request).servers
if params.key?("fields") and params["fields"].is_a?(Array)
Devops::Model::Server.fields.each do |k|
fields.push k if params["fields"].include?(k)
end
end
reserved = (params.key?("reserved") ? true : nil)
json Devops::API2_0::Handler::Server.new(request, params).servers(fields, reserved)
end end
# Get chef nodes list # Get chef nodes list
@ -50,7 +41,7 @@ module Devops
# ] # ]
app.get_with_headers "/servers/chef", :headers => [:accept] do app.get_with_headers "/servers/chef", :headers => [:accept] do
check_privileges("server", "r") check_privileges("server", "r")
json Devops::API2_0::Handler::Server.new(request, params).chef_servers json Devops::API2_0::Handler::Server.new(request).chef_servers
end end
# Get provider servers list # Get provider servers list
@ -89,9 +80,9 @@ module Devops
# "private_ip": "172.17.0.1" # "private_ip": "172.17.0.1"
# } # }
# ] # ]
app.get_with_headers "/servers/:provider", :headers => [:accept] do app.get_with_headers "/servers/:provider", :headers => [:accept] do |provider|
check_privileges("server", "r") check_privileges("server", "r")
json Devops::API2_0::Handler::Server.new(request, params).provider_servers(params[:provider]) json Devops::API2_0::Handler::Server.new(request).provider_servers(provider)
end end
# Get server info by :name # Get server info by :name
@ -112,7 +103,7 @@ module Devops
hash = {} hash = {}
hash["GET"] = lambda {|id| hash["GET"] = lambda {|id|
check_privileges("server", "r") check_privileges("server", "r")
json Devops::API2_0::Handler::Server.new(request, params).server(id).to_hash json Devops::API2_0::Handler::Server.new(request).server(id).to_hash
} }
# Delete devops server # Delete devops server
@ -131,9 +122,7 @@ module Devops
# 200 - Deleted # 200 - Deleted
hash["DELETE"] = lambda {|id| hash["DELETE"] = lambda {|id|
check_privileges("server", "w") check_privileges("server", "w")
body = create_object_from_json_body(Hash, true) info, r = Devops::API2_0::Handler::Server.new(request).delete(id)
key = (body.nil? ? nil : body["key"])
info, r = Devops::API2_0::Handler::Server.new(request, params).delete(id, key)
create_response(info, r) create_response(info, r)
} }
app.multi_routes "/server/:id", {:headers => [:accept, :content_type]}, hash app.multi_routes "/server/:id", {:headers => [:accept, :content_type]}, hash
@ -160,28 +149,18 @@ module Devops
# * *Returns* : text stream # * *Returns* : text stream
app.post_with_headers "/server", :headers => [:content_type] do app.post_with_headers "/server", :headers => [:content_type] do
check_privileges("server", "w") check_privileges("server", "w")
body = create_object_from_json_body handler = Devops::API2_0::Handler::Server.new(request)
project_name = check_string(body["project"], "Parameter 'project' must be a not empty string")
env_name = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string")
server_name = check_string(body["name"], "Parameter 'name' should be null or not empty string", true)
without_bootstrap = body["without_bootstrap"]
force = body["force"]
halt_response("Parameter 'without_bootstrap' should be a null or true") unless without_bootstrap.nil? or without_bootstrap == true
halt_response("Parameter 'force' should be a null or true") unless force.nil? or force == true
groups = check_array(body["groups"], "Parameter 'groups' should be null or not empty array of string", String, true)
key_name = check_string(body["key"], "Parameter 'key' should be null or not empty string", true)
handler = Devops::API2_0::Handler::Server.new(request, params)
if body.key?("trace") if body.key?("trace")
stream() do |out| stream() do |out|
begin begin
status = handler.create_server_stream out, body status = handler.create_server_stream out
out << create_status(status) out << create_status(status)
rescue IOError => e rescue IOError => e
logger.error e.message logger.error e.message
end end
end end
else else
json handler.create_server body json handler.create_server
end end
end end
@ -201,9 +180,7 @@ module Devops
# 200 - Paused # 200 - Paused
app.post_with_headers "/server/:node_name/pause", :headers => [:accept, :content_type] do |node_name| app.post_with_headers "/server/:node_name/pause", :headers => [:accept, :content_type] do |node_name|
check_privileges("server", "w") check_privileges("server", "w")
body = create_object_from_json_body(Hash, true) info = Devops::API2_0::Handler::Server.new(request).pause_server(node_name)
key = (body.nil? ? nil : body["key"])
info = Devops::API2_0::Handler::Server.new(request, params).pause_server(node_name, key)
create_response(info) create_response(info)
end end
@ -223,9 +200,7 @@ module Devops
# 200 - Unpaused # 200 - Unpaused
app.post_with_headers "/server/:node_name/unpause", :headers => [:accept, :content_type] do |node_name| app.post_with_headers "/server/:node_name/unpause", :headers => [:accept, :content_type] do |node_name|
check_privileges("server", "w") check_privileges("server", "w")
body = create_object_from_json_body(Hash, true) info = Devops::API2_0::Handler::Server.new(request).unpause_server(node_name)
key = (body.nil? ? nil : body["key"])
info = Devops::API2_0::Handler::Server.new(request, params).unpause_server(node_name, key)
create_response(info) create_response(info)
end end
@ -245,9 +220,7 @@ module Devops
# 200 - Reserved # 200 - Reserved
app.post_with_headers "/server/:node_name/reserve", :headers => [:accept, :content_type] do |node_name| app.post_with_headers "/server/:node_name/reserve", :headers => [:accept, :content_type] do |node_name|
check_privileges("server", "w") check_privileges("server", "w")
body = create_object_from_json_body(Hash, true) Devops::API2_0::Handler::Server.new(request).reserve_server(node_name)
key = (body.nil? ? nil : body["key"])
Devops::API2_0::Handler::Server.new(request, params).reserve_server(node_name, key)
create_response("Server '#{node_name}' has been reserved") create_response("Server '#{node_name}' has been reserved")
end end
@ -267,9 +240,7 @@ module Devops
# 200 - Unreserved # 200 - Unreserved
app.post_with_headers "/server/:node_name/unreserve", :headers => [:accept, :content_type] do |node_name| app.post_with_headers "/server/:node_name/unreserve", :headers => [:accept, :content_type] do |node_name|
check_privileges("server", "w") check_privileges("server", "w")
body = create_object_from_json_body(Hash, true) Devops::API2_0::Handler::Server.new(request).unreserve_server(node_name)
key = (body.nil? ? nil : body["key"])
Devops::API2_0::Handler::Server.new(request, params).unreserve_server(node_name, key)
create_response("Server '#{node_name}' has been unreserved") create_response("Server '#{node_name}' has been unreserved")
end end
@ -291,28 +262,19 @@ module Devops
# * *Returns* : text stream # * *Returns* : text stream
app.post_with_headers "/server/bootstrap", :headers => [:accept, :content_type] do app.post_with_headers "/server/bootstrap", :headers => [:accept, :content_type] do
check_privileges("server", "w") check_privileges("server", "w")
body = create_object_from_json_body(Hash, true)
id = check_string(body["instance_id"], "Parameter 'instance_id' must be a not empty string")
name = check_string(body["name"], "Parameter 'name' should be a not empty string", true)
rl = check_array(body["run_list"], "Parameter 'run_list' should be a not empty array of string", String, true)
unless rl.nil?
validator = Validators::Helpers::RunList.new(rl)
halt_response(validator.message) unless validator.valid?
end
t = check_string(body["bootstrap_template"], "Parameter 'bootstrap_template' should be a not empty string", true)
handler = Devops::API2_0::Handler::Server.new(request, params) handler = Devops::API2_0::Handler::Server.new(request)
if body.key?("trace") if body.key?("trace")
stream() do |out| stream() do |out|
begin begin
status = handler.bootstrap_server_stream out, body status = handler.bootstrap_server_stream out
out << create_status(status) out << create_status(status)
rescue IOError => e rescue IOError => e
logger.error e.message logger.error e.message
end end
end end
else else
handler.bootstrap_server(body) json handler.bootstrap_server()
end end
end end
@ -337,15 +299,7 @@ module Devops
# 200 - Added # 200 - Added
app.post_with_headers "/server/add", :headers => [:accept, :content_type] do app.post_with_headers "/server/add", :headers => [:accept, :content_type] do
check_privileges("server", "w") check_privileges("server", "w")
body = create_object_from_json_body info = Devops::API2_0::Handler::Server.new(request).add_server()
project = check_string(body["project"], "Parameter 'project' must be a not empty string")
deploy_env = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string")
key = check_string(body["key"], "Parameter 'key' must be a not empty string")
remote_user = check_string(body["remote_user"], "Parameter 'remote_user' must be a not empty string")
private_ip = check_string(body["private_ip"], "Parameter 'private_ip' must be a not empty string")
public_ip = check_string(body["public_ip"], "Parameter 'public_ip' should be a not empty string", true)
info = Devops::API2_0::Handler::Server.new(request, params).add_server(body)
create_response(info) create_response(info)
end end

View File

@ -7,19 +7,18 @@ module Devops
app.get_with_headers '/stacks', :headers => [:accept] do app.get_with_headers '/stacks', :headers => [:accept] do
check_privileges("stack", "r") check_privileges("stack", "r")
json Devops::API2_0::Handler::Stack.new(request, params).stacks.map(&:to_hash) json Devops::API2_0::Handler::Stack.new(request).stacks.map(&:to_hash)
end end
app.get_with_headers '/stacks/provider/:provider', :headers => [:accept] do |provider| app.get_with_headers '/stacks/provider/:provider', :headers => [:accept] do |provider|
check_privileges("stack", "r") check_privileges("stack", "r")
check_provider(provider) check_provider(provider)
json Devops::API2_0::Handler::Stack.new(request, params).stacks_for_provider(provider).map(&:to_hash) json Devops::API2_0::Handler::Stack.new(request).stacks_for_provider(provider).map(&:to_hash)
end end
app.post_with_headers "/stack", :headers => [:accept] do app.post_with_headers "/stack", :headers => [:accept] do
check_privileges("stack", "w") check_privileges("stack", "w")
object = create_object_from_json_body m = Devops::API2_0::Handler::Stack.new(request).create_stack object
m = Devops::API2_0::Handler::Stack.new(request, params).create_stack object
create_response "Created", m.to_hash, 201 create_response "Created", m.to_hash, 201
end end
@ -27,29 +26,29 @@ module Devops
hash['GET'] = lambda { |stack_id| hash['GET'] = lambda { |stack_id|
check_privileges("stack", "r") check_privileges("stack", "r")
json Devops::API2_0::Handler::Stack.new(request, params).stack(stack_id).to_hash json Devops::API2_0::Handler::Stack.new(request).stack(stack_id).to_hash
} }
hash['DELETE'] = lambda { |stack_id| hash['DELETE'] = lambda { |stack_id|
check_privileges("stack", "w") check_privileges("stack", "w")
Devops::API2_0::Handler::Stack.new(request, params).delete_stack(stack_id) Devops::API2_0::Handler::Stack.new(request).delete_stack(stack_id)
create_response("Stack '#{stack_id}' has been removed") create_response("Stack '#{stack_id}' has been removed")
} }
app.multi_routes '/stack/:stack_id', {:headers => [:accept]}, hash app.multi_routes '/stack/:stack_id', {:headers => [:accept]}, hash
app.post_with_headers "/stack/:stack_id/sync_details", :headers => [:accept] do |stack_id| app.post_with_headers "/stack/:stack_id/sync_details", :headers => [:accept] do |stack_id|
check_privileges("stack", "w") check_privileges("stack", "w")
json Devops::API2_0::Handler::Stack.new(request, params).sync_details(stack_id).to_hash json Devops::API2_0::Handler::Stack.new(request).sync_details(stack_id).to_hash
end end
app.get_with_headers "/stack/:stack_id/resources", :headers => [:accept] do |stack_id| app.get_with_headers "/stack/:stack_id/resources", :headers => [:accept] do |stack_id|
check_privileges("stack", "r") check_privileges("stack", "r")
json Devops::API2_0::Handler::Stack.new(request, params).resources(stack_id) json Devops::API2_0::Handler::Stack.new(request).resources(stack_id)
end end
app.get_with_headers "/stack/:stack_id/resources/:resource_id", :headers => [:accept] do |stack_id, resource_id| app.get_with_headers "/stack/:stack_id/resources/:resource_id", :headers => [:accept] do |stack_id, resource_id|
check_privileges("stack", "r") check_privileges("stack", "r")
json Devops::API2_0::Handler::Stack.new(request, params).resource(stack_id, resource_id) json Devops::API2_0::Handler::Stack.new(request).resource(stack_id, resource_id)
end end
puts "Stack routes initialized" puts "Stack routes initialized"

View File

@ -16,7 +16,7 @@ module Devops
# #
app.get_with_headers "/stack_presets", :headers => [:accept] do app.get_with_headers "/stack_presets", :headers => [:accept] do
# check_privileges("stack_template_presets", "r") # check_privileges("stack_template_presets", "r")
json Devops::API2_0::Handler::StackPreset.new(request, params).presets.map(&:to_hash) json Devops::API2_0::Handler::StackPreset.new(request).presets.map(&:to_hash)
end end
# Get information about stack_template_preset # Get information about stack_template_preset
@ -31,7 +31,7 @@ module Devops
# #
app.get_with_headers "/stack_presets/:id", :headers => [:accept] do |id| app.get_with_headers "/stack_presets/:id", :headers => [:accept] do |id|
# check_privileges("stack_template_presets", "r") # check_privileges("stack_template_presets", "r")
json Devops::API2_0::Handler::StackPreset.new(request, params).preset(id).to_hash json Devops::API2_0::Handler::StackPreset.new(request).preset(id).to_hash
end end
# Build stack template from preset # Build stack template from preset
@ -57,8 +57,7 @@ module Devops
app.post_with_headers "/stack_presets/:id/apply", :headers => [:accept] do |id| app.post_with_headers "/stack_presets/:id/apply", :headers => [:accept] do |id|
# check_privileges("stack_template_presets", "r") # check_privileges("stack_template_presets", "r")
check_privileges('stack_template', 'w') check_privileges('stack_template', 'w')
body = create_object_from_json_body stack = Devops::API2_0::Handler::StackPreset.new(request).apply(id)
stack = Devops::API2_0::Handler::StackPreset.new(request, params).apply(id, body)
create_response 'Created', stack.to_hash, 201 create_response 'Created', stack.to_hash, 201
end end

View File

@ -6,19 +6,18 @@ module Devops
def self.registered(app) def self.registered(app)
app.get_with_headers '/stack_templates', :headers => [:accept] do app.get_with_headers '/stack_templates', :headers => [:accept] do
check_privileges('stack_template', 'r') check_privileges('stack_template', 'r')
json Devops::API2_0::Handler::StackTemplate.new(request, params).stack_templates.map(&:to_hash) json Devops::API2_0::Handler::StackTemplate.new(request).stack_templates.map(&:to_hash)
end end
app.get_with_headers '/stack_templates/provider/:provider', :headers => [:accept] do |provider| app.get_with_headers '/stack_templates/provider/:provider', :headers => [:accept] do |provider|
check_privileges('stack_template', 'r') check_privileges('stack_template', 'r')
check_provider(provider) check_provider(provider)
json Devops::API2_0::Handler::StackTemplate.new(request, params).stack_templates_for_provider(provider).map(&:to_hash) json Devops::API2_0::Handler::StackTemplate.new(request).stack_templates_for_provider(provider).map(&:to_hash)
end end
app.post_with_headers "/stack_template", :headers => [:accept] do app.post_with_headers "/stack_template", :headers => [:accept] do
check_privileges('stack_template', 'w') check_privileges('stack_template', 'w')
body = create_object_from_json_body model = Devops::API2_0::Handler::StackTemplate.new(request).create_stack_template()
model = Devops::API2_0::Handler::StackTemplate.new(request, params).create_stack_template(body)
create_response 'Created', model.to_hash, 201 create_response 'Created', model.to_hash, 201
end end
@ -26,12 +25,12 @@ module Devops
hash['GET'] = lambda {|stack_template_id| hash['GET'] = lambda {|stack_template_id|
check_privileges('stack_template', 'r') check_privileges('stack_template', 'r')
json Devops::API2_0::Handler::StackTemplate.new(request, params).stack_template(stack_template_id).to_hash json Devops::API2_0::Handler::StackTemplate.new(request).stack_template(stack_template_id).to_hash
} }
hash['DELETE'] = lambda {|stack_template_id| hash['DELETE'] = lambda {|stack_template_id|
check_privileges('stack_template', 'w') check_privileges('stack_template', 'w')
Devops::API2_0::Handler::StackTemplate.new(request, params).delete_stack_template(stack_template_id) Devops::API2_0::Handler::StackTemplate.new(request).delete_stack_template(stack_template_id)
create_response("Template '#{stack_template_id}' has been removed") create_response("Template '#{stack_template_id}' has been removed")
} }

View File

@ -17,9 +17,9 @@ module Devops
# [ # [
# "tag_1" # "tag_1"
# ] # ]
hash["GET"] = lambda { hash["GET"] = lambda {|node_name|
check_privileges("server", "r") check_privileges("server", "r")
json Devops::API2_0::Handler::Tag.new(params[:node_name]).tags() json Devops::API2_0::Handler::Tag.new(request).tags(node_name)
} }
# Set tags list to :node_name # Set tags list to :node_name
@ -36,12 +36,10 @@ module Devops
# #
# * *Returns* : # * *Returns* :
# 200 # 200
hash["POST"] = lambda { hash["POST"] = lambda {|node_name|
check_privileges("server", "w") check_privileges("server", "w")
tags = create_object_from_json_body(Array) tags = Devops::API2_0::Handler::Tag.new(request).set_tags(node_name)
check_array(tags, "Request body should be a not empty array of strings") create_response("Set tags for #{node_name}", tags: tags)
Devops::Version2_0::Handler::Tag.new(params[:node_name]).set_tags(tags)
create_response("Set tags for #{params[:node_name]}", tags: tags)
} }
# Delete tags from :node_name # Delete tags from :node_name
@ -58,12 +56,10 @@ module Devops
# #
# * *Returns* : # * *Returns* :
# 200 # 200
hash["DELETE"] = lambda { hash["DELETE"] = lambda {|node_name|
check_privileges("server", "w") check_privileges("server", "w")
tags = create_object_from_json_body(Array) tags = Devops::API2_0::Handler::Tag.new(request).unset_tags(node_name)
check_array(tags, "Request body should be a not empty array of strings") create_response("Deleted tags for #{node_name}", tags: tags)
Devops::Version2_0::Handler::Tag.new(params[:node_name]).unset_tags(tags)
create_response("Deleted tags for #{params[:node_name]}", tags: tags)
} }
app.multi_routes "/tags/:node_name", {:headers => [:accept, :content_type]}, hash app.multi_routes "/tags/:node_name", {:headers => [:accept, :content_type]}, hash

View File

@ -33,10 +33,9 @@ module Devops
# "id": "test" # "id": "test"
# } # }
# ] # ]
app.get_with_headers "/users", :headers => [:accept] do#, &Devops::API2_0::Handler::User.get_users app.get_with_headers "/users", :headers => [:accept] do
check_privileges("user", "r") check_privileges("user", "r")
users = Devops::API2_0::Handler::User.new.users.map {|i| h = i.to_hash; h.delete("password"); h} json Devops::API2_0::Handler::User.new(request).users.map(&:to_hash)
json users
end end
# Create user # Create user
@ -55,13 +54,9 @@ module Devops
# #
# * *Returns* : # * *Returns* :
# 201 - Created # 201 - Created
app.post_with_headers "/user", :headers => [:accept, :content_type] do#, &Devops::API2_0::Handler::User.create_user app.post_with_headers "/user", :headers => [:accept, :content_type] do
check_privileges("user", "w") check_privileges("user", "w")
user = create_object_from_json_body Devops::API2_0::Handler::User.new(request).create
["username", "password", "email"].each do |p|
check_string(user[p], "Parameter '#{p}' must be a not empty string")
end
Devops::API2_0::Handler::User.new.create(user)
create_response("Created", nil, 201) create_response("Created", nil, 201)
end end
@ -75,23 +70,10 @@ module Devops
# #
# * *Returns* : # * *Returns* :
# 200 - Deleted # 200 - Deleted
hash["DELETE"] = lambda { hash["DELETE"] = lambda {|user|
check_privileges("user", "w") check_privileges("user", "w")
projects = Devops::Db.connector.projects_by_user params[:user] Devops::API2_0::Handler::User.new(request).delete(user)
if !projects.empty? create_response("User '#{user}' removed")
str = ""
projects.each do |p|
p.deploy_envs.each do |e|
str+="#{p.id}.#{e.identifier} " if e.users.include? params[:user]
end
end
logger.info projects
raise DependencyError.new "Deleting is forbidden: User is included in #{str}"
#return [400, "Deleting is forbidden: User is included in #{str}"]
end
Devops::API2_0::Handler::User.new.delete(params[:user])
create_response("User '#{params[:user]}' removed")
} }
# Change user privileges # Change user privileges
@ -109,17 +91,14 @@ module Devops
# #
# * *Returns* : # * *Returns* :
# 200 - Updated # 200 - Updated
hash["PUT"] = lambda { hash["PUT"] = lambda {|user|
check_privileges("user", "w") check_privileges("user", "w")
data = create_object_from_json_body Devops::API2_0::Handler::User.new(request).change_user_privileges(user)
cmd = check_string(data["cmd"], "Parameter 'cmd' should be a not empty string", true) || ""
privileges = check_string(data["privileges"], "Parameter 'privileges' should be a not empty string", true) || ""
Devops::API2_0::Handler::User.new.change_user_privileges(params[:user], cmd, privileges)
create_response("Updated") create_response("Updated")
} }
app.multi_routes "/user/:user", {:headers => [:accept, :content_type]}, hash app.multi_routes "/user/:user", {:headers => [:accept, :content_type]}, hash
# Change user email/password # Change user email
# #
# * *Request* # * *Request*
# - method : PUT # - method : PUT
@ -128,23 +107,34 @@ module Devops
# - Content-Type: application/json # - Content-Type: application/json
# - body : # - body :
# { # {
# "email/password": "new user email/password", # "email": "new user email",
# } # }
# #
# * *Returns* : # * *Returns* :
# 200 - Updated # 200 - Updated
app.put_with_headers %r{\A/user/#{DevopsConfig::OBJECT_NAME}/(email|password)\z}, :headers => [:accept, :content_type] do#, &Devops::API2_0::Handler::User.change_user_email_or_password app.put_with_headers %r{\A/user/#{DevopsConfig::OBJECT_NAME}/email\z}, :headers => [:accept, :content_type] do |user|
check_privileges("user", "w") check_privileges("user", "w") unless request.env['REMOTE_USER'] == user
action = File.basename(request.path) Devops::API2_0::Handler::User.new(request).change_email(user)
u = File.basename(File.dirname(request.path)) create_response("Updated")
raise InvalidPrivileges.new("Access denied for '#{request.env['REMOTE_USER']}'") if u == Devops::Model::User::ROOT_USER_NAME and request.env['REMOTE_USER'] != Devops::Model::User::ROOT_USER_NAME end
check_privileges("user", "w") unless request.env['REMOTE_USER'] == u # Change user password
#
body = create_object_from_json_body # * *Request*
p = check_string(body[action], "Parameter '#{action}' must be a not empty string") # - method : PUT
h = Devops::API2_0::Handler::User.new # - headers :
h.send("change_#{action}", body.merge('user_id' => u)) # - Accept: application/json
# - Content-Type: application/json
# - body :
# {
# "password": "new user password",
# }
#
# * *Returns* :
# 200 - Updated
app.put_with_headers %r{\A/user/#{DevopsConfig::OBJECT_NAME}/password\z}, :headers => [:accept, :content_type] do |user|
check_privileges("user", "w") unless request.env['REMOTE_USER'] == user
Devops::API2_0::Handler::User.new(request).change_password(user)
create_response("Updated") create_response("Updated")
end end

View File

@ -4,8 +4,7 @@ require "commands/ssh"
module DeployCommands module DeployCommands
def deploy_server_proc def deploy_server_proc
lambda do |out, s, mongo, tags| lambda do |out, s, mongo, tags, deploy_info|
begin
old_tags_str = nil old_tags_str = nil
new_tags_str = nil new_tags_str = nil
unless tags.empty? unless tags.empty?
@ -18,34 +17,47 @@ module DeployCommands
cmd = KnifeCommands.tags_create(s.chef_node_name, new_tags_str) cmd = KnifeCommands.tags_create(s.chef_node_name, new_tags_str)
unless cmd[1] unless cmd[1]
m = "Error: Cannot add tags '#{new_tags_str}' to server '#{s.chef_node_name}'" m = "Error: Cannot add tags '#{new_tags_str}' to server '#{s.chef_node_name}'"
logger.error(m) DevopsLogger.logger.error(m)
out << m + "\n" out << m + "\n"
return 3 return 3
end end
logger.info("Set tags for '#{s.chef_node_name}': #{new_tags_str}") DevopsLogger.logger.info("Set tags for '#{s.chef_node_name}': #{new_tags_str}")
end end
k = mongo.key s.key k = mongo.key s.key
r = deploy_server out, s, k.path r = deploy_server out, s, k.path, deploy_info
unless tags.empty? unless tags.empty?
out << "Restore tags\n" out << "Restore tags\n"
cmd = KnifeCommands.tags_delete(s.chef_node_name, new_tags_str) cmd = KnifeCommands.tags_delete(s.chef_node_name, new_tags_str)
logger.info("Deleted tags for #{s.chef_node_name}: #{new_tags_str}") DevopsLogger.logger.info("Deleted tags for #{s.chef_node_name}: #{new_tags_str}")
cmd = KnifeCommands.tags_create(s.chef_node_name, old_tags_str) cmd = KnifeCommands.tags_create(s.chef_node_name, old_tags_str)
logger.info("Set tags for #{s.chef_node_name}: #{old_tags_str}") DevopsLogger.logger.info("Set tags for #{s.chef_node_name}: #{old_tags_str}")
end end
return r return r
rescue IOError => e
logger.error e.message
return 4
end
end end
end end
def deploy_server out, server, cert_path def deploy_server out, server, cert_path, deploy_info
out << "Before deploy hooks...\n"
res = server.run_hook(:before_deploy, out, deploy_info)
out << "Done\n"
out << "\nRun chef-client on '#{server.chef_node_name}'\n" out << "\nRun chef-client on '#{server.chef_node_name}'\n"
cmd = "chef-client" cmd = "chef-client --no-color"
if deploy_info["use_json_file"]
deploy_info.delete["use_json_file"]
out << "Build information:\n"
json = JSON.pretty_generate(deploy_info)
out << json
out << "\n"
file = "#{server.project}_#{server.deploy_env}_#{Time.new.to_i}"
dir = DevopsConfig.config[:project_info_dir]
File.open(File.join(dir, file), "w") do |f|
f.write json
end
out.flush if out.respond_to?(:flush)
cmd << " -j http://#{DevopsConfig.config[:address]}:#{DevopsConfig.config[:port]}/#{DevopsConfig.config[:url_prefix]}/v2.0/chef/client/data/#{file}"
end
ip = if server.public_ip.nil? ip = if server.public_ip.nil?
server.private_ip server.private_ip
else else
@ -55,7 +67,15 @@ module DeployCommands
out.flush if out.respond_to?(:flush) out.flush if out.respond_to?(:flush)
lline = KnifeCommands.ssh_stream(out, cmd, ip, server.remote_user, cert_path) lline = KnifeCommands.ssh_stream(out, cmd, ip, server.remote_user, cert_path)
r = /Chef\sClient\sfinished/i r = /Chef\sClient\sfinished/i
return (lline[r].nil? ? 1 : 0) if lline[r].nil?
1
else
out << "After deploy hooks...\n"
res = server.run_hook(:after_deploy, out, deploy_info)
out << "Done\n"
0
end
end end
end end

View File

@ -7,39 +7,41 @@ module ServerCommands
include DeployCommands include DeployCommands
def create_server_proc def create_server_proc
lambda do |out, s, provider, mongo| lambda do |out, s, provider|
mongo = ::Devops::Db.connector
begin begin
out << "Create server...\n" out << "Create server...\n"
out.flush if out.respond_to?(:flush) out.flush if out.respond_to?(:flush)
unless provider.create_server(s, out) unless provider.create_server(s, out)
return 3 return 3
end end
mongo.server_insert s s.create
out.flush if out.respond_to?(:flush) out.flush if out.respond_to?(:flush)
logger.info "Server with parameters: #{s.to_hash.inspect} is running" DevopsLogger.logger.info "Server with parameters: #{s.to_hash.inspect} is running"
key = mongo.key(s.key) key = mongo.key(s.key)
s.chef_node_name = provider.create_default_chef_node_name(s) if s.chef_node_name.nil? return two_phase_bootstrap(s, out, provider, key.path)
return two_phase_bootstrap(s, out, provider, mongo, key.path, logger)
rescue IOError => e rescue IOError => e
logger.error e.message DevopsLogger.logger.error e.message
logger.warn roll_back(s, provider) DevopsLogger.logger.warn roll_back(s, provider)
mongo.server_delete s.id mongo.server_delete s.id
return 5 return 5
end end
end end
end end
=begin
def create_server_proc def create_server_proc
lambda do |out, s, provider, mongo| lambda do |out, s, provider|
mongo = ::Devops::Db.connector
begin begin
out << "Create server...\n" out << "Create server...\n"
out.flush if out.respond_to?(:flush) out.flush if out.respond_to?(:flush)
unless provider.create_server(s, out) unless provider.create_server(s, out)
return 3 return 3
end end
mongo.server_insert s s.create
out.flush if out.respond_to?(:flush) out.flush if out.respond_to?(:flush)
logger.info "Server with parameters: #{s.to_hash.inspect} is running" DevopsLogger.logger.info "Server with parameters: #{s.to_hash.inspect} is running"
key = mongo.key(s.key) key = mongo.key(s.key)
s.chef_node_name = provider.create_default_chef_node_name(s) if s.chef_node_name.nil? s.chef_node_name = provider.create_default_chef_node_name(s) if s.chef_node_name.nil?
out << "\n\nBootstrap..." out << "\n\nBootstrap..."
@ -47,11 +49,11 @@ module ServerCommands
run_list = s.options[:run_list] run_list = s.options[:run_list]
s.options[:run_list] = provider.run_list s.options[:run_list] = provider.run_list
out << "\nBootstrap with provider run list: #{s.options[:run_list].inspect}" out << "\nBootstrap with provider run list: #{s.options[:run_list].inspect}"
status = bootstrap(s, out, key.path, logger) status = bootstrap(s, out, key.path)
out.flush if out.respond_to?(:flush) out.flush if out.respond_to?(:flush)
if status == 0 if status == 0
mongo.server_set_chef_node_name s mongo.server_set_chef_node_name s
logger.info "Server with id '#{s.id}' is bootstraped" DevopsLogger.logger.info "Server with id '#{s.id}' is bootstraped"
if check_server(s) if check_server(s)
out << "Server #{s.chef_node_name} is created" out << "Server #{s.chef_node_name} is created"
else else
@ -68,39 +70,41 @@ module ServerCommands
status = deploy_server(out, s, key.path) status = deploy_server(out, s, key.path)
if status != 0 if status != 0
msg = "Failed on chef-client with project run list, server with id '#{s.id}'" msg = "Failed on chef-client with project run list, server with id '#{s.id}'"
logger.error msg DevopsLogger.logger.error msg
out << "\n" + msg + "\n" out << "\n" + msg + "\n"
mongo.server_delete s.id mongo.server_delete s.id
end end
return status return status
else else
msg = "Failed while bootstraping server with id '#{s.id}'" msg = "Failed while bootstraping server with id '#{s.id}'"
logger.error msg DevopsLogger.logger.error msg
out << "\n" + msg + "\n" out << "\n" + msg + "\n"
out << roll_back(s, provider) out << roll_back(s, provider)
mongo.server_delete s.id mongo.server_delete s.id
status status
end end
rescue IOError => e rescue IOError => e
logger.error e.message DevopsLogger.logger.error e.message
logger.warn roll_back(s, provider) DevopsLogger.logger.warn roll_back(s, provider)
mongo.server_delete s.id mongo.server_delete s.id
return 5 return 5
end end
end end
end end
=end
def two_phase_bootstrap s, out, provider, mongo, cert_path, logger def two_phase_bootstrap s, out, provider, cert_path
mongo = ::Devops::Db.connector
out << "\n\nBootstrap..." out << "\n\nBootstrap..."
out.flush if out.respond_to?(:flush) out.flush if out.respond_to?(:flush)
run_list = s.options[:run_list] run_list = s.options[:run_list]
s.options[:run_list] = provider.run_list s.options[:run_list] = provider.run_list
out << "\nBootstrap with provider run list: #{s.options[:run_list].inspect}" out << "\nBootstrap with provider run list: #{s.options[:run_list].inspect}"
status = bootstrap(s, out, cert_path, logger) s.chef_node_name = provider.create_default_chef_node_name(s) if s.chef_node_name.nil?
status = bootstrap(s, out, cert_path)
out.flush if out.respond_to?(:flush) out.flush if out.respond_to?(:flush)
if status == 0 if status == 0
mongo.server_set_chef_node_name s DevopsLogger.logger.info "Server with id '#{s.id}' is bootstraped"
logger.info "Server with id '#{s.id}' is bootstraped"
if check_server(s) if check_server(s)
out << "Server #{s.chef_node_name} is created" out << "Server #{s.chef_node_name} is created"
else else
@ -117,12 +121,12 @@ module ServerCommands
status = deploy_server(out, s, cert_path) status = deploy_server(out, s, cert_path)
if status != 0 if status != 0
msg = "Failed on chef-client with project run list, server with id '#{s.id}'" msg = "Failed on chef-client with project run list, server with id '#{s.id}'"
logger.error msg DevopsLogger.logger.error msg
out << "\n" + msg + "\n" out << "\n" + msg + "\n"
end end
else else
msg = "Failed while bootstraping server with id '#{s.id}'" msg = "Failed while bootstraping server with id '#{s.id}'"
logger.error msg DevopsLogger.logger.error msg
out << "\n" + msg + "\n" out << "\n" + msg + "\n"
out << roll_back(s, provider) out << roll_back(s, provider)
mongo.server_delete s.id mongo.server_delete s.id
@ -130,7 +134,8 @@ module ServerCommands
return status return status
end end
def extract_servers provider, project, env, params, user, mongo def extract_servers provider, project, env, params, user
mongo = ::Devops::Db.connector
flavors = provider.flavors flavors = provider.flavors
projects = {} projects = {}
env_name = env.identifier env_name = env.identifier
@ -187,7 +192,7 @@ module ServerCommands
s.project = project_name s.project = project_name
s.deploy_env = env_name s.deploy_env = env_name
s.remote_user = image.remote_user s.remote_user = image.remote_user
s.chef_node_name = info[:name] || provider.create_default_chef_node_name(s) s.chef_node_name = info[:name]# || provider.create_default_chef_node_name(s)
s.key = info[:key] || provider.ssh_key s.key = info[:key] || provider.ssh_key
s.options = { s.options = {
:image => image.id, :image => image.id,
@ -215,7 +220,10 @@ module ServerCommands
KnifeCommands.chef_node_list.include?(s.chef_node_name) and KnifeCommands.chef_client_list.include?(s.chef_node_name) KnifeCommands.chef_node_list.include?(s.chef_node_name) and KnifeCommands.chef_client_list.include?(s.chef_node_name)
end end
def bootstrap s, out, cert_path, logger def bootstrap s, out, cert_path
out << "Before bootstrap hooks...\n"
res = s.run_hook(:before_bootstrap, out)
out << "Done\n"
if s.private_ip.nil? if s.private_ip.nil?
out << "Error: Private IP is null" out << "Error: Private IP is null"
return false return false
@ -249,7 +257,7 @@ module ServerCommands
if i == 120 if i == 120
out << "\nCan not connect to #{s.remote_user}@#{ip}" out << "\nCan not connect to #{s.remote_user}@#{ip}"
out << "\n" + res out << "\n" + res
logger.error "Can not connect with command 'ssh -i #{cert_path} #{s.remote_user}@#{ip}':\n#{res}" DevopsLogger.logger.error "Can not connect with command 'ssh -i #{cert_path} #{s.remote_user}@#{ip}':\n#{res}"
return false return false
end end
raise ArgumentError.new("Can not connect with command '#{cmd}' ") unless $?.success? raise ArgumentError.new("Can not connect with command '#{cmd}' ") unless $?.success?
@ -257,7 +265,17 @@ module ServerCommands
retry retry
end end
return KnifeCommands.knife_bootstrap(out, ip, bootstrap_options) r = KnifeCommands.knife_bootstrap(out, ip, bootstrap_options)
if r == 0
out << "Chef node name: #{s.chef_node_name}\n"
::Devops::Db.connector.server_set_chef_node_name s
out << "Chef node name has been updated\n"
out << "After bootstrap hooks...\n"
res = s.run_hook(:after_bootstrap, out)
out << "Done\n"
else
end
r
end end
def self.unbootstrap s, cert_path def self.unbootstrap s, cert_path
@ -266,7 +284,7 @@ module ServerCommands
r = `ssh -i #{cert_path} -q #{s.remote_user}@#{s.private_ip} rm -Rf /etc/chef` r = `ssh -i #{cert_path} -q #{s.remote_user}@#{s.private_ip} rm -Rf /etc/chef`
raise(r) unless $?.success? raise(r) unless $?.success?
rescue => e rescue => e
logger.error "Unbootstrap error: " + e.message DevopsLogger.logger.error "Unbootstrap error: " + e.message
i += 1 i += 1
sleep(1) sleep(1)
retry unless i == 5 retry unless i == 5
@ -275,15 +293,16 @@ module ServerCommands
nil nil
end end
def delete_server s, mongo, logger def delete_server s
mongo = ::Devops::Db.connector
if s.static? if s.static?
if !s.chef_node_name.nil? if !s.chef_node_name.nil?
cert = ::Devops::Db.connector.key s.key cert = mongo.key s.key
ServerCommands.unbootstrap(s, cert.path) ServerCommands.unbootstrap(s, cert.path)
end end
mongo.server_delete s.id mongo.server_delete s.id
msg = "Static server '#{s.id}' is removed" msg = "Static server '#{s.id}' is removed"
logger.info msg DevopsLogger.logger.info msg
return msg, nil return msg, nil
end end
r = delete_from_chef_server(s.chef_node_name) r = delete_from_chef_server(s.chef_node_name)
@ -292,12 +311,12 @@ module ServerCommands
r[:server] = provider.delete_server s r[:server] = provider.delete_server s
rescue Fog::Compute::OpenStack::NotFound, Fog::Compute::AWS::NotFound rescue Fog::Compute::OpenStack::NotFound, Fog::Compute::AWS::NotFound
r[:server] = "Server with id '#{s.id}' not found in '#{provider.name}' servers" r[:server] = "Server with id '#{s.id}' not found in '#{provider.name}' servers"
logger.warn r[:server] DevopsLogger.logger.warn r[:server]
end end
mongo.server_delete s.id mongo.server_delete s.id
info = "Server '#{s.id}' with name '#{s.chef_node_name}' for project '#{s.project}-#{s.deploy_env}' is removed" info = "Server '#{s.id}' with name '#{s.chef_node_name}' for project '#{s.project}-#{s.deploy_env}' is removed"
logger.info info DevopsLogger.logger.info info
r.each{|key, log| logger.info("#{key} - #{log}")} r.each{|key, log| DevopsLogger.logger.info("#{key} - #{log}")}
return info, r return info, r
end end

View File

@ -13,4 +13,8 @@ class DevopsLogger
def self.logger def self.logger
@_logger @_logger
end end
def self.logger= logger
@_logger = logger
end
end end

View File

@ -132,6 +132,10 @@ module Devops
h h
end end
def deploy_info deploy_env, build_number
{}
end
def to_hash_without_id def to_hash_without_id
h = {} h = {}
h["deploy_envs"] = self.deploy_envs.map {|e| e.to_hash} unless self.deploy_envs.nil? h["deploy_envs"] = self.deploy_envs.map {|e| e.to_hash} unless self.deploy_envs.nil?

View File

@ -10,7 +10,7 @@ module Devops
PROJECT_TEST_TYPE = 4 PROJECT_TEST_TYPE = 4
STACK_TYPE = 5 STACK_TYPE = 5
attr_accessor :id, :file, :created_at, :created_by, :project, :deploy_env, :type attr_accessor :id, :file, :created_at, :updated_at, :created_by, :project, :deploy_env, :type, :chef_node_name, :host
def initialize r def initialize r
self.id = r["_id"] self.id = r["_id"]
@ -20,16 +20,23 @@ module Devops
self.deploy_env = r["deploy_env"] self.deploy_env = r["deploy_env"]
self.type = r["type"] self.type = r["type"]
self.created_at = r["created_at"] self.created_at = r["created_at"]
self.chef_node_name = r["chef_node_name"]
self.host = r["host"]
self.created_at = r["created_at"].localtime unless r["created_at"].nil?
self.updated_at = r["updated_at"].localtime unless r["updated_at"].nil?
end end
def to_hash_without_id def to_hash_without_id
{ {
"file" => self.file, "file" => self.file,
"created_at" => self.created_at, "created_at" => self.created_at,
"updated_at" => self.updated_at,
"created_by" => self.created_by, "created_by" => self.created_by,
"project" => self.project, "project" => self.project,
"deploy_env" => self.deploy_env, "deploy_env" => self.deploy_env,
"type" => self.type "type" => self.type,
"chef_node_name" => self.chef_node_name,
"host" => self.host
} }
end end

View File

@ -4,6 +4,21 @@ module Devops
module Model module Model
class Server < MongoModel class Server < MongoModel
include Hooks
#params:
# out - container for output data
# deploy_info - hash with deploy data
define_hook :before_deploy
define_hook :after_deploy
define_hook :before_create
define_hook :after_create
#params:
# out - container for output data
define_hook :before_bootstrap
define_hook :after_bootstrap
attr_accessor :provider, :chef_node_name, :id, :remote_user, :project, :deploy_env, :private_ip, :public_ip, :created_at, :without_bootstrap, :created_by, :reserved_by attr_accessor :provider, :chef_node_name, :id, :remote_user, :project, :deploy_env, :private_ip, :public_ip, :created_at, :without_bootstrap, :created_by, :reserved_by
attr_accessor :options, :static, :key attr_accessor :options, :static, :key
@ -39,6 +54,14 @@ module Devops
self.reserved_by = s["reserved_by"] self.reserved_by = s["reserved_by"]
end end
def create
res = {}
res[:before] = self.run_hook :before_create
Devops::Db.connector.server_insert self
res[:after] = self.run_hook :after_create
res
end
def validate! def validate!
super super
true true

View File

@ -0,0 +1,3 @@
class DeployInfoError < Exception
end

View File

@ -12,7 +12,8 @@ class BootstrapWorker < Worker
include ServerCommands include ServerCommands
def perform(dir, e_provider, server, owner, conf) def perform(dir, e_provider, server, owner, conf)
call(conf, e_provider, dir) do |mongo, provider, out, file| call(conf, e_provider, dir) do |provider, out, file|
mongo = Devops::Db.connector
s = Server.new(server) s = Server.new(server)
s.options = convert_config(server["options"]) s.options = convert_config(server["options"])
o = { o = {
@ -27,12 +28,8 @@ class BootstrapWorker < Worker
key = mongo.key(s.key) key = mongo.key(s.key)
out << "\nBootstrap with run list: #{s.options[:run_list].inspect}" out << "\nBootstrap with run list: #{s.options[:run_list].inspect}"
status = bootstrap(s, out, key.path, logger) status = bootstrap(s, out, key.path)
if status == 0 mongo.set_report_server_data(jid, s.chef_node_name, s.public_ip || s.private_ip)
out << "Chef node name: #{s.chef_node_name}\n"
mongo.server_set_chef_node_name s
out << "Chef node name has been updated\n"
end
status status
end end
end end

View File

@ -12,7 +12,8 @@ class CreateServerWorker < Worker
include ServerCommands include ServerCommands
def perform(dir, e_provider, server, owner, conf) def perform(dir, e_provider, server, owner, conf)
call(conf, e_provider, dir) do |mongo, provider, out, file| call(conf, e_provider, dir) do |provider, out, file|
mongo = Devops::Db.connector
s = Server.new(server) s = Server.new(server)
s.options = convert_config(server["options"]) s.options = convert_config(server["options"])
o = { o = {
@ -25,7 +26,7 @@ class CreateServerWorker < Worker
} }
mongo.save_report(Report.new(o)) mongo.save_report(Report.new(o))
status = create_server_proc.call(out, s, provider, mongo) status = create_server_proc.call(out, s, provider)
status status
end end
end end

View File

@ -1,6 +1,3 @@
#root = File.join(File.dirname(__FILE__), "..")
#$LOAD_PATH.push root unless $LOAD_PATH.include? root
require File.join(File.dirname(__FILE__), "worker") require File.join(File.dirname(__FILE__), "worker")
require "commands/deploy" require "commands/deploy"
@ -10,8 +7,9 @@ require "db/mongo/models/report"
class DeployWorker < Worker class DeployWorker < Worker
include DeployCommands include DeployCommands
def perform(dir, server, tags, owner, conf) def perform(dir, server, tags, owner, conf, deploy_info)
call(conf, nil, dir) do |mongo, provider, out, file| call(conf, nil, dir) do |provider, out, file|
mongo = Devops::Db.connector
s = Server.new(server) s = Server.new(server)
o = { o = {
"file" => file, "file" => file,
@ -19,11 +17,14 @@ class DeployWorker < Worker
"created_by" => owner, "created_by" => owner,
"project" => s.project, "project" => s.project,
"deploy_env" => s.deploy_env, "deploy_env" => s.deploy_env,
"type" => Report::DEPLOY_TYPE "type" => Report::DEPLOY_TYPE,
"status" => STATUS::RUNNING,
"chef_node_name" => s.chef_node_name,
"host" => s.public_ip || s.private_ip
} }
mongo.save_report(Report.new(o)) mongo.save_report(Report.new(o))
status = deploy_server_proc.call(out, s, mongo, tags) status = deploy_server_proc.call(out, s, tags, deploy_info)
status status
end end
end end

View File

@ -13,8 +13,9 @@ class ProjectTestWorker < Worker
include StatusCommands include StatusCommands
def perform(dir, params, conf) def perform(dir, params, conf)
call(conf, nil, dir) do |mongo, provider, out, file| call(conf, nil, dir) do |provider, out, file|
logger.info "Test project '#{params["project"]}' and env '#{params["env"]}' (user - #{params["user"]})" DevopsLogger.logger.info "Test project '#{params["project"]}' and env '#{params["env"]}' (user - #{params["user"]})"
mongo = Devops::Db.connector
project = mongo.project(params["project"]) project = mongo.project(params["project"])
env = project.deploy_env(params["env"]) env = project.deploy_env(params["env"])
user = params["user"] user = params["user"]
@ -29,7 +30,7 @@ class ProjectTestWorker < Worker
mongo.save_report(Report.new(o)) mongo.save_report(Report.new(o))
provider = ::Provider::ProviderFactory.get(env.provider) provider = ::Provider::ProviderFactory.get(env.provider)
servers = extract_servers(provider, project, env, {}, user, mongo) servers = extract_servers(provider, project, env, {}, user)
result = {:servers => []} result = {:servers => []}
project.deploy_envs = [ env ] project.deploy_envs = [ env ]
result[:project] = project.to_hash result[:project] = project.to_hash
@ -51,7 +52,7 @@ class ProjectTestWorker < Worker
key = mongo.key(s.key) key = mongo.key(s.key)
out << "\n=== Bootstrap ===\n" out << "\n=== Bootstrap ===\n"
out.flush out.flush
r = bootstrap(s, out, key.path, logger) r = bootstrap(s, out, key.path)
t1 = Time.now t1 = Time.now
sr[:chef_node_name] = s.chef_node_name sr[:chef_node_name] = s.chef_node_name
if r == 0 if r == 0

View File

@ -2,7 +2,6 @@ require "providers/provider_factory"
require "commands/stack" require "commands/stack"
require "db/mongo/models/stack/stack_factory" require "db/mongo/models/stack/stack_factory"
require "db/mongo/models/report" require "db/mongo/models/report"
require 'workers/workers_storage'
class StackSyncWorker < Worker class StackSyncWorker < Worker
include StackCommands include StackCommands
@ -11,7 +10,8 @@ class StackSyncWorker < Worker
# :provider # :provider
# :stack_id # :stack_id
def perform(options) def perform(options)
call(options['config'], options['provider'], options['dir']) do |mongo, provider, out, file| call(options['config'], options['provider'], options['dir']) do |provider, out, file|
mongo = Devops::Db.connector
stack = mongo.stack(options['stack_id']) stack = mongo.stack(options['stack_id'])
o = { o = {
"file" => file, "file" => file,

View File

@ -6,8 +6,11 @@ require "sidekiq/api"
require "fileutils" require "fileutils"
require "db/mongo/mongo_connector" require "core/devops-config"
require "core/devops-logger"
require "core/devops-db"
require "providers/provider_factory" require "providers/provider_factory"
require 'workers/workers_storage'
class Worker class Worker
include Sidekiq::Worker include Sidekiq::Worker
@ -23,16 +26,10 @@ class Worker
def convert_config conf def convert_config conf
config = {} config = {}
conf.each {|k,v| config[k.is_a?(String) ? k.to_sym : k] = v} conf.each {|k,v| config[k.is_a?(String) ? k.to_sym : k] = v}
logger.debug "Config: #{config.inspect}" DevopsLogger.logger.debug "Config: #{config.inspect}"
config config
end end
def mongo_connector config
mongo = MongoConnector.new(config[:mongo_db], config[:mongo_host], config[:mongo_port], config[:mongo_user], config[:mongo_password])
logger.debug "Mongo connector: #{mongo.inspect}"
mongo
end
def set_status id, status def set_status id, status
Sidekiq.redis {|con| con.hset "devops", id, status} Sidekiq.redis {|con| con.hset "devops", id, status}
end end
@ -45,27 +42,30 @@ class Worker
end end
def call conf, e_provider, dir def call conf, e_provider, dir
DevopsLogger.logger = logger
FileUtils.mkdir_p(dir) unless File.exists?(dir) FileUtils.mkdir_p(dir) unless File.exists?(dir)
set_status jid, "init" set_status jid, "init"
config = convert_config(conf) DevopsConfig.config = convert_config(conf)
file = File.join(dir, jid) file = File.join(dir, jid)
error = nil error = nil
mongo = nil
provider = nil provider = nil
begin begin
mongo = mongo_connector(config) Devops::Db.init
unless e_provider.nil? unless e_provider.nil?
::Provider::ProviderFactory.init(config) ::Provider::ProviderFactory.init(config)
provider = ::Provider::ProviderFactory.get(e_provider) provider = ::Provider::ProviderFactory.get(e_provider)
end end
rescue Exception => e rescue Exception => e
error = e error = e
DevopsLogger.logger.error e.message
return
end end
mongo = ::Devops::Db.connector
File.open(file, "w") do |out| File.open(file, "w") do |out|
begin begin
set_status jid, STATUS::RUNNING set_status jid, STATUS::RUNNING
raise error unless error.nil? raise error unless error.nil?
status = yield(mongo, provider, out, file) status = yield(provider, out, file)
status = (status == 0 ? STATUS::COMPLETED : STATUS::FAILED) status = (status == 0 ? STATUS::COMPLETED : STATUS::FAILED)
set_status jid, status set_status jid, status
mongo.set_report_status(jid, status) mongo.set_report_status(jid, status)