From 0b3b10e1dfc7a97c69d96b5d2c03397d57264dad Mon Sep 17 00:00:00 2001 From: Anton Martynov Date: Wed, 11 Nov 2015 14:35:27 +0300 Subject: [PATCH 1/4] #840: remove json_file from deploy_info --- devops-service/lib/executors/server_executor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devops-service/lib/executors/server_executor.rb b/devops-service/lib/executors/server_executor.rb index 1d57df3..9532cf4 100644 --- a/devops-service/lib/executors/server_executor.rb +++ b/devops-service/lib/executors/server_executor.rb @@ -360,7 +360,7 @@ module Devops deploy_info.delete("use_json_file") json = nil dir = DevopsConfig.config[:project_info_dir] - file = deploy_info["json_file"] || "#{@server.project}_#{@server.deploy_env}_#{Time.new.to_i}" + file = deploy_info.delete("json_file") || "#{@server.project}_#{@server.deploy_env}_#{Time.new.to_i}" path = File.join(dir, file) if File.exists?(path) json = File.read(path) From df38e8611702975a1eb6e282848d9ee284f66c5a Mon Sep 17 00:00:00 2001 From: Anton Chuchkalov Date: Fri, 13 Nov 2015 17:22:55 +0300 Subject: [PATCH 2/4] #871: ability to delete all project servers --- .../handler/helpers/outputtable.rb | 9 +++--- .../lib/devops-client/handler/project.rb | 18 +++++++++++ .../devops-client/options/project_options.rb | 10 ++++-- .../lib/devops-client/output/project.rb | 28 +++++++++++++++++ devops-client/locales/en.yml | 2 ++ devops-service/app/api2/handlers/project.rb | 28 +++++++++++++++++ devops-service/app/api2/helpers/parser.rb | 10 +++++- devops-service/app/api2/parsers/project.rb | 7 +++++ devops-service/app/api2/routes/project.rb | 31 +++++++++++++++++-- .../lib/executors/server_executor.rb | 4 ++- devops-service/providers/ec2.rb | 3 +- 11 files changed, 138 insertions(+), 12 deletions(-) diff --git a/devops-client/lib/devops-client/handler/helpers/outputtable.rb b/devops-client/lib/devops-client/handler/helpers/outputtable.rb index e7b948c..1f78db3 100644 --- a/devops-client/lib/devops-client/handler/helpers/outputtable.rb +++ b/devops-client/lib/devops-client/handler/helpers/outputtable.rb @@ -5,8 +5,8 @@ module Outputtable end def outputter - raise 'You should use "output_with" method to define outputter' unless defined?(outputter_class) - @outputter ||= outputter_class.new(data_to_output, options.merge(current_command: current_command)) + raise 'You should use "output_with" method to define outputter' unless self.class.outputter_class + @outputter ||= self.class.outputter_class.new(data_to_output, options.merge(current_command: current_command)) end def output(options={}) @@ -19,10 +19,9 @@ module Outputtable end module ClassMethods + attr_reader :outputter_class def output_with(klass) - define_method :outputter_class do - klass - end + @outputter_class = klass end end diff --git a/devops-client/lib/devops-client/handler/project.rb b/devops-client/lib/devops-client/handler/project.rb index 80feb88..bf6b7aa 100644 --- a/devops-client/lib/devops-client/handler/project.rb +++ b/devops-client/lib/devops-client/handler/project.rb @@ -84,6 +84,10 @@ class Project < Handler when "test" self.options = @options_parser.test_options 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 @options_parser.invalid_command end @@ -440,4 +444,18 @@ protected @list || @show || @servers || @test 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 diff --git a/devops-client/lib/devops-client/options/project_options.rb b/devops-client/lib/devops-client/options/project_options.rb index 96ad738..3bbd72e 100644 --- a/devops-client/lib/devops-client/options/project_options.rb +++ b/devops-client/lib/devops-client/options/project_options.rb @@ -3,7 +3,7 @@ require "set" 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 super(args, def_options) @@ -23,6 +23,7 @@ class ProjectOptions < CommonOptions self.user_add_params = [id, "USER_NAME", "[USER_NAME ...]"] self.user_delete_params = [id, "USER_NAME", "[USER_NAME ...]"] self.test_params = [id, env] + self.delete_servers_params = [id, "[#{env}]"] end def create_options @@ -65,7 +66,6 @@ class ProjectOptions < CommonOptions # end end - end def user_add_options @@ -94,4 +94,10 @@ class ProjectOptions < CommonOptions 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 diff --git a/devops-client/lib/devops-client/output/project.rb b/devops-client/lib/devops-client/output/project.rb index 256fd59..e6151cb 100644 --- a/devops-client/lib/devops-client/output/project.rb +++ b/devops-client/lib/devops-client/output/project.rb @@ -27,6 +27,8 @@ module Output when :test title = I18n.t("output.title.project.test", :project => ARGV[2], :env => ARGV[3]) create_test(@data) + when :delete_servers + return delete_servers_output else title = I18n.t("output.title.project.list") create_list(@data) @@ -149,5 +151,31 @@ module Output headers_and_rows(stacks, fields_to_output) 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 diff --git a/devops-client/locales/en.yml b/devops-client/locales/en.yml index 7e61cf8..58f1d9f 100644 --- a/devops-client/locales/en.yml +++ b/devops-client/locales/en.yml @@ -343,6 +343,8 @@ en: deploy_env: "Delete user from deploy environment" deploy: servers: "Servers list (comma separated) for deploy" + delete_servers: + dry_run: "Only show servers to delete, no real deleting" script: params: Script arguments (comma separated list) server: diff --git a/devops-service/app/api2/handlers/project.rb b/devops-service/app/api2/handlers/project.rb index 68d0b39..c771eae 100644 --- a/devops-service/app/api2/handlers/project.rb +++ b/devops-service/app/api2/handlers/project.rb @@ -3,6 +3,8 @@ require "db/mongo/models/project" require "workers/project_test_worker" require "app/api2/parsers/project" require "lib/project/type/types_factory" +require "lib/executors/server_executor" + require_relative "../helpers/version_2.rb" require_relative "request_handler" @@ -298,6 +300,32 @@ module Devops return [jid] end + def delete_project_servers(project_id) + env_id, dry_run = parser.delete_project_servers + Devops::Db.connector.project(project_id) + servers = Devops::Db.connector.servers(project_id, env_id) + info = {to_delete: servers.map(&:id)} + if !dry_run + info.merge!(delete_chosen_servers!(servers)) + end + info + end + + private + + def delete_chosen_servers!(servers) + 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 diff --git a/devops-service/app/api2/helpers/parser.rb b/devops-service/app/api2/helpers/parser.rb index ebf0d5e..dc5b4d3 100644 --- a/devops-service/app/api2/helpers/parser.rb +++ b/devops-service/app/api2/helpers/parser.rb @@ -28,6 +28,14 @@ module Devops check_param val, String, msg, _nil, empty 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 check_param val, Array, msg, _nil, empty 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 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 else raise Devops::ValidationError.new(msg) diff --git a/devops-service/app/api2/parsers/project.rb b/devops-service/app/api2/parsers/project.rb index dc2a8e9..08b0e4c 100644 --- a/devops-service/app/api2/parsers/project.rb +++ b/devops-service/app/api2/parsers/project.rb @@ -97,6 +97,13 @@ module Devops servers = check_array(obj["servers"], "Parameter 'servers' should be a not empty array of strings", String, true) return deploy_env, servers 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 diff --git a/devops-service/app/api2/routes/project.rb b/devops-service/app/api2/routes/project.rb index edb48c1..7b66b61 100644 --- a/devops-service/app/api2/routes/project.rb +++ b/devops-service/app/api2/routes/project.rb @@ -166,10 +166,37 @@ module Devops # "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") 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 # diff --git a/devops-service/lib/executors/server_executor.rb b/devops-service/lib/executors/server_executor.rb index 9532cf4..cb983d1 100644 --- a/devops-service/lib/executors/server_executor.rb +++ b/devops-service/lib/executors/server_executor.rb @@ -116,7 +116,9 @@ module Devops return 0 end rescue => e - @out << e.message + @out.puts e.message + @out.puts e.backtrace.join("\n") + DevopsLogger.logger.error e.message roll_back mongo.server_delete @server.id diff --git a/devops-service/providers/ec2.rb b/devops-service/providers/ec2.rb index 52644f8..3711e35 100644 --- a/devops-service/providers/ec2.rb +++ b/devops-service/providers/ec2.rb @@ -110,7 +110,8 @@ module Provider vpcId = nil unless subnets.empty? 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? out << "Can not get 'vpcId' by subnet name '#{options["SubnetId"]}'\n" return false From 1c9fca2017156cd3ab413c31fd4ce3792c77792a Mon Sep 17 00:00:00 2001 From: Anton Chuchkalov Date: Fri, 13 Nov 2015 18:49:32 +0300 Subject: [PATCH 3/4] add ability to use blank password in devops-client conf --- devops-client/lib/devops-client.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devops-client/lib/devops-client.rb b/devops-client/lib/devops-client.rb index 5004cf1..fd6c6e7 100644 --- a/devops-client/lib/devops-client.rb +++ b/devops-client/lib/devops-client.rb @@ -33,7 +33,7 @@ module DevopsClient if config[:host].nil? abort(I18n.t("config.invalid.host"), :file => @@config_file) end - [:api, :username, :password].each do |key| + [:api, :username].each do |key| if config[key].nil? or config[key].empty? abort(I18n.t("config.invalid.empty", :file => @@config_file, :key => key)) end From 8ea70f707231541f098350412899825f330ce3c6 Mon Sep 17 00:00:00 2001 From: Anton Chuchkalov Date: Fri, 13 Nov 2015 19:44:00 +0300 Subject: [PATCH 4/4] #871: ask questions before deleting --- .../lib/devops-client/handler/project.rb | 23 ++++++++++++++++++- .../lib/devops-client/output/project.rb | 9 -------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/devops-client/lib/devops-client/handler/project.rb b/devops-client/lib/devops-client/handler/project.rb index bf6b7aa..dd261d3 100644 --- a/devops-client/lib/devops-client/handler/project.rb +++ b/devops-client/lib/devops-client/handler/project.rb @@ -451,11 +451,32 @@ protected abort(error) end + ask_for_delete_servers(project, env) body = { deploy_env: env, - dry_run: @options[:dry_run] + dry_run: false } @list = delete("/project/#{project}/servers", body) end + private + + def ask_for_delete_servers(project, env) + body = { + deploy_env: env, + dry_run: true + } + to_delete = delete("/project/#{project}/servers", body)['to_delete'] + if to_delete.empty? + abort "There are no servers to delete." + else + puts "Servers to delete:\n----\n" + puts to_delete.join("\n") + puts '----' + end + if @options[:dry_run] || !question('Are you sure to delete them? ') + abort + end + end + end diff --git a/devops-client/lib/devops-client/output/project.rb b/devops-client/lib/devops-client/output/project.rb index e6151cb..b137aad 100644 --- a/devops-client/lib/devops-client/output/project.rb +++ b/devops-client/lib/devops-client/output/project.rb @@ -153,15 +153,6 @@ module Output 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.'