diff --git a/devops-service/app/api2/handlers/server.rb b/devops-service/app/api2/handlers/server.rb index e830b70..e79bb1f 100644 --- a/devops-service/app/api2/handlers/server.rb +++ b/devops-service/app/api2/handlers/server.rb @@ -85,9 +85,9 @@ module Devops p = Devops::Db.connector.check_project_auth(body["project"], body["deploy_env"], user) env = p.deploy_env(body["deploy_env"]) - provider = ::Provider::ProviderFactory.get(env.provider) + provider = env.provider_instance server_name = body["name"] - check_chef_node_name(server_name, provider) unless server_name.nil? + check_chef_node_name(server_name, provider, KnifeFactory.instance) unless server_name.nil? groups = body["groups"] unless groups.nil? buf = groups - provider.groups.keys @@ -95,15 +95,13 @@ module Devops end yield p, env, user, body - - #Server.extract_servers(provider, p, env, body, user) end def pause_server node_name s = Server.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 = ::Provider::ProviderFactory.get(s.provider) + provider = s.provider_instance r = provider.pause_server s if r.nil? "Server with instance ID '#{s.id}' and node name '#{node_name}' is paused" @@ -116,7 +114,7 @@ module Devops s = Server.get_server_by_key(node_name, parser.instance_key) ## Authorization Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user - provider = ::Provider::ProviderFactory.get(s.provider) + provider = s.provider_instance r = provider.unpause_server s if r.nil? "Server with instance ID '#{s.id}' and node name '#{node_name}' is unpaused" @@ -201,9 +199,9 @@ module Devops p = Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user d = p.deploy_env(s.deploy_env) - provider = ::Provider::ProviderFactory.get(s.provider) + provider = s.provider_instance - check_chef_node_name(name, provider) unless name.nil? + check_chef_node_name(name, provider, KnifeFactory.instance) unless name.nil? unless t.nil? templates = get_templates halt_response("Invalid bootstrap template '#{t}', available values: #{templates.join(", ")}", 400) unless templates.include?(t) @@ -249,16 +247,14 @@ module Devops def prepare_tags node_name s = get_server_by_key(node_name, parser.instance_key) - user = parser.current_user - Devops::Db.connector.check_project_auth s.project, s.deploy_env, user + Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user provider = ::Provider::ProviderFactory.get(s.provider) yield s.id, provider end def set_run_list node_name s = get_server_by_key(node_name, parser.instance_key) - user = parser.current_user - Devops::Db.connector.check_project_auth s.project, s.deploy_env, user + Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user Devops::Db.connector.set_server_run_list(s.id, parser.run_list) end @@ -267,18 +263,17 @@ module Devops key == "instance" ? mongo.server_by_instance_id(id) : mongo.server_by_chef_node_name(id) end - def check_chef_node_name name, provider - mongo = Devops::Db.connector - mongo.server_by_chef_node_name name - halt(400, "Server with name '#{name}' already exist") + def check_chef_node_name name, provider, knife + Devops::Db.connector.server_by_chef_node_name(name) + raise InvalidRecord.new("Server with name '#{name}' already exist") rescue RecordNotFound => e # server not found - OK s = provider.servers.detect {|s| s["name"] == name} - halt(400, "#{provider.name} node with name '#{name}' already exist") unless s.nil? - s = KnifeFactory.instance.chef_node_list.detect {|n| n == name} - halt(400, "Chef node with name '#{name}' already exist") unless s.nil? - s = KnifeFactory.instance.chef_client_list.detect {|c| c == name} - halt(400, "Chef client with name '#{name}' already exist") unless s.nil? + raise InvalidRecord.new("#{provider.name} node with name '#{name}' already exist") unless s.nil? + s = knife.chef_node_list.detect {|n| n == name} + raise InvalidRecord.new("Chef node with name '#{name}' already exist") unless s.nil? + s = knife.chef_client_list.detect {|c| c == name} + raise InvalidRecord.new("Chef client with name '#{name}' already exist") unless s.nil? end end diff --git a/devops-service/app/api2/handlers/stack.rb b/devops-service/app/api2/handlers/stack.rb index d190b00..ce9ec93 100644 --- a/devops-service/app/api2/handlers/stack.rb +++ b/devops-service/app/api2/handlers/stack.rb @@ -1,3 +1,4 @@ +require "lib/executors/server_executor" require 'db/mongo/models/stack/stack_factory' require "app/api2/parsers/stack" require_relative "request_handler" @@ -77,6 +78,86 @@ module Devops def set_run_list id Devops::Db.connector.set_stack_run_list(id, parser.run_list) end + + def deploy id + stack = self.stack(id) + owner = parser.current_user + status = [] + project = Devops::Db.connector.check_project_auth(stack.project, stack.deploy_env, owner) + body = parser.deploy + names = body["names"] + tags = body["tags"] || [] + dir = DevopsConfig.config[:report_dir_v2] + files = [] + jid = nil + uri = URI.parse(parser.request.url) + servers = Devops::Db.connector.stack_servers(stack_id, true) + deploy_info = project.deploy_info(stack.deploy_env, nil) + servers.each do |s| + begin + jid = DeployWorker.perform_async(dir, s.to_hash, tags, owner, DevopsConfig.config, deploy_info) + Worker.set_status jid, Worker::STATUS::IN_QUEUE + DevopsLogger.logger.info "Job '#{jid}' has been queued" + rescue DeployInfoError => e + msg = "Can not get deploy info: " + e.message + DevopsLogger.logger.error msg + jid = "error_#{s.chef_node_name}_#{Time.new.to_i}" + file = File.jon(dir, jid) + File.open(file, "w") do |out| + #unless attributes.nil? + # out << "Report attributes: #{attributes.inspect}\n" + #end + out.write msg + end + o = { + "file" => file, + "_id" => jid, + "created_by" => owner, + "project" => s.project, + "deploy_env" => s.deploy_env, + "type" => Report::DEPLOY_TYPE, + "status" => Worker::STATUS::FAILED +# "attributes" => attributes + } + Devops::Db.connector.save_report(Report.new(o)) + end + uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid + files.push uri.to_s + end + files + + end + + def deploy_stream id, out + stack = self.stack(id) + owner = parser.current_user + status = [] + project = Devops::Db.connector.check_project_auth(stack.project, stack.deploy_env, owner) + body = parser.deploy + #TODO: deploy servers names +# names = body["names"] + tags = body["tags"] || [] + # find all stack reserved servers + servers = Devops::Db.connector.stack_servers(stack_id, true) + deploy_info = project.deploy_info(stack.deploy_env, nil) + servers.each do |s| + begin + res = Devops::Executor::ServerExecutor.new(s, out).deploy_server_with_tags(tags, deploy_info) + status.push(res) + rescue DeployInfoError => e + msg = "Can not get deploy info: " + e.message + DevopsLogger.logger.error msg + out << msg + "\n" + status.push 2 + next + end + end + status + rescue RecordNotFound => e + out << e.message + [-10] + end + end end end diff --git a/devops-service/app/api2/handlers/tag.rb b/devops-service/app/api2/handlers/tag.rb index 5027ffb..de072e7 100644 --- a/devops-service/app/api2/handlers/tag.rb +++ b/devops-service/app/api2/handlers/tag.rb @@ -16,13 +16,13 @@ module Devops end def tags node_name - KnifeCommands.tags_list(node_name) + KnifeFactory.instance.tags_list(node_name) end def set_tags node_name tags = parser.tags tagsStr = tags.join(" ") - cmd = KnifeCommands.tags_create(node_name, tagsStr) + cmd = KnifeFactory.instance.tags_create(node_name, tagsStr) halt_response("Cannot add tags #{tagsStr} to server #{node_name}", 500) unless cmd[1] tags end @@ -30,7 +30,7 @@ module Devops def unset_tags node_name tags = parser.tags tagsStr = tags.join(" ") - cmd = KnifeCommands.tags_delete(node_name, tagsStr) + cmd = KnifeFactory.instance.tags_delete(node_name, tagsStr) halt_response("Cannot delete tags #{tagsStr} from server #{node_name}: #{cmd[0]}", 500) unless cmd[1] tags end diff --git a/devops-service/app/api2/parsers/stack.rb b/devops-service/app/api2/parsers/stack.rb index cc50706..42e666a 100644 --- a/devops-service/app/api2/parsers/stack.rb +++ b/devops-service/app/api2/parsers/stack.rb @@ -21,6 +21,13 @@ module Devops list end + def deploy + @body ||= create_object_from_json_body + names = check_array(@body["names"], "Parameter 'names' should be a not empty array of strings", String, true) + tags = check_array(@body["tags"], "Parameter 'tags' should be an array of strings", String, true) + @body + end + end end end diff --git a/devops-service/app/api2/routes/stack.rb b/devops-service/app/api2/routes/stack.rb index 7202206..c3aa9a3 100644 --- a/devops-service/app/api2/routes/stack.rb +++ b/devops-service/app/api2/routes/stack.rb @@ -72,6 +72,39 @@ module Devops create_response(info) end + # Deploy stack instances + # + # * *Request* + # - method : POST + # - headers : + # - Accept: application/json + # - Content-Type: application/json + # - body : + # { + # "tags" : ["tag1", "tag2"] + # } + # + # * *Returns* : + # 200 - Updated + app.patch_with_headers "/stack/:id/deploy", :headers => [:accept, :content_type] do |id| + check_privileges("stack", "x") + if request["X-Stream"] + stream() do |out| + status = [] + begin + status = Devops::API2_0::Handler::Stack.new(request).deploy_stream(id, out) + out << create_status(status) + rescue IOError => e + logger.error e.message + break + end + end # stream + else + files = Devops::API2_0::Handler::Stack.new(request).deploy(id) + sleep 1 + json files + end + end puts "Stack routes initialized" end diff --git a/devops-service/db/mongo/connectors/server.rb b/devops-service/db/mongo/connectors/server.rb index 8adb509..fa1eb7b 100644 --- a/devops-service/db/mongo/connectors/server.rb +++ b/devops-service/db/mongo/connectors/server.rb @@ -29,8 +29,10 @@ module Connectors servers_find(q, f) end - def stack_servers(stack_id) - list('stack' => stack_id) + def stack_servers(stack_id, reserver=nil, options={}) + q = {'stack' => stack_id} + q['reserved_by'] = {'$ne' => nil} unless reserved.nil? + list(q, options) end def servers_by_names(names) @@ -72,7 +74,7 @@ module Connectors end def set_server_run_list(id, run_list) - @collection.update({"_id" => id}, {"$set" => {"run_list" => run_list}}) + collection.update({"_id" => id}, {"$set" => {"run_list" => run_list}}) end private diff --git a/devops-service/db/mongo/models/project.rb b/devops-service/db/mongo/models/project.rb index 4331ebc..88e353a 100644 --- a/devops-service/db/mongo/models/project.rb +++ b/devops-service/db/mongo/models/project.rb @@ -134,7 +134,15 @@ module Devops end def deploy_info deploy_env, build_number - {} + { + "run_list" => deploy_env.run_list, + "project" => self.id, + "project_info" => { + "project" => self.id, + "deploy_env" => deploy_env.identifier, + "deployers" => deploy_env.users + } + } end def to_hash_without_id diff --git a/devops-service/lib/project/type/generic_type.rb b/devops-service/lib/project/type/generic_type.rb index ae81da0..4319996 100644 --- a/devops-service/lib/project/type/generic_type.rb +++ b/devops-service/lib/project/type/generic_type.rb @@ -10,6 +10,7 @@ module Devops include ProjectType def prepare project + #TODO: without creating roles #project.before_create create_roles end