#871: ability to delete all project servers

This commit is contained in:
Anton Chuchkalov 2015-11-13 17:22:55 +03:00
parent 0b3b10e1df
commit df38e86117
11 changed files with 138 additions and 12 deletions

View File

@ -5,8 +5,8 @@ module Outputtable
end end
def outputter def outputter
raise 'You should use "output_with" method to define outputter' unless defined?(outputter_class) raise 'You should use "output_with" method to define outputter' unless self.class.outputter_class
@outputter ||= outputter_class.new(data_to_output, options.merge(current_command: current_command)) @outputter ||= self.class.outputter_class.new(data_to_output, options.merge(current_command: current_command))
end end
def output(options={}) def output(options={})
@ -19,10 +19,9 @@ module Outputtable
end end
module ClassMethods module ClassMethods
attr_reader :outputter_class
def output_with(klass) def output_with(klass)
define_method :outputter_class do @outputter_class = klass
klass
end
end end
end end

View File

@ -84,6 +84,10 @@ class Project < Handler
when "test" when "test"
self.options = @options_parser.test_options self.options = @options_parser.test_options
test_handler @options_parser.args test_handler @options_parser.args
when "delete_servers"
self.options = @options_parser.delete_servers_options
delete_servers_handler @options_parser.args
output(output_type: :delete_servers)
else else
@options_parser.invalid_command @options_parser.invalid_command
end end
@ -440,4 +444,18 @@ protected
@list || @show || @servers || @test @list || @show || @servers || @test
end end
def delete_servers_handler(args)
project, env = args[2], args[3]
if error = inspect_parameters(@options_parser.delete_servers_params, project, env)
@options_parser.invalid_delete_servers_command
abort(error)
end
body = {
deploy_env: env,
dry_run: @options[:dry_run]
}
@list = delete("/project/#{project}/servers", body)
end
end end

View File

@ -3,7 +3,7 @@ require "set"
class ProjectOptions < CommonOptions class ProjectOptions < CommonOptions
commands :create, :delete, :deploy, :list, {:multi => [:create]}, :servers, :stacks, {:set => [:run_list]}, :show, :test, :update, {:user => [:add, :delete]} commands :create, :delete, :deploy, :list, {:multi => [:create]}, :servers, :stacks, {:set => [:run_list]}, :show, :test, :update, {:user => [:add, :delete]}, :delete_servers
def initialize args, def_options def initialize args, def_options
super(args, def_options) super(args, def_options)
@ -23,6 +23,7 @@ class ProjectOptions < CommonOptions
self.user_add_params = [id, "USER_NAME", "[USER_NAME ...]"] self.user_add_params = [id, "USER_NAME", "[USER_NAME ...]"]
self.user_delete_params = [id, "USER_NAME", "[USER_NAME ...]"] self.user_delete_params = [id, "USER_NAME", "[USER_NAME ...]"]
self.test_params = [id, env] self.test_params = [id, env]
self.delete_servers_params = [id, "[#{env}]"]
end end
def create_options def create_options
@ -65,7 +66,6 @@ class ProjectOptions < CommonOptions
# end # end
end end
end end
def user_add_options def user_add_options
@ -94,4 +94,10 @@ class ProjectOptions < CommonOptions
end end
end end
def delete_servers_options
self.options do |parser, options|
parser.recognize_option_value(:dry_run, 'project', type: :switch, default: false, switch_value: true, i18n_scope: 'delete_servers')
end
end
end end

View File

@ -27,6 +27,8 @@ module Output
when :test when :test
title = I18n.t("output.title.project.test", :project => ARGV[2], :env => ARGV[3]) title = I18n.t("output.title.project.test", :project => ARGV[2], :env => ARGV[3])
create_test(@data) create_test(@data)
when :delete_servers
return delete_servers_output
else else
title = I18n.t("output.title.project.list") title = I18n.t("output.title.project.list")
create_list(@data) create_list(@data)
@ -149,5 +151,31 @@ module Output
headers_and_rows(stacks, fields_to_output) headers_and_rows(stacks, fields_to_output)
end end
def delete_servers_output
output = ''
if @options[:dry_run]
if @data['to_delete'].empty?
output << "There are no servers to delete."
else
output << "Servers to delete:\n----\n"
output << @data['to_delete'].join("\n")
end
return output
end
if @data['deleted'].empty?
output << 'There are no deleted servers.'
else
output << "Deleted servers:\n----\n"
output << @data['deleted'].join("\n")
end
if !@data['failed'].empty?
output << "\nThere were errors during deleting these servers:\n----\n"
output << @data['failed'].join("\n")
end
output
end
end end
end end

View File

@ -343,6 +343,8 @@ en:
deploy_env: "Delete user from deploy environment" deploy_env: "Delete user from deploy environment"
deploy: deploy:
servers: "Servers list (comma separated) for deploy" servers: "Servers list (comma separated) for deploy"
delete_servers:
dry_run: "Only show servers to delete, no real deleting"
script: script:
params: Script arguments (comma separated list) params: Script arguments (comma separated list)
server: server:

View File

