From ca21238de288067d7a4eb3621922bb7361030d74 Mon Sep 17 00:00:00 2001 From: amartynov Date: Fri, 23 Oct 2015 14:54:56 +0300 Subject: [PATCH 01/23] #840: refactored --- devops-service/app/api2/handlers/server.rb | 36 +++++++++---------- .../lib/executors/server_executor.rb | 4 +++ 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/devops-service/app/api2/handlers/server.rb b/devops-service/app/api2/handlers/server.rb index 18b2e35..cddbf54 100644 --- a/devops-service/app/api2/handlers/server.rb +++ b/devops-service/app/api2/handlers/server.rb @@ -119,17 +119,15 @@ module Devops # TODO: check bootstrap template name def bootstrap_server_stream out - s, rl, bt = prepare_bootstrap_server + options = prepare_bootstrap_server + s = options.delete[:server] status = [] cert = Devops::Db.connector.key s.key DevopsLogger.logger.debug "Bootstrap certificate path: #{cert.path}" #bootstrap s, out, cert.path, logger - options = { - :bootstrap_template => bt, - :cert_path => cert.path, - :run_list => rl - } - r = two_phase_bootstrap s, options, out + options[:cert_path] = cert.path + executor = Devops::Executor::ServerExecutor.new(s, out) + r = executor.two_phase_bootstrap(options) str = nil r = if check_server(s) Devops::Db.connector.server_set_chef_node_name s @@ -148,17 +146,16 @@ module Devops end def bootstrap_server - server, rl, bootstrap_template = prepare_bootstrap_server - dir = DevopsConfig[:report_dir_v2] - files = [] - uri = URI.parse(@request.url) + options = prepare_bootstrap_server + s = options.delete[:server] + options[:provider_name] = s.provider + options[:server_attrs] = s.to_mongo_hash + options[:owner] = parser.current_user +# dir = DevopsConfig[:report_dir_v2] +# files = [] +# uri = URI.parse(@request.url) - uri = Worker.start_async(BootstrapWorker, @request, - provider_name: server.provider, - server_attrs: server.to_mongo_hash, - bootstrap_template: bootstrap_template, - owner: parser.current_user - ) + uri = Worker.start_async(BootstrapWorker, @request, options) sleep 1 [uri] @@ -171,6 +168,7 @@ module Devops rl = body["run_list"] t = body["bootstrap_template"] s = Devops::Db.connector.server_by_instance_id(id) + res = {server: s} p = Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user d = p.deploy_env(s.deploy_env) @@ -181,9 +179,11 @@ module Devops unless t.nil? templates = get_templates halt_response("Invalid bootstrap template '#{t}', available values: #{templates.join(", ")}", 400) unless templates.include?(t) + s[:bootstrap_template] = t end s.chef_node_name = name || provider.create_default_chef_node_name(s) - return s, rl || d.run_list, t + res[:run_list] = rl || d.run_list + return res end def unbootstrap_server id diff --git a/devops-service/lib/executors/server_executor.rb b/devops-service/lib/executors/server_executor.rb index 1b9e604..bf1e238 100644 --- a/devops-service/lib/executors/server_executor.rb +++ b/devops-service/lib/executors/server_executor.rb @@ -215,7 +215,11 @@ module Devops bootstrap_options end + def prepare_two_phase_bootstrap options + end + def two_phase_bootstrap options + prepare_two_phase_bootstrap(options) # bootstrap phase begin provider = @server.provider_instance From 1805f8d65cc67d9538d6bc72293d6157c5946389 Mon Sep 17 00:00:00 2001 From: amartynov Date: Fri, 23 Oct 2015 17:14:52 +0300 Subject: [PATCH 02/23] #840: some changes --- devops-service/app/api2/handlers/server.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devops-service/app/api2/handlers/server.rb b/devops-service/app/api2/handlers/server.rb index cddbf54..2830c55 100644 --- a/devops-service/app/api2/handlers/server.rb +++ b/devops-service/app/api2/handlers/server.rb @@ -179,7 +179,7 @@ module Devops unless t.nil? templates = get_templates halt_response("Invalid bootstrap template '#{t}', available values: #{templates.join(", ")}", 400) unless templates.include?(t) - s[:bootstrap_template] = t + res[:bootstrap_template] = t end s.chef_node_name = name || provider.create_default_chef_node_name(s) res[:run_list] = rl || d.run_list From 8af43f658d92ebed17c801d3918bdcd709409a85 Mon Sep 17 00:00:00 2001 From: amartynov Date: Mon, 26 Oct 2015 12:39:54 +0300 Subject: [PATCH 03/23] #840: test --- devops-service/lib/executors/server_executor.rb | 2 ++ devops-service/workers/bootstrap_worker.rb | 3 +++ 2 files changed, 5 insertions(+) diff --git a/devops-service/lib/executors/server_executor.rb b/devops-service/lib/executors/server_executor.rb index bf1e238..429bedb 100644 --- a/devops-service/lib/executors/server_executor.rb +++ b/devops-service/lib/executors/server_executor.rb @@ -216,6 +216,8 @@ module Devops end def prepare_two_phase_bootstrap options + @out << "Prepare bootstrap...\n" + @out << "Done\n" end def two_phase_bootstrap options diff --git a/devops-service/workers/bootstrap_worker.rb b/devops-service/workers/bootstrap_worker.rb index 5fe0856..eafc303 100644 --- a/devops-service/workers/bootstrap_worker.rb +++ b/devops-service/workers/bootstrap_worker.rb @@ -17,9 +17,12 @@ class BootstrapWorker < Worker server = Devops::Model::Server.new(server_attrs) report = save_report(file, owner, server) +=begin options = { bootstrap_template: bootstrap_template } +=end +out << options.inspect executor = Devops::Executor::ServerExecutor.new(server, out) executor.report = report status = executor.two_phase_bootstrap(options) From a3cb07ab5c2405e80200400dc283b0e800278b6b Mon Sep 17 00:00:00 2001 From: amartynov Date: Mon, 26 Oct 2015 12:50:31 +0300 Subject: [PATCH 04/23] #840: worker options keys to symbols --- devops-service/workers/worker.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/devops-service/workers/worker.rb b/devops-service/workers/worker.rb index ca91940..4745026 100644 --- a/devops-service/workers/worker.rb +++ b/devops-service/workers/worker.rb @@ -13,6 +13,8 @@ require "core/devops-db" require "providers/provider_factory" require "lib/knife/knife_factory" + +# All options keys MUST be a symbol!!! class Worker include Sidekiq::Worker @@ -27,7 +29,7 @@ class Worker end def self.start_async(worker_class, request, job_options) - jid = worker_class.perform_async(job_options.dup) + jid = worker_class.perform_async(convert_config(job_options)) Worker.set_status jid, Worker::STATUS::IN_QUEUE DevopsLogger.logger.info "Job '#{jid}' has been queued" @@ -37,10 +39,12 @@ class Worker end def self.start_sync(worker_class, request, job_options, out) - stringified_options = {} + stringified_options = convert_config(job_options) +=begin job_options.each do |key, value| stringified_options[key.to_s] = value end +=end w = worker_class.new w.out = out w.perform(stringified_options) From 708a1741dcc9fc6b3f7a3883dd49f7125c309ce5 Mon Sep 17 00:00:00 2001 From: amartynov Date: Mon, 26 Oct 2015 12:56:50 +0300 Subject: [PATCH 05/23] #840: convert_config is static now --- devops-service/workers/worker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devops-service/workers/worker.rb b/devops-service/workers/worker.rb index 4745026..493babd 100644 --- a/devops-service/workers/worker.rb +++ b/devops-service/workers/worker.rb @@ -130,7 +130,7 @@ class Worker ::Provider::ProviderFactory.get(provider_name) if provider_name end - def convert_config conf + def self.convert_config conf config = {} conf.each {|k,v| config[k.is_a?(String) ? k.to_sym : k] = v} config From f6b0aa6a8940e3c85581aea616885fa7703aef85 Mon Sep 17 00:00:00 2001 From: amartynov Date: Mon, 26 Oct 2015 13:16:32 +0300 Subject: [PATCH 06/23] #840: test 2 --- devops-service/workers/bootstrap_worker.rb | 2 ++ devops-service/workers/worker.rb | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/devops-service/workers/bootstrap_worker.rb b/devops-service/workers/bootstrap_worker.rb index eafc303..fe94b85 100644 --- a/devops-service/workers/bootstrap_worker.rb +++ b/devops-service/workers/bootstrap_worker.rb @@ -22,7 +22,9 @@ class BootstrapWorker < Worker bootstrap_template: bootstrap_template } =end +out << "\nFrom bootstrap worker: " out << options.inspect +out << "\n" executor = Devops::Executor::ServerExecutor.new(server, out) executor.report = report status = executor.two_phase_bootstrap(options) diff --git a/devops-service/workers/worker.rb b/devops-service/workers/worker.rb index 493babd..068d3d1 100644 --- a/devops-service/workers/worker.rb +++ b/devops-service/workers/worker.rb @@ -29,7 +29,7 @@ class Worker end def self.start_async(worker_class, request, job_options) - jid = worker_class.perform_async(convert_config(job_options)) + jid = worker_class.perform_async(Worker.convert_config(job_options)) Worker.set_status jid, Worker::STATUS::IN_QUEUE DevopsLogger.logger.info "Job '#{jid}' has been queued" @@ -39,7 +39,7 @@ class Worker end def self.start_sync(worker_class, request, job_options, out) - stringified_options = convert_config(job_options) + stringified_options = Worker.convert_config(job_options) =begin job_options.each do |key, value| stringified_options[key.to_s] = value @@ -133,6 +133,7 @@ class Worker def self.convert_config conf config = {} conf.each {|k,v| config[k.is_a?(String) ? k.to_sym : k] = v} + DevopsLogger.logger.info "Converted options: #{config.inspect}" config end From 02e4ae88d8324df83da20876d7300c1af104e08a Mon Sep 17 00:00:00 2001 From: amartynov Date: Mon, 26 Oct 2015 13:27:14 +0300 Subject: [PATCH 07/23] #840: convert config in worker instance --- devops-service/workers/bootstrap_worker.rb | 1 + devops-service/workers/worker.rb | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/devops-service/workers/bootstrap_worker.rb b/devops-service/workers/bootstrap_worker.rb index fe94b85..b15f5ef 100644 --- a/devops-service/workers/bootstrap_worker.rb +++ b/devops-service/workers/bootstrap_worker.rb @@ -12,6 +12,7 @@ class BootstrapWorker < Worker server_attrs = options.fetch('server_attrs') bootstrap_template = options.fetch('bootstrap_template') owner = options.fetch('owner') + options = convert_config(options) call(provider_name) do |provider, out, file| server = Devops::Model::Server.new(server_attrs) diff --git a/devops-service/workers/worker.rb b/devops-service/workers/worker.rb index 068d3d1..53342a1 100644 --- a/devops-service/workers/worker.rb +++ b/devops-service/workers/worker.rb @@ -29,7 +29,7 @@ class Worker end def self.start_async(worker_class, request, job_options) - jid = worker_class.perform_async(Worker.convert_config(job_options)) + jid = worker_class.perform_async(job_options) Worker.set_status jid, Worker::STATUS::IN_QUEUE DevopsLogger.logger.info "Job '#{jid}' has been queued" @@ -39,7 +39,7 @@ class Worker end def self.start_sync(worker_class, request, job_options, out) - stringified_options = Worker.convert_config(job_options) + stringified_options = job_options =begin job_options.each do |key, value| stringified_options[key.to_s] = value @@ -130,7 +130,7 @@ class Worker ::Provider::ProviderFactory.get(provider_name) if provider_name end - def self.convert_config conf + def convert_config conf config = {} conf.each {|k,v| config[k.is_a?(String) ? k.to_sym : k] = v} DevopsLogger.logger.info "Converted options: #{config.inspect}" From 02cf7427cfb45b900980365dcf1ac0b1f49bc562 Mon Sep 17 00:00:00 2001 From: amartynov Date: Mon, 26 Oct 2015 14:51:25 +0300 Subject: [PATCH 08/23] #840: some small fixes --- devops-service/workers/bootstrap_worker.rb | 5 +---- devops-service/workers/worker.rb | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/devops-service/workers/bootstrap_worker.rb b/devops-service/workers/bootstrap_worker.rb index b15f5ef..ba8b2c6 100644 --- a/devops-service/workers/bootstrap_worker.rb +++ b/devops-service/workers/bootstrap_worker.rb @@ -10,7 +10,7 @@ class BootstrapWorker < Worker def perform(options) provider_name = options.fetch('provider_name') server_attrs = options.fetch('server_attrs') - bootstrap_template = options.fetch('bootstrap_template') +# bootstrap_template = options.fetch('bootstrap_template') owner = options.fetch('owner') options = convert_config(options) @@ -23,9 +23,6 @@ class BootstrapWorker < Worker bootstrap_template: bootstrap_template } =end -out << "\nFrom bootstrap worker: " -out << options.inspect -out << "\n" executor = Devops::Executor::ServerExecutor.new(server, out) executor.report = report status = executor.two_phase_bootstrap(options) diff --git a/devops-service/workers/worker.rb b/devops-service/workers/worker.rb index 53342a1..d29a30b 100644 --- a/devops-service/workers/worker.rb +++ b/devops-service/workers/worker.rb @@ -133,7 +133,6 @@ class Worker def convert_config conf config = {} conf.each {|k,v| config[k.is_a?(String) ? k.to_sym : k] = v} - DevopsLogger.logger.info "Converted options: #{config.inspect}" config end From 8d0cd797a216d739822d2e469e30baf3716a6f15 Mon Sep 17 00:00:00 2001 From: amartynov Date: Mon, 2 Nov 2015 11:42:20 +0300 Subject: [PATCH 09/23] #789: account fields --- devops-service/app/api2/handlers/provider.rb | 4 ++++ devops-service/app/api2/routes/provider.rb | 16 ++++++++++++++++ .../provider_accounts/ec2_provider_account.rb | 8 ++++++++ .../openstack_provider_account.rb | 9 +++++++++ .../models/provider_accounts/provider_account.rb | 13 ++++++++----- .../provider_accounts/static_provider_account.rb | 3 +++ devops-service/providers/ec2_accounts_factory.rb | 2 +- devops-service/providers/provider_factory.rb | 8 +++++++- 8 files changed, 56 insertions(+), 7 deletions(-) diff --git a/devops-service/app/api2/handlers/provider.rb b/devops-service/app/api2/handlers/provider.rb index c059a90..274e840 100644 --- a/devops-service/app/api2/handlers/provider.rb +++ b/devops-service/app/api2/handlers/provider.rb @@ -20,6 +20,10 @@ module Devops ::Provider::ProviderFactory.get(provider).accounts end + def account_fields provider + ::Provider::ProviderFactory.get_account_class(provider).account_fields + end + def add_account provider account = ::Provider::ProviderFactory.get(provider).create_account(parser.account) key = Devops::Db.connector.key account.ssh_key diff --git a/devops-service/app/api2/routes/provider.rb b/devops-service/app/api2/routes/provider.rb index d0e117a..49a797e 100644 --- a/devops-service/app/api2/routes/provider.rb +++ b/devops-service/app/api2/routes/provider.rb @@ -26,6 +26,22 @@ module Devops json Devops::API2_0::Handler::Provider.new(request).providers end + # Get list of provider account fields + # + # * *Request* + # - method : GET + # - headers : + # - Accept: application/json + # + # * *Returns* : hash + # key - field + # value - description + app.get_with_headers "/provider/:provider/account/fields", :headers => [:accept] do |provider| + check_privileges("provider", "r") + check_provider(provider) + json Devops::API2_0::Handler::Provider.new(request).account_fields(provider) + end + # Get list of provider accounts # # * *Request* diff --git a/devops-service/db/mongo/models/provider_accounts/ec2_provider_account.rb b/devops-service/db/mongo/models/provider_accounts/ec2_provider_account.rb index f2633fb..85ee83a 100644 --- a/devops-service/db/mongo/models/provider_accounts/ec2_provider_account.rb +++ b/devops-service/db/mongo/models/provider_accounts/ec2_provider_account.rb @@ -34,6 +34,14 @@ module Devops Ec2ProviderAccount.new a end + def self.account_fields + { + access_key_id: "AWS account access key", + secret_access_key: "AWS account secret key", + availability_zone: "Availability zone, todo: remove field?" + }.merge(ProviderAccount::ACCOUNT_FIELDS) + end + # TODO: remove def validate_fields_types diff --git a/devops-service/db/mongo/models/provider_accounts/openstack_provider_account.rb b/devops-service/db/mongo/models/provider_accounts/openstack_provider_account.rb index 77c27a7..9aa6ca2 100644 --- a/devops-service/db/mongo/models/provider_accounts/openstack_provider_account.rb +++ b/devops-service/db/mongo/models/provider_accounts/openstack_provider_account.rb @@ -6,6 +6,15 @@ module Devops attr_accessor :username, :auth_url, :tenant, :api_key + def self.account_fields + { + username: "Openstack user name", + auth_url: "Identity API endpoint", + tenant: "Tenant to access", + api_key: "Openstack user password" + }.merge(ProviderAccount::ACCOUNT_FIELDS) + end + def initialize a={} super(a) self.username = a["username"] diff --git a/devops-service/db/mongo/models/provider_accounts/provider_account.rb b/devops-service/db/mongo/models/provider_accounts/provider_account.rb index 56cd315..2bfed36 100644 --- a/devops-service/db/mongo/models/provider_accounts/provider_account.rb +++ b/devops-service/db/mongo/models/provider_accounts/provider_account.rb @@ -7,14 +7,19 @@ module Devops include ModelWithProvider - attr_accessor :account_name, :description, :ssh_key, :certificate + attr_accessor :account_name, :description, :ssh_key + + ACCOUNT_FIELDS = { + account_name: "Account name (id)", + description: "Account description", + ssh_key: "Ssh key id" + } def initialize a={} self.account_name = a["account_name"] self.description = a["description"] self.ssh_key = a["ssh_key"] self.provider = a["provider"] - self.certificate = a["certificate"] self.created_at = a["created_at"] end @@ -28,7 +33,6 @@ module Devops "description" => self.description, "ssh_key" => self.ssh_key, "provider" => self.provider, - "certificate" => self.certificate, "created_at" => self.created_at } end @@ -38,8 +42,7 @@ module Devops "_id" => self.account_name, "description" => self.description, "ssh_key" => self.ssh_key, - "provider" => self.provider, - "certificate" => self.certificate + "provider" => self.provider } end diff --git a/devops-service/db/mongo/models/provider_accounts/static_provider_account.rb b/devops-service/db/mongo/models/provider_accounts/static_provider_account.rb index 37dc129..1359165 100644 --- a/devops-service/db/mongo/models/provider_accounts/static_provider_account.rb +++ b/devops-service/db/mongo/models/provider_accounts/static_provider_account.rb @@ -9,6 +9,9 @@ module Devops StaticProviderAccount.new a end + def self.account_fields + ProviderAccount::ACCOUNT_FIELDS + end end end end diff --git a/devops-service/providers/ec2_accounts_factory.rb b/devops-service/providers/ec2_accounts_factory.rb index ca94ece..88198e2 100644 --- a/devops-service/providers/ec2_accounts_factory.rb +++ b/devops-service/providers/ec2_accounts_factory.rb @@ -8,11 +8,11 @@ module Provider create_connection_from_account(config, account) puts "\tFound ec2 account '#{account.account_name}'" end + ProviderFactory.add_provider Ec2::PROVIDER unless @connections.empty? end def create_connection_from_account config, account options = { - aws_certificate: account.certificate, aws_ssh_key: account.ssh_key, aws_access_key_id: account.access_key_id, aws_secret_access_key: account.secret_access_key, diff --git a/devops-service/providers/provider_factory.rb b/devops-service/providers/provider_factory.rb index e0c9b2c..3bb8610 100644 --- a/devops-service/providers/provider_factory.rb +++ b/devops-service/providers/provider_factory.rb @@ -3,11 +3,12 @@ require "sinatra" module Provider module ProviderFactory + @@available_providers = [] @@providers = {} @@providers_with_accounts_factories = {} def self.providers - @@providers.keys + @@available_providers end def self.get provider, account=nil @@ -25,6 +26,10 @@ module Provider @@providers.values end + def self.add_provider provider + @@available_providers << provider unless @@available_providers.include?(provider) + end + def self.init conf # require providers here to get access to debug properties require_all @@ -34,6 +39,7 @@ module Provider o = Provider.const_get(p.capitalize).new(conf) if o.configured? @@providers[p] = o + @@available_providers << p puts "Provider '#{p}' has been loaded" end factory = Provider.const_get(p.capitalize + "AccountsFactory").new From d2bbe96f16661799c9927b33ef584133975558bd Mon Sep 17 00:00:00 2001 From: amartynov Date: Mon, 2 Nov 2015 11:43:57 +0300 Subject: [PATCH 10/23] #840: fixed --- devops-service/app/api2/handlers/server.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/devops-service/app/api2/handlers/server.rb b/devops-service/app/api2/handlers/server.rb index 2830c55..cfa7595 100644 --- a/devops-service/app/api2/handlers/server.rb +++ b/devops-service/app/api2/handlers/server.rb @@ -120,7 +120,7 @@ module Devops # TODO: check bootstrap template name def bootstrap_server_stream out options = prepare_bootstrap_server - s = options.delete[:server] + s = options.delete(:server) status = [] cert = Devops::Db.connector.key s.key DevopsLogger.logger.debug "Bootstrap certificate path: #{cert.path}" @@ -147,7 +147,7 @@ module Devops def bootstrap_server options = prepare_bootstrap_server - s = options.delete[:server] + s = options.delete(:server) options[:provider_name] = s.provider options[:server_attrs] = s.to_mongo_hash options[:owner] = parser.current_user From 45ede3d962d2ee0a10b5a6796c1fcf1820e3a820 Mon Sep 17 00:00:00 2001 From: amartynov Date: Mon, 2 Nov 2015 13:09:53 +0300 Subject: [PATCH 11/23] #853: server deploy command --- devops-service/app/api2/handlers/server.rb | 43 ++++++++++++++++++++ devops-service/app/api2/routes/server.rb | 47 ++++++++++++++++++++++ devops-service/workers/worker.rb | 4 +- 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/devops-service/app/api2/handlers/server.rb b/devops-service/app/api2/handlers/server.rb index 6eb4cbd..f4f4cbc 100644 --- a/devops-service/app/api2/handlers/server.rb +++ b/devops-service/app/api2/handlers/server.rb @@ -78,6 +78,49 @@ module Devops [uri] end + def deploy node_name + call_deploy(node_name) do |options| + [ Worker.start_async(DeployWorker, @request, options) ] + end + end + + def deploy_stream node_name, out + call_deploy(node_name) do |options| + Worker.start_sync(DeployWorker, @request, options, out) + end + rescue RecordNotFound => e + out << e.message + -10 + end + + def call_deploy node_name + body = parser.deploy + names = body["names"] + tags = body["tags"] || [] + run_list = body["run_list"] + dir = DevopsConfig.config[:report_dir_v2] + owner = parser.current_user + s = Server.get_server_by_key(node_name, parser.instance_key) + project = Devops::Db.connector.check_project_auth s.project, s.deploy_env, owner + deploy_info = create_deploy_info(s, project, body["build_number"]) + deploy_info["run_list"] = run_list if run_list + + yield({ + server_attrs: s.to_hash, + owner: owner, + tags: tags, + deploy_info: deploy_info + }) + end + + def servers names + servers = Devops::Db.connector.servers(nil, nil, names, true) + raise RecordNotFound.new("No reserved servers found for names '#{names.join("', '")}'") if servers.empty? + servers.sort_by!{|s| names.index(s.chef_node_name)} + servers + end + + def pause_server node_name s = Server.get_server_by_key(node_name, parser.instance_key) ## Authorization diff --git a/devops-service/app/api2/routes/server.rb b/devops-service/app/api2/routes/server.rb index 88d75f7..b00d983 100644 --- a/devops-service/app/api2/routes/server.rb +++ b/devops-service/app/api2/routes/server.rb @@ -132,6 +132,53 @@ module Devops } app.multi_routes "/server/:id", {:headers => [:accept, :content_type]}, hash + # Run deploy command on reserved server + # + # * *Request* + # - method : POST + # - headers : + # - Content-Type: application/json + # - body : + # { + # "names": [], -> array of servers names to run chef-client + # "tags": [], -> array of tags to apply on each server before running chef-client + # "build_number": "", -> string, build number to deploy + # "run_list": [], -> array of strings to set run_list for chef-client + # } + # + # * *Returns* : text stream + app.post_with_headers "/server/:node_name/deploy", :headers => [:content_type, :accept] do |node_name| + check_privileges("server", "x") + + if request["HTTP_X_STREAM"] + stream() do |out| + status = [] + begin + status = Devops::API2_0::Handler::Server.new(request).deploy_stream(node_name, out) + out << create_status(status) + rescue DeployInfoError => e + msg = "Can not get deploy info: " + e.message + DevopsLogger.logger.error "msg:\n#{e.backtrace.join('\n')}" + out.puts msg + rescue IOError => e + logger.error e.message + break + end + end # stream + else + files = begin + Devops::API2_0::Handler::Server.new(request).deploy(node_name) + rescue DeployInfoError => e + msg = "Can not get deploy info: " + e.message + DevopsLogger.logger.error "#{msg}:\n#{e.backtrace.join("\n")}" + out << "\nError - " + out.puts msg + end + sleep 1 + json files + end + end + # Create devops server # # * *Request* diff --git a/devops-service/workers/worker.rb b/devops-service/workers/worker.rb index ca91940..9ae96c9 100644 --- a/devops-service/workers/worker.rb +++ b/devops-service/workers/worker.rb @@ -60,9 +60,7 @@ class Worker call_sync(provider, &block) end rescue StandardError => e - puts e.message - puts e.backtrace.join("\n") - DevopsLogger.logger.error e.message + DevopsLogger.logger.error "#{e.message}:\n#{e.backtrace.join("\n")}" end end From 5549b028c4b065daf8beaafe37aa77d329c59dbe Mon Sep 17 00:00:00 2001 From: amartynov Date: Mon, 2 Nov 2015 17:33:25 +0300 Subject: [PATCH 12/23] #789: validation --- devops-service/app/api2/handlers/provider.rb | 7 ++--- devops-service/app/api2/helpers/version_2.rb | 2 +- devops-service/app/api2/routes/v2.0.rb | 14 +++++++++- devops-service/app/devops-api2.rb | 2 +- devops-service/db/mongo/models/mongo_model.rb | 26 +++++++++++++++---- .../provider_accounts/ec2_provider_account.rb | 7 +++++ .../provider_accounts/provider_account.rb | 15 +++++++++++ .../field_validators/description.rb | 17 ++++++++++++ .../db/validators/field_validators/name.rb | 2 +- .../db/validators/field_validators/ssh_key.rb | 20 ++++++++++++++ devops-service/exceptions/devops_error.rb | 15 ++++++++++- devops-service/exceptions/invalid_record.rb | 22 +++++++++++++++- devops-service/providers/accounts_factory.rb | 12 +++++++++ devops-service/providers/base_provider.rb | 8 ------ devops-service/providers/ec2.rb | 4 --- .../providers/ec2_accounts_factory.rb | 10 ++++++- devops-service/providers/provider_factory.rb | 11 ++++++++ 17 files changed, 167 insertions(+), 27 deletions(-) create mode 100644 devops-service/db/validators/field_validators/description.rb create mode 100644 devops-service/db/validators/field_validators/ssh_key.rb diff --git a/devops-service/app/api2/handlers/provider.rb b/devops-service/app/api2/handlers/provider.rb index 274e840..a054f2c 100644 --- a/devops-service/app/api2/handlers/provider.rb +++ b/devops-service/app/api2/handlers/provider.rb @@ -17,7 +17,7 @@ module Devops end def accounts provider - ::Provider::ProviderFactory.get(provider).accounts + ::Provider::ProviderFactory.get_accounts_factory(provider).accounts end def account_fields provider @@ -25,8 +25,8 @@ module Devops end def add_account provider - account = ::Provider::ProviderFactory.get(provider).create_account(parser.account) - key = Devops::Db.connector.key account.ssh_key + account = ::Provider::ProviderFactory.get_accounts_factory(provider).create_account(parser.account) + account.validate_fields! Devops::Db.connector.provider_accounts_insert(account) ::Provider::ProviderFactory.add_account(provider, account) account.to_hash @@ -35,6 +35,7 @@ module Devops def delete_account name, provider account = Devops::Db.connector.provider_accounts_show(name) Devops::Db.connector.provider_accounts_delete(name) + ::Provider::ProviderFactory.delete_account(provider, account) account.to_hash end diff --git a/devops-service/app/api2/helpers/version_2.rb b/devops-service/app/api2/helpers/version_2.rb index 08a538b..2e4ce94 100644 --- a/devops-service/app/api2/helpers/version_2.rb +++ b/devops-service/app/api2/helpers/version_2.rb @@ -30,7 +30,7 @@ module Devops def check_provider provider list = ::Provider::ProviderFactory.providers - halt_response("Invalid provider '#{provider}', available providers: '#{list.join("', '")}'", 404) unless list.include?(provider) + halt_response("Invalid provider '#{provider}', available providers: '#{list.join("', '")}'", 400) unless list.include?(provider) end # Save information about requests with methods POST, PUT, DELETE diff --git a/devops-service/app/api2/routes/v2.0.rb b/devops-service/app/api2/routes/v2.0.rb index 4a220d9..3645afc 100644 --- a/devops-service/app/api2/routes/v2.0.rb +++ b/devops-service/app/api2/routes/v2.0.rb @@ -61,13 +61,23 @@ module Devops DevopsLogger.logger = @@logger begin res = super(env) - rescue DevopsError => e + rescue ::Devops::Exception::DevopsError => e + return [e.code, {}, e.message] + rescue InvalidRecord => e return [e.code, {}, e.message] end @@access_logger.info(env["REQUEST_METHOD"] + " " + env["REQUEST_URI"] + " - from #{env["HTTP_USER_AGENT"]} (#{env["REMOTE_USER"]}) / #{res[0]}") res end + def handle_exception!(boom) + if boom.is_a?(::Devops::Exception::DevopsError) + boom.http_response + else + super(boom) + end + end + error Devops::ValidationError do e = env["sinatra.error"] #logger.warn e.message @@ -92,12 +102,14 @@ module Devops halt_response(e.message, 404) end +=begin error InvalidRecord do e = env["sinatra.error"] logger.warn e.message logger.warn "Request body: #{request.body.read}" halt_response(e.message, 400) end +=end error InvalidCommand do e = env["sinatra.error"] diff --git a/devops-service/app/devops-api2.rb b/devops-service/app/devops-api2.rb index 4eb8832..5e650de 100644 --- a/devops-service/app/devops-api2.rb +++ b/devops-service/app/devops-api2.rb @@ -78,7 +78,7 @@ module Devops Devops::Api2.register r end Routes.route "/v2.0", Devops::Api2 - Devops::Api2.routes_list + #Devops::Api2.routes_list end private diff --git a/devops-service/db/mongo/models/mongo_model.rb b/devops-service/db/mongo/models/mongo_model.rb index 60e46b7..3721a5c 100644 --- a/devops-service/db/mongo/models/mongo_model.rb +++ b/devops-service/db/mongo/models/mongo_model.rb @@ -66,6 +66,21 @@ module Devops end end + def validate_fields! + result = [] + self.class.field_validators.each do |field, validation_method| + begin + self.send(validation_method) + rescue InvalidRecord => e + result << {key: field, message: e.message} + end + end + unless result.empty? + raise InvalidRecord.new(error_data: result) + end + true + end + def build_error_message(message) # overrided in descendants message @@ -123,17 +138,16 @@ module Devops end @validators = [] -# @field_validators = [] + @field_validators = {} class << self attr_accessor :validators -# attr_accessor :field_validators + attr_accessor :field_validators def inherited(subclass) subclass.validators = [] subclass.validators += self.validators -# subclass.field_validators = [] -# subclass.field_validators += self.field_validators + subclass.field_validators = self.field_validators.clone end # all exceptions are handled in @validate! method @@ -146,11 +160,13 @@ module Devops # validate field value # if method validate! returns false, then stop validation without error def set_field_validators field, *validators - define_method("validate_" + field.to_s + "!") do + method_name = "validate_" + field.to_s + "!" + define_method(method_name) do validators.each do |validator| break unless validator.new(self, send(field)).validate! end end + self.field_validators[field] = method_name end # private class methods diff --git a/devops-service/db/mongo/models/provider_accounts/ec2_provider_account.rb b/devops-service/db/mongo/models/provider_accounts/ec2_provider_account.rb index 85ee83a..3f2fb41 100644 --- a/devops-service/db/mongo/models/provider_accounts/ec2_provider_account.rb +++ b/devops-service/db/mongo/models/provider_accounts/ec2_provider_account.rb @@ -6,6 +6,13 @@ module Devops attr_accessor :access_key_id, :availability_zone, :secret_access_key + set_field_validators :access_key_id, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty + + set_field_validators :secret_access_key, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty def initialize a={} super(a) self.provider = Provider::Ec2::PROVIDER diff --git a/devops-service/db/mongo/models/provider_accounts/provider_account.rb b/devops-service/db/mongo/models/provider_accounts/provider_account.rb index 2bfed36..3a6fb59 100644 --- a/devops-service/db/mongo/models/provider_accounts/provider_account.rb +++ b/devops-service/db/mongo/models/provider_accounts/provider_account.rb @@ -9,6 +9,21 @@ module Devops attr_accessor :account_name, :description, :ssh_key + set_field_validators :account_name, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty, + ::Validators::FieldValidator::Name + + set_field_validators :description, ::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty, + ::Validators::FieldValidator::Description + + set_field_validators :ssh_key, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty, + ::Validators::FieldValidator::SshKey + ACCOUNT_FIELDS = { account_name: "Account name (id)", description: "Account description", diff --git a/devops-service/db/validators/field_validators/description.rb b/devops-service/db/validators/field_validators/description.rb new file mode 100644 index 0000000..c414e3a --- /dev/null +++ b/devops-service/db/validators/field_validators/description.rb @@ -0,0 +1,17 @@ +require_relative "base" +module Validators + module FieldValidator + class Description < Base + + MAX_LEN = 500 + + def valid? + @value.size <= 500 + end + + def message + "Invalid value '#{@value}': it should be less or equals then #{MAX_LEN} symbols" + end + end + end +end diff --git a/devops-service/db/validators/field_validators/name.rb b/devops-service/db/validators/field_validators/name.rb index 1319d85..4603934 100644 --- a/devops-service/db/validators/field_validators/name.rb +++ b/devops-service/db/validators/field_validators/name.rb @@ -11,7 +11,7 @@ module Validators end def message - "Invalid value '#{@value}': it should contains symbols 'a-zA-Z0-9_' and length should be more then 1 and less or equals then #{MAX_NAME_LEN}" + "Invalid value '#{@value}': it should contains symbols 'a-zA-Z0-9_' and length should be more then 1 and less or equals then #{MAX_NAME_LEN} symbols" end end end diff --git a/devops-service/db/validators/field_validators/ssh_key.rb b/devops-service/db/validators/field_validators/ssh_key.rb new file mode 100644 index 0000000..fce76e3 --- /dev/null +++ b/devops-service/db/validators/field_validators/ssh_key.rb @@ -0,0 +1,20 @@ +require_relative "base" +module Validators + module FieldValidator + class SshKey < Base + + MAX_LEN = 500 + + def valid? + Devops::Db.connector.key @value + true + rescue RecordNotFound + false + end + + def message + "Invalid value '#{@value}': ssh key '#{@value}' not found" + end + end + end +end diff --git a/devops-service/exceptions/devops_error.rb b/devops-service/exceptions/devops_error.rb index 996ec04..fdcb6a2 100644 --- a/devops-service/exceptions/devops_error.rb +++ b/devops-service/exceptions/devops_error.rb @@ -1,12 +1,25 @@ +require "json" module Devops module Exception class DevopsError < StandardError - def code + def http_status 500 end + def http_response + [self.http_status, self.http_headers, self.http_body] + end + + def http_body + JSON.pretty_generate(message: self.message) + end + + def http_headers + {"Content-Type" => "application/json"} + end + end end diff --git a/devops-service/exceptions/invalid_record.rb b/devops-service/exceptions/invalid_record.rb index 5ca7cb1..48d3750 100644 --- a/devops-service/exceptions/invalid_record.rb +++ b/devops-service/exceptions/invalid_record.rb @@ -1,3 +1,23 @@ -class InvalidRecord < StandardError +require_relative "devops_error" +class InvalidRecord < ::Devops::Exception::DevopsError + def initialize msg + if msg.is_a?(String) + super(msg) + else + @object = msg + end + end + + def http_status + 400 + end + + def http_body + if @object.nil? + super + else + JSON.pretty_generate(@object) + end + end end diff --git a/devops-service/providers/accounts_factory.rb b/devops-service/providers/accounts_factory.rb index c956b14..7f212e9 100644 --- a/devops-service/providers/accounts_factory.rb +++ b/devops-service/providers/accounts_factory.rb @@ -14,8 +14,20 @@ module Provider @connections[name] = conn end + def delete_connection name + @connections.delete(name) + end + def create_connection_from_account config, account end + + def accounts + Devops::Db.connector.provider_accounts(provider_name) + end + + def create_account hash + raise "override me" + end end end diff --git a/devops-service/providers/base_provider.rb b/devops-service/providers/base_provider.rb index a7d27dc..bf9ef34 100644 --- a/devops-service/providers/base_provider.rb +++ b/devops-service/providers/base_provider.rb @@ -6,14 +6,6 @@ module Provider attr_accessor :ssh_key, :certificate_path, :connection_options, :run_list - def accounts - Devops::Db.connector.provider_accounts(self.name) - end - - def create_account hash - raise "override me" - end - def create_default_chef_node_name s "#{self.ssh_key}-#{s.project}-#{s.deploy_env}-#{Time.now.to_i}" end diff --git a/devops-service/providers/ec2.rb b/devops-service/providers/ec2.rb index 40fb10b..73aff74 100644 --- a/devops-service/providers/ec2.rb +++ b/devops-service/providers/ec2.rb @@ -35,10 +35,6 @@ module Provider super and !(empty_param?(o[:aws_access_key_id]) or empty_param?(o[:aws_secret_access_key])) end - def create_account hash - Devops::Model::Ec2ProviderAccount.new(hash) - end - def name PROVIDER end diff --git a/devops-service/providers/ec2_accounts_factory.rb b/devops-service/providers/ec2_accounts_factory.rb index 88198e2..58eb3a8 100644 --- a/devops-service/providers/ec2_accounts_factory.rb +++ b/devops-service/providers/ec2_accounts_factory.rb @@ -4,13 +4,17 @@ module Provider def init config @connections = {} - Devops::Db.connector.provider_accounts(Ec2::PROVIDER).each do |account| + accounts.each do |account| create_connection_from_account(config, account) puts "\tFound ec2 account '#{account.account_name}'" end ProviderFactory.add_provider Ec2::PROVIDER unless @connections.empty? end + def provider_name + Ec2::PROVIDER + end + def create_connection_from_account config, account options = { aws_ssh_key: account.ssh_key, @@ -25,5 +29,9 @@ module Provider add_connection(account.account_name, Ec2.new(options)) end + def create_account hash + Devops::Model::Ec2ProviderAccount.new(hash) + end + end end diff --git a/devops-service/providers/provider_factory.rb b/devops-service/providers/provider_factory.rb index 3bb8610..921cceb 100644 --- a/devops-service/providers/provider_factory.rb +++ b/devops-service/providers/provider_factory.rb @@ -50,6 +50,7 @@ module Provider next end end + puts "Available providers: #{@@available_providers}" end def self.add_account provider, account @@ -58,6 +59,12 @@ module Provider DevopsLogger.logger.info("Added #{provider} account '#{account.account_name}'") end + def self.delete_account provider, account + factory = @@providers_with_accounts_factories[provider] + factory.delete_connection(account.account_name) + DevopsLogger.logger.info("Removed #{provider} account '#{account.account_name}'") + end + def self.require_all ["ec2", "openstack", "static"].each do |provider| begin @@ -69,6 +76,10 @@ module Provider end end + def self.get_accounts_factory provider + @@providers_with_accounts_factories[provider] + end + def self.get_account_class provider case(provider) when ::Provider::Static::PROVIDER From 2f2f446defc7d67c9ef8d01c2517b7a15165e49b Mon Sep 17 00:00:00 2001 From: Anton Martynov Date: Tue, 3 Nov 2015 12:05:07 +0300 Subject: [PATCH 13/23] #856: subreports for stack reports --- devops-service/app/api2/handlers/deploy.rb | 6 +-- devops-service/app/api2/handlers/project.rb | 8 +-- devops-service/app/api2/handlers/server.rb | 12 ++--- devops-service/app/api2/handlers/stack.rb | 12 ++--- devops-service/db/mongo/connectors/report.rb | 14 ++++- devops-service/db/mongo/models/report.rb | 10 ++-- devops-service/db/mongo/mongo_connector.rb | 2 +- devops-service/workers/bootstrap_worker.rb | 4 +- .../workers/create_server_worker.rb | 3 +- .../workers/delete_server_worker.rb | 2 +- devops-service/workers/deploy_worker.rb | 2 +- devops-service/workers/project_test_worker.rb | 2 +- .../workers/stack_bootstrap_worker.rb | 54 +++++++++++++------ devops-service/workers/worker.rb | 42 +++++++-------- 14 files changed, 97 insertions(+), 76 deletions(-) diff --git a/devops-service/app/api2/handlers/deploy.rb b/devops-service/app/api2/handlers/deploy.rb index 2e42e2f..acaf5b1 100644 --- a/devops-service/app/api2/handlers/deploy.rb +++ b/devops-service/app/api2/handlers/deploy.rb @@ -19,10 +19,8 @@ module Devops names = body["names"] tags = body["tags"] || [] run_list = body["run_list"] - dir = DevopsConfig.config[:report_dir_v2] files = [] jid = nil - uri = URI.parse(parser.request.url) owner = parser.current_user @deploy_info_buf = {} servers(names).each do |s| @@ -36,7 +34,7 @@ module Devops deploy_info = create_deploy_info(s, project, body["build_number"]) deploy_info["run_list"] = run_list if run_list - uri = Worker.start_async(DeployWorker, @request, + jid = Worker.start_async(DeployWorker, server_attrs: s.to_hash, owner: owner, tags: tags, @@ -63,7 +61,7 @@ module Devops } Devops::Db.connector.save_report(Report.new(o)) end - files.push(uri) + files.push(jid) end files end diff --git a/devops-service/app/api2/handlers/project.rb b/devops-service/app/api2/handlers/project.rb index e82616c..68d0b39 100644 --- a/devops-service/app/api2/handlers/project.rb +++ b/devops-service/app/api2/handlers/project.rb @@ -251,13 +251,13 @@ module Devops deploy_info_buf[s.deploy_env] = project_model.deploy_info(deploy_env_model, nil) end - uri = Worker.start_async(DeployWorker, @request, + jid = Worker.start_async(DeployWorker, server_attrs: s.to_hash, owner: parser.current_user, tags: [], deploy_info: deploy_info ) - files.push uri + files.push jid end files end @@ -288,14 +288,14 @@ module Devops raise InvalidRecord.new(msg) end - uri = Worker.start_async(ProjectTestWorker, @request, + jid = Worker.start_async(ProjectTestWorker, project: project.id, deploy_env: env.identifier, user: @request.env['REMOTE_USER'] ) sleep 1 - return [uri] + return [jid] end end diff --git a/devops-service/app/api2/handlers/server.rb b/devops-service/app/api2/handlers/server.rb index 6eb4cbd..04cea15 100644 --- a/devops-service/app/api2/handlers/server.rb +++ b/devops-service/app/api2/handlers/server.rb @@ -71,11 +71,11 @@ module Devops user = parser.current_user check_if_server_attrs_are_valid(body, user) - uri = Worker.start_async(CreateServerWorker, @request, + jid = Worker.start_async(CreateServerWorker, server_attrs: body, owner: user ) - [uri] + [jid] end def pause_server node_name @@ -153,19 +153,15 @@ module Devops def bootstrap_server server, rl, bootstrap_template = prepare_bootstrap_server - dir = DevopsConfig[:report_dir_v2] - files = [] - uri = URI.parse(@request.url) - uri = Worker.start_async(BootstrapWorker, @request, - provider_name: server.provider, + jid = Worker.start_async(BootstrapWorker, server_attrs: server.to_mongo_hash, bootstrap_template: bootstrap_template, owner: parser.current_user ) sleep 1 - [uri] + [jid] end def prepare_bootstrap_server diff --git a/devops-service/app/api2/handlers/stack.rb b/devops-service/app/api2/handlers/stack.rb index 664df53..ffc1fe0 100644 --- a/devops-service/app/api2/handlers/stack.rb +++ b/devops-service/app/api2/handlers/stack.rb @@ -28,13 +28,10 @@ module Devops object["provider"] = env.provider object["provider_account"] = env.provider_account - # TODO: without provider_name - uri = Worker.start_async(StackBootstrapWorker, @request, - provider_name: env.provider, + jid = Worker.start_async(StackBootstrapWorker, stack_attributes: object ) - puts "Syncing report is located here: #{uri}" - [uri] + [jid] end def stack id @@ -102,7 +99,6 @@ module Devops def deploy id stack = self.stack(id) owner = parser.current_user - status = [] project = Devops::Db.connector.check_project_auth(stack.project, stack.deploy_env, owner) deploy_env_model = project.deploy_env(stack.deploy_env) body = parser.deploy @@ -114,7 +110,7 @@ module Devops servers.each do |s| begin deploy_info = project.deploy_info(deploy_env_model, nil) - uri = Worker.start_async(DeployWorker, @request, + jid = Worker.start_async(DeployWorker, server_attrs: s.to_hash, owner: owner, tags: tags, @@ -140,7 +136,7 @@ module Devops } Devops::Db.connector.save_report(Report.new(o)) end - files.push uri + files.push jid end files end diff --git a/devops-service/db/mongo/connectors/report.rb b/devops-service/db/mongo/connectors/report.rb index 8c5b199..fcc363f 100644 --- a/devops-service/db/mongo/connectors/report.rb +++ b/devops-service/db/mongo/connectors/report.rb @@ -51,8 +51,18 @@ module Connectors collection.find(options).sort(sort).to_a.map {|bson| model_from_bson(bson)} end - def set_report_status(jid, status) - collection.update({"_id" => jid}, {"$set" => {"status" => status, "updated_at" => Time.new}}) + def add_report_subreports(jid, subreports) + collection.update({"_id" => jid}, {"$push" => {"subreports" => {"$each" => subreports}}}) + end + + def set_report_status(jid, status, job_result_code) + set = {"status" => status, "updated_at" => Time.new} + set["job_result_code"] = job_result_code unless job_result_code.nil? + collection.update({"_id" => jid}, {"$set" => set}) + end + + def set_report_status(jid, status, job_result_code) + collection.update({"_id" => jid}, {"$set" => {"status" => status, "updated_at" => Time.new, "job_result_code" => job_result_code}}) end def set_report_server_data id, chef_node_name, host diff --git a/devops-service/db/mongo/models/report.rb b/devops-service/db/mongo/models/report.rb index c7ca2c4..c557b22 100644 --- a/devops-service/db/mongo/models/report.rb +++ b/devops-service/db/mongo/models/report.rb @@ -12,7 +12,7 @@ module Devops DEPLOY_STACK_TYPE = 6 DELETE_SERVER_TYPE = 7 - attr_accessor :id, :file, :created_at, :updated_at, :created_by, :project, :deploy_env, :type, :chef_node_name, :host, :status, :stack + attr_accessor :id, :file, :updated_at, :created_by, :project, :deploy_env, :type, :chef_node_name, :host, :status, :stack, :subreports, :job_result_code def initialize r self.id = r["_id"] @@ -21,13 +21,15 @@ module Devops self.project = r["project"] self.deploy_env = r["deploy_env"] 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.stack = r["stack"] self.created_at = r["created_at"].localtime unless r["created_at"].nil? self.updated_at = r["updated_at"].localtime unless r["updated_at"].nil? self.status = r["status"] + self.subreports = r["subreports"] + self.job_result_code = r["job_result_code"] end def to_hash_without_id @@ -42,7 +44,9 @@ module Devops "chef_node_name" => self.chef_node_name, "host" => self.host, "status" => self.status, - "stack" => self.stack + "stack" => self.stack, + "subreports" => self.subreports, + "job_result_code" => self.job_result_code } end diff --git a/devops-service/db/mongo/mongo_connector.rb b/devops-service/db/mongo/mongo_connector.rb index 224e952..bda584e 100644 --- a/devops-service/db/mongo/mongo_connector.rb +++ b/devops-service/db/mongo/mongo_connector.rb @@ -31,7 +31,7 @@ class MongoConnector [:user_auth, :user, :users, :users_names, :user_insert, :user_delete, :user_update, :create_root_user, :check_user_privileges] => :users_connector, [:keys, :key, :key_insert, :key_delete] => :keys_connector, - [:save_report, :report, :reports, :set_report_status, :set_report_server_data] => :reports_connector, + [:save_report, :report, :reports, :set_report_status, :set_report_server_data, :add_report_subreports] => :reports_connector, [:insert_statistic, :search_statistic] => :statistics_connector, [:provider_accounts, :provider_accounts_insert, :provider_accounts_delete, :provider_accounts_show] => :provider_accounts_connector ) diff --git a/devops-service/workers/bootstrap_worker.rb b/devops-service/workers/bootstrap_worker.rb index 5fe0856..881a9c4 100644 --- a/devops-service/workers/bootstrap_worker.rb +++ b/devops-service/workers/bootstrap_worker.rb @@ -1,19 +1,17 @@ require File.join(File.dirname(__FILE__), "worker") require "lib/executors/server_executor" -require "providers/provider_factory" require "db/mongo/models/server" require "db/mongo/models/report" class BootstrapWorker < Worker def perform(options) - provider_name = options.fetch('provider_name') server_attrs = options.fetch('server_attrs') bootstrap_template = options.fetch('bootstrap_template') owner = options.fetch('owner') - call(provider_name) do |provider, out, file| + call() do |out, file| server = Devops::Model::Server.new(server_attrs) report = save_report(file, owner, server) diff --git a/devops-service/workers/create_server_worker.rb b/devops-service/workers/create_server_worker.rb index 192de26..bc2655a 100644 --- a/devops-service/workers/create_server_worker.rb +++ b/devops-service/workers/create_server_worker.rb @@ -1,6 +1,5 @@ require File.join(File.dirname(__FILE__), "worker") -require "providers/provider_factory" require "db/mongo/models/server" require "db/mongo/models/report" require "lib/executors/server_executor" @@ -11,7 +10,7 @@ class CreateServerWorker < Worker server_attrs = options.fetch('server_attrs') owner = options.fetch('owner') - call(nil) do |not_used, out, file| + call() do |out, file| project = mongo.project(server_attrs["project"]) env = project.deploy_env(server_attrs["deploy_env"]) report = save_report(file, project, env, owner) diff --git a/devops-service/workers/delete_server_worker.rb b/devops-service/workers/delete_server_worker.rb index 66c8f48..c8fe476 100644 --- a/devops-service/workers/delete_server_worker.rb +++ b/devops-service/workers/delete_server_worker.rb @@ -8,7 +8,7 @@ class DeleteServerWorker < Worker chef_node_name = options.fetch('server_chef_node_name') puts "Expire server '#{chef_node_name}'." - call(nil) do |not_used, out, file| + call() do |out, file| server = mongo.server_by_chef_node_name(chef_node_name) report = save_report(file, server) diff --git a/devops-service/workers/deploy_worker.rb b/devops-service/workers/deploy_worker.rb index e47d384..9916ee2 100644 --- a/devops-service/workers/deploy_worker.rb +++ b/devops-service/workers/deploy_worker.rb @@ -12,7 +12,7 @@ class DeployWorker < Worker tags = options.fetch('tags') deploy_info = options.fetch('deploy_info') - call(nil) do |not_used, out, file| + call() do |out, file| server = Devops::Model::Server.new(server_attrs) report = save_report(file, owner, server) diff --git a/devops-service/workers/project_test_worker.rb b/devops-service/workers/project_test_worker.rb index 5f70be4..760b06c 100644 --- a/devops-service/workers/project_test_worker.rb +++ b/devops-service/workers/project_test_worker.rb @@ -15,7 +15,7 @@ class ProjectTestWorker < Worker project_name = params.fetch('project') deploy_env_name = params.fetch('deploy_env') - call(nil) do |not_used, out, file| + call() do |out, file| DevopsLogger.logger.info "Test project '#{project_name}' and env '#{deploy_env_name}' (user - #{user})" project = mongo.project(project_name) env = project.deploy_env(deploy_env_name) diff --git a/devops-service/workers/stack_bootstrap_worker.rb b/devops-service/workers/stack_bootstrap_worker.rb index 780606a..e803b08 100644 --- a/devops-service/workers/stack_bootstrap_worker.rb +++ b/devops-service/workers/stack_bootstrap_worker.rb @@ -1,4 +1,3 @@ -require "providers/provider_factory" require "commands/stack" require "db/mongo/models/stack/stack_factory" require "db/mongo/models/project" @@ -12,10 +11,9 @@ class StackBootstrapWorker < Worker include StackCommands def perform(options) - provider_name = options.fetch('provider_name') stack_attrs = options.fetch('stack_attributes') - call(provider_name) do |provider, out, file| + call() do |out, file| @out = out without_bootstrap = stack_attrs.delete('without_bootstrap') @out.puts "Received 'without_bootstrap' option" if without_bootstrap @@ -23,13 +21,13 @@ class StackBootstrapWorker < Worker report = save_report(file, stack_attrs) begin - stack = create_stack(provider_name, stack_attrs) + stack = create_stack(stack_attrs) rescue StackCreatingError return 1 end begin - servers = persist_stack_servers!(stack, provider) + servers = persist_stack_servers!(stack) bootstrap_servers!(servers, report) unless without_bootstrap rescue BootstrapingStackServerError @out.puts "\nAn error occured during bootstraping stack servers. Initiating stack rollback." @@ -57,8 +55,8 @@ class StackBootstrapWorker < Worker @out.puts "Rollback has been completed" end - def create_stack(provider_name, stack_attrs) - stack = Devops::Model::StackFactory.create(provider_name, stack_attrs, @out) + def create_stack(stack_attrs) + stack = Devops::Model::StackFactory.create(stack_attrs["provider"], stack_attrs, @out) mongo.stack_insert(stack) operation_result = sync_stack_proc.call(@out, stack, mongo) @@ -76,15 +74,40 @@ class StackBootstrapWorker < Worker def bootstrap_servers!(servers, report) @out << "\nStart bootstraping stack servers\n" - bootstraping_results = {} + + report.subreports = subreports = [] + data = {} servers.each do |server| - executor = Devops::Executor::ServerExecutor.new(server, @out) - executor.report = report - #TODO: can stack choose bootstrap template? - bootstraping_results[server.chef_node_name] = executor.two_phase_bootstrap({bootstrap_template: 'omnibus'}) - @out.flush + sjid = Worker.start_async(BootstrapWorker, + server_attrs: server.to_mongo_hash, + bootstrap_template: 'omnibus', + owner: server.created_by + ) + subreports << sjid + @out.puts "Bootstraping server '#{server.id}'... job id: #{sjid}" + data[server.id] = sjid end - check_bootstrap_results!(bootstraping_results) + @out.puts + @out.flush + mongo.add_report_subreports(jid, subreports) + results = [] + data.each do |server_id, subreport_id| + begin + sleep(5) + subreport = mongo.report(subreport_id) + status = subreport.status + if status == Worker::STATUS::COMPLETED + @out.puts "Server '#{server_id}' has been bootstraped with job #{subreport_id}" + break + elsif status == Worker::STATUS::FAILED + results << subreport.job_result_code + @out.puts "Server '#{server_id}' hasn't been bootstraped with job #{subreport_id}. Job result code is '#{subreport.job_result_code}'" + break + end + end while(true) + end + @out.flush + results.empty? ? 0 : -5 end def check_bootstrap_results!(results) @@ -130,11 +153,12 @@ class StackBootstrapWorker < Worker report end - def persist_stack_servers!(stack, provider) + def persist_stack_servers!(stack) @out.puts "Start syncing stack servers with CID" @out.flush project = mongo.project(stack.project) deploy_env = project.deploy_env(stack.deploy_env) + provider = stack.provider_instance servers = provider.stack_servers(stack).map do |extended_info| server_attrs = { diff --git a/devops-service/workers/worker.rb b/devops-service/workers/worker.rb index ca91940..3252f8f 100644 --- a/devops-service/workers/worker.rb +++ b/devops-service/workers/worker.rb @@ -26,14 +26,16 @@ class Worker IN_QUEUE = "queued" end - def self.start_async(worker_class, request, job_options) + def self.start_async(worker_class, job_options) jid = worker_class.perform_async(job_options.dup) Worker.set_status jid, Worker::STATUS::IN_QUEUE DevopsLogger.logger.info "Job '#{jid}' has been queued" - + jid +=begin uri = URI.parse(request.url) uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/#{jid}" uri.to_s +=end end def self.start_sync(worker_class, request, job_options, out) @@ -50,14 +52,13 @@ class Worker Sidekiq.redis {|con| con.hset "devops", id, status} end - def call provider_name, &block + def call &block begin - initialize_devops(provider_name) - provider = ::Provider::ProviderFactory.get(provider_name) if provider_name + initialize_devops() if jid - call_async(provider, &block) + call_async(&block) else - call_sync(provider, &block) + call_sync(&block) end rescue StandardError => e puts e.message @@ -68,7 +69,7 @@ class Worker private - def initialize_devops(provider_name) + def initialize_devops() DevopsLogger.logger = logger DevopsConfig.read DevopsService.init @@ -76,33 +77,33 @@ class Worker end # outputs to file - def call_async(provider) + def call_async() dir = DevopsConfig[:report_dir_v2] # directory is created on server start in config.ru file = File.join(dir, jid) - update_job_status(STATUS::INIT) + update_job_status(STATUS::INIT, nil) File.open(file, "w") do |out| begin - update_job_status(STATUS::RUNNING) + update_job_status(STATUS::RUNNING, nil) self.out = out - job_result = yield(provider, out, file) + job_result = yield(out, file) canonical_status = (job_result == 0 ? STATUS::COMPLETED : STATUS::FAILED) - update_job_status(canonical_status) + update_job_status(canonical_status, job_result) rescue StandardError, RecordNotFound => e out << "\n #{e.class}\n #{e.message}\n" out << e.backtrace.join("\n") - update_job_status(STATUS::FAILED) + update_job_status(STATUS::FAILED, -100) end end end # outputs to STDOUT - def call_sync(provider) + def call_sync() out = STDOUT begin - yield(provider, out, '') + yield(out, '') rescue StandardError, RecordNotFound => e out << "\n" out << e.message @@ -115,17 +116,12 @@ class Worker ::Devops::Db.connector end - def update_job_status(status) + def update_job_status(status, job_result_code) set_status(jid, status) - mongo.set_report_status(jid, status) + mongo.set_report_status(jid, status, job_result_code) status end - def init_provider(provider_name) - ::Provider::ProviderFactory.init(DevopsConfig.config) - ::Provider::ProviderFactory.get(provider_name) if provider_name - end - def convert_config conf config = {} conf.each {|k,v| config[k.is_a?(String) ? k.to_sym : k] = v} From da2a68f4514dd0eee69e14357f280f3bd9a8aafa Mon Sep 17 00:00:00 2001 From: Anton Martynov Date: Tue, 3 Nov 2015 13:08:31 +0300 Subject: [PATCH 14/23] #855: cid:priority --- devops-service/providers/ec2.rb | 1 + .../workers/stack_bootstrap_worker.rb | 63 ++++++++++++------- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/devops-service/providers/ec2.rb b/devops-service/providers/ec2.rb index 40fb10b..80925dc 100644 --- a/devops-service/providers/ec2.rb +++ b/devops-service/providers/ec2.rb @@ -323,6 +323,7 @@ module Provider 'key_name' => instance["keyName"], 'private_ip' => instance["privateIpAddress"], 'public_ip' => instance["ipAddress"], + 'tags' => instance["tagSet"] } end end diff --git a/devops-service/workers/stack_bootstrap_worker.rb b/devops-service/workers/stack_bootstrap_worker.rb index e803b08..cc98b19 100644 --- a/devops-service/workers/stack_bootstrap_worker.rb +++ b/devops-service/workers/stack_bootstrap_worker.rb @@ -26,9 +26,15 @@ class StackBootstrapWorker < Worker return 1 end + #TODO: errors begin - servers = persist_stack_servers!(stack) - bootstrap_servers!(servers, report) unless without_bootstrap + servers_with_priority = persist_stack_servers!(stack) + unless without_bootstrap + sorted_keys = servers_with_priority.keys.sort{|x,y| y <=> x} + sorted_keys.each do |key| + bootstrap_servers!(servers_with_priority[key], report) + end + end rescue BootstrapingStackServerError @out.puts "\nAn error occured during bootstraping stack servers. Initiating stack rollback." rollback_stack!(stack) @@ -75,7 +81,7 @@ class StackBootstrapWorker < Worker def bootstrap_servers!(servers, report) @out << "\nStart bootstraping stack servers\n" - report.subreports = subreports = [] + subreports = [] data = {} servers.each do |server| sjid = Worker.start_async(BootstrapWorker, @@ -153,6 +159,10 @@ class StackBootstrapWorker < Worker report end + # returns + # { + # "priority" => [Servers] + # } def persist_stack_servers!(stack) @out.puts "Start syncing stack servers with CID" @out.flush @@ -160,30 +170,37 @@ class StackBootstrapWorker < Worker deploy_env = project.deploy_env(stack.deploy_env) provider = stack.provider_instance - servers = provider.stack_servers(stack).map do |extended_info| - server_attrs = { - 'provider' => provider.name, - 'project' => project.id, - 'deploy_env' => deploy_env.identifier, - 'remote_user' => mongo.image(deploy_env.image).remote_user, - 'key' => extended_info["key_name"] || provider.ssh_key, - '_id' => extended_info["id"], - 'chef_node_name' => extended_info["name"], - 'private_ip' => extended_info["private_ip"], - 'public_ip' => extended_info["public_ip"], - 'created_by' => stack.owner, - 'run_list' => stack.run_list || [], - 'stack' => stack.name - } + stack_servers_info = provider.stack_servers(stack).group_by{|info| info["tags"]["cid:priority"] || 0} + stack_servers_with_priority = {} + stack_servers_info.each do |priority, info_array| + stack_servers_with_priority[priority] = info_array.map do |extended_info| + server_attrs = { + 'provider' => provider.name, + 'project' => project.id, + 'deploy_env' => deploy_env.identifier, + 'remote_user' => mongo.image(deploy_env.image).remote_user, + 'key' => extended_info["key_name"] || provider.ssh_key, + '_id' => extended_info["id"], + 'chef_node_name' => extended_info["name"], + 'private_ip' => extended_info["private_ip"], + 'public_ip' => extended_info["public_ip"], + 'created_by' => stack.owner, + 'run_list' => stack.run_list || [], + 'stack' => stack.name + } - server = ::Devops::Model::Server.new(server_attrs) - mongo.server_insert(server) - # server.chef_node_name = provider.create_default_chef_node_name(server) - server + server = ::Devops::Model::Server.new(server_attrs) + mongo.server_insert(server) + # server.chef_node_name = provider.create_default_chef_node_name(server) + server + end end @out.puts "Stack servers have been synced with CID" + stack_servers_info.each do |priority, servers| + @out.puts "Priority '#{priority}': #{servers.map(&:id).join(", ")}" + end @out.flush - servers + stack_servers_with_priority end end From 034018fb42454a2773846c83bf0e9965eec706d6 Mon Sep 17 00:00:00 2001 From: amartynov Date: Thu, 5 Nov 2015 16:47:12 +0300 Subject: [PATCH 15/23] #855: some fixes --- devops-service/workers/stack_bootstrap_worker.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/devops-service/workers/stack_bootstrap_worker.rb b/devops-service/workers/stack_bootstrap_worker.rb index cc98b19..5bfbb22 100644 --- a/devops-service/workers/stack_bootstrap_worker.rb +++ b/devops-service/workers/stack_bootstrap_worker.rb @@ -35,6 +35,8 @@ class StackBootstrapWorker < Worker bootstrap_servers!(servers_with_priority[key], report) end end + @out.puts "Done." + 0 rescue BootstrapingStackServerError @out.puts "\nAn error occured during bootstraping stack servers. Initiating stack rollback." rollback_stack!(stack) @@ -153,7 +155,9 @@ class StackBootstrapWorker < Worker "created_by" => stack_attrs['owner'], "project" => stack_attrs["project"], "deploy_env" => stack_attrs["deploy_env"], - "type" => ::Devops::Model::Report::STACK_TYPE + "type" => ::Devops::Model::Report::STACK_TYPE, + "subreports" => [], + "stack" => stack_attrs['name'] ) mongo.save_report(report) report @@ -196,7 +200,7 @@ class StackBootstrapWorker < Worker end end @out.puts "Stack servers have been synced with CID" - stack_servers_info.each do |priority, servers| + stack_servers_with_priority.each do |priority, servers| @out.puts "Priority '#{priority}': #{servers.map(&:id).join(", ")}" end @out.flush From 6fd7275f2e04dd70dfa3d12c419df3206e70a962 Mon Sep 17 00:00:00 2001 From: amartynov Date: Fri, 6 Nov 2015 11:55:36 +0300 Subject: [PATCH 16/23] #855: cid:priority tag to integer --- devops-service/workers/stack_bootstrap_worker.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/devops-service/workers/stack_bootstrap_worker.rb b/devops-service/workers/stack_bootstrap_worker.rb index 5bfbb22..442e793 100644 --- a/devops-service/workers/stack_bootstrap_worker.rb +++ b/devops-service/workers/stack_bootstrap_worker.rb @@ -32,6 +32,7 @@ class StackBootstrapWorker < Worker unless without_bootstrap sorted_keys = servers_with_priority.keys.sort{|x,y| y <=> x} sorted_keys.each do |key| + @out.puts "Servers with priority '#{key}':" bootstrap_servers!(servers_with_priority[key], report) end end @@ -174,7 +175,11 @@ class StackBootstrapWorker < Worker deploy_env = project.deploy_env(stack.deploy_env) provider = stack.provider_instance - stack_servers_info = provider.stack_servers(stack).group_by{|info| info["tags"]["cid:priority"] || 0} + stack_servers = provider.stack_servers(stack) + stack_servers.each do |info| + info["tags"]["cid:priority"] = info["tags"]["cid:priority"].to_i + end + stack_servers_info = stack_servers.group_by{|info| info["tags"]["cid:priority"]} stack_servers_with_priority = {} stack_servers_info.each do |priority, info_array| stack_servers_with_priority[priority] = info_array.map do |extended_info| @@ -201,7 +206,7 @@ class StackBootstrapWorker < Worker end @out.puts "Stack servers have been synced with CID" stack_servers_with_priority.each do |priority, servers| - @out.puts "Priority '#{priority}': #{servers.map(&:id).join(", ")}" + @out.puts "Servers with priority '#{priority}': #{servers.map(&:id).join(", ")}" end @out.flush stack_servers_with_priority From e26fa71311a0060b98dc902f9bf21e92572f0d51 Mon Sep 17 00:00:00 2001 From: amartynov Date: Fri, 6 Nov 2015 12:52:31 +0300 Subject: [PATCH 17/23] #840: two_phase_bootstrap option :deploy_info to override project deploy_info --- devops-service/lib/executors/server_executor.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/devops-service/lib/executors/server_executor.rb b/devops-service/lib/executors/server_executor.rb index 429bedb..88c9131 100644 --- a/devops-service/lib/executors/server_executor.rb +++ b/devops-service/lib/executors/server_executor.rb @@ -262,7 +262,7 @@ module Devops @out << "\nComputed run list: #{run_list.join(", ")}" @out.flush @knife_instance.set_run_list(@server.chef_node_name, run_list) - deploy_info = @project.deploy_info(@deploy_env) + deploy_info = options[:deploy_info] || @project.deploy_info(@deploy_env) deploy_status = deploy_server(deploy_info) if deploy_status == 0 0 @@ -352,8 +352,7 @@ module Devops deploy_info.delete("use_json_file") @out << "Deploy Input Parameters:\n" json = JSON.pretty_generate(deploy_info) - @out << json - @out << "\n" + @out.puts json 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| From daaa73b8f4edb83ae2494973a132bdaef2dada79 Mon Sep 17 00:00:00 2001 From: amartynov Date: Fri, 6 Nov 2015 13:53:52 +0300 Subject: [PATCH 18/23] #840: additional log --- devops-service/lib/executors/server_executor.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/devops-service/lib/executors/server_executor.rb b/devops-service/lib/executors/server_executor.rb index 88c9131..57e7109 100644 --- a/devops-service/lib/executors/server_executor.rb +++ b/devops-service/lib/executors/server_executor.rb @@ -190,8 +190,10 @@ module Devops @out << "After bootstrap hooks...\n" res = self.run_hook(:after_bootstrap, @out) @out << "Done\n" + msg = "Server with id '#{@server.id}' is bootstraped" + @out.puts msg @out.flush - DevopsLogger.logger.info "Server with id '#{@server.id}' is bootstraped" + DevopsLogger.logger.info msg r else @out << "Can not bootstrap node '#{@server.id}', error code: #{r}" From 84822598a2bbb618da8e44259ab0db379f129ae0 Mon Sep 17 00:00:00 2001 From: amartynov Date: Fri, 6 Nov 2015 14:00:24 +0300 Subject: [PATCH 19/23] #840: some logs --- devops-service/lib/executors/server_executor.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/devops-service/lib/executors/server_executor.rb b/devops-service/lib/executors/server_executor.rb index 57e7109..27a072b 100644 --- a/devops-service/lib/executors/server_executor.rb +++ b/devops-service/lib/executors/server_executor.rb @@ -235,7 +235,8 @@ module Devops if check_server @out << "Server #{@server.chef_node_name} is created" else - @out << roll_back + @out.puts "Can not find client or node on chef-server" + roll_back @out.flush mongo.server_delete @server.id return result_code(:server_not_in_chef_nodes) @@ -429,13 +430,14 @@ module Devops end def roll_back + @out.puts "Trying to roll back..." unless @server.id.nil? - @out << "Server '#{@server.chef_node_name}' with id '#{@server.id}' is not created\n" - @out << delete_from_chef_server(@server.chef_node_name).values.join("\n") + @out.puts "Server '#{@server.chef_node_name}' with id '#{@server.id}' is not created" + @out.puts delete_from_chef_server(@server.chef_node_name).values.join("\n") begin - @out << @server.provider_instance.delete_server(@server) + @out.puts @server.provider_instance.delete_server(@server) rescue => e - @out << e.message + @out.puts e.message end @out << "\nRolled back\n" end From 74a9530888c9c1e5f4a9abc2e9e2db2ac3d400cb Mon Sep 17 00:00:00 2001 From: amartynov Date: Fri, 6 Nov 2015 16:11:28 +0300 Subject: [PATCH 20/23] #840: new deploy_info parameter 'json_file' --- .../lib/executors/server_executor.rb | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/devops-service/lib/executors/server_executor.rb b/devops-service/lib/executors/server_executor.rb index 27a072b..febcfed 100644 --- a/devops-service/lib/executors/server_executor.rb +++ b/devops-service/lib/executors/server_executor.rb @@ -353,14 +353,20 @@ module Devops cmd = "chef-client --no-color" if deploy_info["use_json_file"] deploy_info.delete("use_json_file") - @out << "Deploy Input Parameters:\n" - json = JSON.pretty_generate(deploy_info) - @out.puts json - file = "#{@server.project}_#{@server.deploy_env}_#{Time.new.to_i}" + json = nil dir = DevopsConfig.config[:project_info_dir] - File.open(File.join(dir, file), "w") do |f| - f.write json + file = deploy_info["json_file"] || "#{@server.project}_#{@server.deploy_env}_#{Time.new.to_i}" + path = File.join(dir, file) + if File.exists?(path) + json = File.read(path) + else + json = JSON.pretty_generate(deploy_info) + File.open(File.join(dir, file), "w") do |f| + f.write json + end end + @out << "Deploy Input Parameters:\n" + @out.puts json @out.flush cmd << " -j http://#{DevopsConfig.config[:address]}:#{DevopsConfig.config[:port]}/#{DevopsConfig.config[:url_prefix]}/v2.0/deploy/data/#{file}" else From d64bb32ed7b0a62ae92b50b0e1e1aca7049327f7 Mon Sep 17 00:00:00 2001 From: Anton Chuchkalov Date: Mon, 9 Nov 2015 18:57:22 +0300 Subject: [PATCH 21/23] #648: track server's last operation --- devops-service/app/api2/handlers/server.rb | 17 ++++++++++--- devops-service/db/mongo/connectors/server.rb | 3 --- devops-service/db/mongo/models/server.rb | 25 ++++++++++++++++--- devops-service/db/validators/all.rb | 2 +- .../lib/executors/server_executor.rb | 5 ++++ 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/devops-service/app/api2/handlers/server.rb b/devops-service/app/api2/handlers/server.rb index 6eb4cbd..bd27bf8 100644 --- a/devops-service/app/api2/handlers/server.rb +++ b/devops-service/app/api2/handlers/server.rb @@ -79,12 +79,14 @@ module Devops end def pause_server node_name - s = Server.get_server_by_key(node_name, parser.instance_key) + s = get_server_by_key(node_name, parser.instance_key) ## Authorization Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user provider = s.provider_instance r = provider.pause_server s if r.nil? + set_last_operation_type_and_save(s, Devops::Model::Server::OperationType::PAUSE) + "Server with instance ID '#{s.id}' and node name '#{node_name}' is paused" else raise ConflictException.new("Server with instance ID '#{s.id}' and node name '#{node_name}' can not be paused, It in state '#{r}'", 409) @@ -92,12 +94,14 @@ module Devops end def unpause_server node_name - s = Server.get_server_by_key(node_name, parser.instance_key) + s = get_server_by_key(node_name, parser.instance_key) ## Authorization Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user provider = s.provider_instance r = provider.unpause_server s if r.nil? + set_last_operation_type_and_save(s, Devops::Model::Server::OperationType::UNPAUSE) + "Server with instance ID '#{s.id}' and node name '#{node_name}' is unpaused" else raise ConflictException.new("Server with instance ID '#{s.id}' and node name '#{node_name}' can not be unpaused, It in state '#{r}'") @@ -110,7 +114,7 @@ module Devops 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? s.reserved_by = user - Devops::Db.connector.server_update(s) + set_last_operation_type_and_save(s, Devops::Model::Server::OperationType::RESERVE) end def unreserve_server node_name @@ -118,7 +122,7 @@ module Devops 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? s.reserved_by = nil - Devops::Db.connector.server_update(s) + set_last_operation_type_and_save(s, Devops::Model::Server::OperationType::UNRESERVE) end # TODO: check bootstrap template name @@ -284,6 +288,11 @@ module Devops end end + def set_last_operation_type_and_save(server, operation_type) + server.set_last_operation(operation_type) + Devops::Db.connector.server_update(server) + end + end end end diff --git a/devops-service/db/mongo/connectors/server.rb b/devops-service/db/mongo/connectors/server.rb index 4ab4fea..12f9e2a 100644 --- a/devops-service/db/mongo/connectors/server.rb +++ b/devops-service/db/mongo/connectors/server.rb @@ -63,17 +63,14 @@ module Connectors end def server_insert(server) - #server.validate! server.created_at = Time.now collection.insert(server.to_mongo_hash) end - # somewhy servers are not validated in previous version of code. I leave this until I know, why. def server_update(server) collection.update({'_id' => server.id}, server.to_hash_without_id) end - # somewhy servers are not validated in previous version of code. I leave this until I know, why. def server_set_chef_node_name(server) collection.update({'_id' => server.id}, {'$set' => {'chef_node_name' => server.chef_node_name}}) end diff --git a/devops-service/db/mongo/models/server.rb b/devops-service/db/mongo/models/server.rb index c9fc4f9..91ec775 100644 --- a/devops-service/db/mongo/models/server.rb +++ b/devops-service/db/mongo/models/server.rb @@ -9,8 +9,17 @@ module Devops include ModelWithProvider + module OperationType + CREATION = :creation + DEPLOY = :deploy + RESERVE = :reserve + UNRESERVE = :unreserve + PAUSE = :pause + UNPAUSE = :unpause + end + attr_accessor :chef_node_name, :id, :remote_user, :project, :deploy_env, :private_ip, :public_ip, :created_at, :without_bootstrap, :created_by, :reserved_by, :stack, :run_list - attr_accessor :key + attr_accessor :key, :last_operation_at, :last_operation_type types :id => {:type => String, :empty => false}, :provider => {:type => String, :empty => false}, @@ -29,7 +38,8 @@ module Devops set_validators ::Validators::DeployEnv::RunList def self.fields - ["chef_node_name", "project", "deploy_env", "provider", "remote_user", "private_ip", "public_ip", "created_at", "created_by", "key", "reserved_by", "run_list", "stack"] + ["chef_node_name", "project", "deploy_env", "provider", "remote_user", "private_ip", "public_ip", "created_at", "created_by", "key", "reserved_by", "run_list", "stack", + "last_operation_type", "last_operation_at"] end def initialize s={} @@ -47,6 +57,8 @@ module Devops self.reserved_by = s["reserved_by"] self.stack = s["stack"] self.run_list = s["run_list"] || [] + self.last_operation_at = s["last_operation_at"] + self.last_operation_type = s["last_operation_type"] self end @@ -77,7 +89,9 @@ module Devops "key" => self.key, "reserved_by" => self.reserved_by, "stack" => stack, - "run_list" => self.run_list + "run_list" => self.run_list, + "last_operation_at" => self.last_operation_at, + "last_operation_type" => self.last_operation_type }.merge(provider_hash).delete_if { |k,v| v.nil? } end @@ -100,6 +114,11 @@ module Devops self.provider == Provider::Static::PROVIDER end + def set_last_operation(operation_type) + self.last_operation_type = operation_type + self.last_operation_at = Time.now + end + end end end diff --git a/devops-service/db/validators/all.rb b/devops-service/db/validators/all.rb index 37f2e28..dc27475 100644 --- a/devops-service/db/validators/all.rb +++ b/devops-service/db/validators/all.rb @@ -12,5 +12,5 @@ require "db/validators/base" 'db/validators/key/*.rb', 'db/validators/image/*.rb' ].each do |files_regexp| - Dir[files_regexp].each {|file| require file } + Dir[File.join(Devops::Application.root, files_regexp)].each {|file| require file } end diff --git a/devops-service/lib/executors/server_executor.rb b/devops-service/lib/executors/server_executor.rb index d53539d..886d399 100644 --- a/devops-service/lib/executors/server_executor.rb +++ b/devops-service/lib/executors/server_executor.rb @@ -76,6 +76,7 @@ module Devops def create_server options @server = Devops::Model::Server.new({"project" => @project.id, "deploy_env" => @deploy_env.identifier, "created_by" => options["created_by"], "provider" => @deploy_env.provider, "provider_account" => @deploy_env.provider_account}) + @server.set_last_operation(Devops::Model::Server::OperationType::CREATION) provider = @deploy_env.provider_instance mongo = ::Devops::Db.connector begin @@ -378,6 +379,10 @@ module Devops @out << "\nAfter deploy hooks...\n" res = self.run_hook(:after_deploy, @out, deploy_info) @out << "Done\n" + + @server.set_last_operation(Devops::Model::Server::OperationType::DEPLOY) + Devops::Db.connector.server_update(@server) + 0 end end From 7c8122eb118c9a4e1811086574ec411a4fba9444 Mon Sep 17 00:00:00 2001 From: amartynov Date: Tue, 10 Nov 2015 11:31:21 +0300 Subject: [PATCH 22/23] #853: fixed (#866) --- devops-service/app/api2/handlers/server.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/devops-service/app/api2/handlers/server.rb b/devops-service/app/api2/handlers/server.rb index f4f4cbc..742e806 100644 --- a/devops-service/app/api2/handlers/server.rb +++ b/devops-service/app/api2/handlers/server.rb @@ -113,14 +113,6 @@ module Devops }) end - def servers names - servers = Devops::Db.connector.servers(nil, nil, names, true) - raise RecordNotFound.new("No reserved servers found for names '#{names.join("', '")}'") if servers.empty? - servers.sort_by!{|s| names.index(s.chef_node_name)} - servers - end - - def pause_server node_name s = Server.get_server_by_key(node_name, parser.instance_key) ## Authorization From 5bd098c818937b44f90dc6dd7aaf89589c4e7a1f Mon Sep 17 00:00:00 2001 From: amartynov Date: Tue, 10 Nov 2015 11:38:04 +0300 Subject: [PATCH 23/23] version: 2.3.2 --- devops-service/app/version/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devops-service/app/version/version.rb b/devops-service/app/version/version.rb index b32fcd3..5e423f6 100644 --- a/devops-service/app/version/version.rb +++ b/devops-service/app/version/version.rb @@ -2,7 +2,7 @@ require 'sinatra/base' class DevopsVersion < Sinatra::Base - VERSION = "2.3.0" + VERSION = "2.3.2" get "/" do VERSION