@ -3,6 +3,8 @@ require "db/mongo/models/project"
require "workers/project_test_worker" require "workers/project_test_worker"
require "app/api2/parsers/project" require "app/api2/parsers/project"
require "lib/project/type/types_factory" require "lib/project/type/types_factory"
require "lib/executors/server_executor"
require_relative "../helpers/version_2.rb" require_relative "../helpers/version_2.rb"
require_relative "request_handler" require_relative "request_handler"
@ -298,6 +300,32 @@ module Devops
return [jid] return [jid]
end end
def delete_project_servers(project_id)
env_id, dry_run = parser.delete_project_servers
Devops::Db.connector.project(project_id)
servers = Devops::Db.connector.servers(project_id, env_id)
info = {to_delete: servers.map(&:id)}
if !dry_run
info.merge!(delete_chosen_servers!(servers))
end
info
end
private
def delete_chosen_servers!(servers)
deleted, failed = [], []
servers.each do |server|
begin
Devops::Executor::ServerExecutor.new(server, '').delete_server
deleted << server.id
rescue
failed << server.id
end
end
{deleted: deleted, failed: failed}
end
end end
end end
end end

View File

@ -28,6 +28,14 @@ module Devops
check_param val, String, msg, _nil, empty check_param val, String, msg, _nil, empty
end end
def check_boolean val, msg
begin
check_param val, TrueClass, msg, false, true
rescue
check_param val, FalseClass, msg, false, true
end
end
def check_array val, msg, vals_type=String, _nil=false, empty=false def check_array val, msg, vals_type=String, _nil=false, empty=false
check_param val, Array, msg, _nil, empty check_param val, Array, msg, _nil, empty
val.each {|v| raise Devops::ValidationError.new(msg) unless v.is_a?(vals_type)} unless val.nil? val.each {|v| raise Devops::ValidationError.new(msg) unless v.is_a?(vals_type)} unless val.nil?
@ -60,7 +68,7 @@ module Devops
end end
end end
if val.is_a?(type) if val.is_a?(type)
raise Devops::ValidationError.new(msg) if val.empty? and !empty raise Devops::ValidationError.new(msg) if !empty && val.empty?
val val
else else
raise Devops::ValidationError.new(msg) raise Devops::ValidationError.new(msg)

View File

@ -97,6 +97,13 @@ module Devops
servers = check_array(obj["servers"], "Parameter 'servers' should be a not empty array of strings", String, true) servers = check_array(obj["servers"], "Parameter 'servers' should be a not empty array of strings", String, true)
return deploy_env, servers return deploy_env, servers
end end
def delete_project_servers
body = create_object_from_json_body
dry_run = check_boolean(body["dry_run"], "Parameter 'dry_run' must be a boolean")
deploy_env = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string", true)
[deploy_env, dry_run]
end
end end
end end
end end

View File

@ -166,10 +166,37 @@ module Devops
# "id": "nstance id" # "id": "nstance id"
# } # }
# ] # ]
app.get_with_headers "/project/:project/servers", :headers => [:accept] do |project| servers_routes_hash = {}
servers_routes_hash["GET"] = lambda { |project|
check_privileges("project", "r") check_privileges("project", "r")
json Devops::API2_0::Handler::Project.new(request).project_servers(project).map(&:to_hash) json Devops::API2_0::Handler::Project.new(request).project_servers(project).map(&:to_hash)
end }
# Deletes project servers
#
# * *Request*
# - method : PATCH
# - headers :
# - Accept: application/json
# - Content-Type: application/json
# - body :
# {
# "dry_run": false # set to true if you'd like to just see list of servers to delete
# "deploy_env": null # set to env's identifier to delete that env's servers
# }
#
# * *Returns* :
# 200 -
# {
# "to_delete": ['server1', 'server2'],
# "deleted": ['server1'],
# "failed": ['server2']
# }
servers_routes_hash["DELETE"] = lambda { |project_id|
check_privileges("project", "w")
json Devops::API2_0::Handler::Project.new(request).delete_project_servers(project_id)
}
app.multi_routes "/project/:project/servers", {}, servers_routes_hash
# Get project stacks # Get project stacks
# #

View File

@ -116,7 +116,9 @@ module Devops
return 0 return 0
end end
rescue => e rescue => e
@out << e.message @out.puts e.message
@out.puts e.backtrace.join("\n")
DevopsLogger.logger.error e.message DevopsLogger.logger.error e.message
roll_back roll_back
mongo.server_delete @server.id mongo.server_delete @server.id

View File

@ -110,7 +110,8 @@ module Provider
vpcId = nil vpcId = nil
unless subnets.empty? unless subnets.empty?
options["SubnetId"] = subnets[0] options["SubnetId"] = subnets[0]
vpcId = self.networks.detect{|n| n["name"] == options["SubnetId"]}["vpcId"] network = self.networks.detect{|n| n["name"] == options["SubnetId"]}
vpcId = network["vpcId"] if network
if vpcId.nil? if vpcId.nil?
out << "Can not get 'vpcId' by subnet name '#{options["SubnetId"]}'\n" out << "Can not get 'vpcId' by subnet name '#{options["SubnetId"]}'\n"
return false return false