diff --git a/devops-service/app/api2/handlers/image.rb b/devops-service/app/api2/handlers/image.rb index 73c7703..08278e8 100644 --- a/devops-service/app/api2/handlers/image.rb +++ b/devops-service/app/api2/handlers/image.rb @@ -1,72 +1,48 @@ require "providers/provider_factory" require "commands/image" +require_relative "request_handler" module Devops - module Version2_0 + module API2_0 module Handler - class Image + class Image < RequestHandler extend ImageCommands - def self.get_images - lambda { - check_privileges("image", "r") - check_provider(params[:provider]) if params[:provider] - images = settings.mongo.images(params[:provider]) - json(images.map {|i| i.to_hash}) - } + def images provider + Devops::Db.connector.images(provider) end - def self.get_provider_images - lambda { - check_privileges("image", "r") - check_provider(params[:provider]) - json Image.get_available_provider_images(settings.mongo, params[:provider]) - } + def provider_images provider + Image.get_available_provider_images(Devops::Db.connector, provider) end - def self.get_image - lambda { - check_privileges("image", "r") - json settings.mongo.image(params[:image_id]) - } + def get_image id + Devops::Db.connector.image(id) end - def self.create_image - lambda { - check_privileges("image", "w") - image = create_object_from_json_body - settings.mongo.image_insert Devops::Model::Image.new(image) - create_response "Created", nil, 201 - } + def create_image image + Devops::Db.connector.image_insert Devops::Model::Image.new(image) end - def self.update_image - lambda { - check_privileges("image", "w") - settings.mongo.image params[:image_id] - image = Devops::Model::Image.new(create_object_from_json_body) - image.id = params[:image_id] - settings.mongo.image_update image - create_response("Image '#{params[:image_id]}' has been updated") - } + def update_image id, image + Devops::Db.connector.image id + obj = Devops::Model::Image.new(image) + obj.id = id + Devops::Db.connector.image_update image end - def self.delete_image - lambda { - check_privileges("image", "w") - projects = settings.mongo.projects_by_image params[:image_id] - unless projects.empty? - ar = [] - projects.each do |p| - ar += p.deploy_envs.select{|e| e.respond_to?(:image)}.select{|e| e.image == params[:image_id]}.map{|e| "#{p.id}.#{e.identifier}"} - end - raise DependencyError.new "Deleting is forbidden: Image is used in #{ar.join(", ")}" + def delete_image id + projects = Devops::Db.connector.projects_by_image id + unless projects.empty? + ar = [] + projects.each do |p| + ar += p.deploy_envs.select{|e| e.respond_to?(:image)}.select{|e| e.image == id}.map{|e| "#{p.id}.#{e.identifier}"} end + raise DependencyError.new "Deleting is forbidden: Image is used in #{ar.join(", ")}" + end - r = settings.mongo.image_delete params[:image_id] - create_response("Image '#{params[:image_id]}' has been removed") - } + Devops::Db.connector.image_delete id end end end diff --git a/devops-service/app/api2/handlers/network.rb b/devops-service/app/api2/handlers/network.rb index c9b67ed..81964c3 100644 --- a/devops-service/app/api2/handlers/network.rb +++ b/devops-service/app/api2/handlers/network.rb @@ -1,17 +1,14 @@ require "providers/provider_factory" +require_relative "request_handler" module Devops - module Version2_0 + module API2_0 module Handler - class Network + class Network < RequestHandler - def self.get_networks - lambda { - check_privileges("network", "r") - check_provider(params[:provider]) - p = ::Provider::ProviderFactory.get params[:provider] - json p.networks_detail - } + def networks provider + p = ::Provider::ProviderFactory.get provider + p.networks_detail end end end diff --git a/devops-service/app/api2/handlers/project.rb b/devops-service/app/api2/handlers/project.rb index e6b0eb0..f4f5de1 100644 --- a/devops-service/app/api2/handlers/project.rb +++ b/devops-service/app/api2/handlers/project.rb @@ -3,261 +3,187 @@ require "commands/status" require "commands/server" require "db/mongo/models/project" require "workers/project_test_worker" +require_relative "request_handler" module Devops - module Version2_0 + module API2_0 module Handler - class Project + class Project < RequestHandler extend DeployCommands extend StatusCommands extend ServerCommands - def self.get_projects - lambda { - check_privileges("project", "r") - fields = [] - if params.key?("fields") and params["fields"].is_a?(Array) - Devops::Model::Project.fields.each do |k| - fields.push k if params["fields"].include?(k) - end + def projects + fields = [] + if @params.key?("fields") and @params["fields"].is_a?(Array) + Devops::Model::Project.fields.each do |k| + fields.push k if @params["fields"].include?(k) end - archived = params.include?("archived") - json settings.mongo.projects(nil, nil, fields, archived).map {|p| p.to_hash} - } + end + archived = @params.include?("archived") + Devops::Db.connector.projects(nil, nil, fields, archived) end - def self.get_project - lambda { - check_privileges("project", "r") - json settings.mongo.project(params[:project]) - } + def project id + Devops::Db.connector.project(id) end - def self.get_project_servers - lambda { - check_privileges("project", "r") - settings.mongo.project(params[:project]) - json settings.mongo.servers(params[:project], params[:deploy_env]).map{|s| s.to_hash} - } + def project_servers id + Devops::Db.connector.project(id) + Devops::Db.connector.servers(id, @params[:deploy_env]) end # TODO: multi project - def self.create_project - lambda { - check_privileges("project", "w") - body = create_object_from_json_body - check_string(body["name"], "Parameter 'name' must be a not empty string") - check_array(body["deploy_envs"], "Parameter 'deploy_envs' must be a not empty array of objects", Hash) - p = Devops::Model::Project.new(body) - halt_response("Project '#{p.id}' already exist") if settings.mongo.is_project_exists?(p) - p.add_authorized_user [request.env['REMOTE_USER']] - p.create - roles_res = "" - if p.multi? - logger.info "Project '#{p.id}' with type 'multi' created" - else - logger.info "Project '#{p.id}' created" - roles = Project.create_roles p.id, p.deploy_envs, logger - roles_res = ". " + Project.create_roles_response(roles) - end - res = "Created" + roles_res - create_response(res, nil, 201) - } + def create_project body + p = Devops::Model::Project.new(body) + halt_response("Project '#{p.id}' already exist") if Devops::Db.connector.is_project_exists?(p) + p.add_authorized_user [@request.env['REMOTE_USER']] + p.create + if p.multi? + "Project '#{p.id}' with type 'multi' created" + else + roles = create_roles p.id, p.deploy_envs, logger + "Project '#{p.id}' created. " + create_roles_response(roles) + end end # TODO: multi project - def self.update_project - lambda { - check_privileges("project", "w") - project = Devops::Model::Project.new(create_object_from_json_body) - project.id = params[:project] - old_project = settings.mongo.project params[:project] - settings.mongo.project_update project - roles = Devops::Version2_0::Handler::Project.create_new_roles(old_project, project, logger) - info = "Project '#{project.id}' has been updated." + Project.create_roles_response(roles) - create_response(info) - } + def update_project id, body + project = Devops::Model::Project.new(body) + project.id = id + old_project = Devops::Db.connector.project id + Devops::Db.connector.project_update project + roles = create_new_roles(old_project, project, logger) + create_roles_response(roles) end # TODO: multi project - def self.update_project_users - lambda { - check_privileges("project", "w") - body = create_object_from_json_body - users = check_array(body["users"], "Parameter 'users' must be a not empty array of strings") - deploy_env = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string", true) - project = settings.mongo.project(params[:id]) - users = settings.mongo.users(users).map{|u| u.id} - buf = users - users - project.add_authorized_user users, deploy_env - settings.mongo.project_update(project) - info = "Users '#{users.join("', '")}' have been added to '#{params[:id]}' project's authorized users" - info << ", invalid users: '#{buf.join("', '")}'" unless buf.empty? - create_response(info) - } + def update_project_users id, deploy_env, users + project = Devops::Db.connector.project(id) + dbusers = Devops::Db.connector.users(users).map{|u| u.id} + buf = dbusers - users + project.add_authorized_user users, deploy_env + Devops::Db.connector.project_update(project) + info = "Users '#{dbusers.join("', '")}' has been added to '#{id}' project's authorized users" + info << ", invalid users: '#{buf.join("', '")}'" unless buf.empty? + info end # TODO: multi project - def self.delete_project_users - lambda { - check_privileges("project", "w") - @project.remove_authorized_user @users, @deploy_env - settings.mongo.project_update @project - info = "Users '#{@users.join("', '")}' have been removed from '#{params[:id]}' project's authorized users" - create_response(info) - } + def delete_project_users id, deploy_env, users + project = Devops::Db.connector.project(id) + project.remove_authorized_user users, deploy_env + Devops::Db.connector.project_update project + "Users '#{users.join("', '")}' have been removed from '#{id}' project's authorized users" end # TODO: multi project - def self.set_project_env_run_list - lambda { - check_privileges("project", "w") - list = create_object_from_json_body(Array) - check_array(list, "Body must contains not empty array of strings") - project = settings.mongo.project(params[:id]) - env = project.deploy_env params[:env] - env.run_list = list - settings.mongo.project_update project - create_response("Updated environment '#{env.identifier}' with run_list '#{env.run_list.inspect}' in project '#{project.id}'") - } + def set_project_env_run_list id, deploy_env, list + project = Devops::Db.connector.project(id) + env = project.deploy_env deploy_env + env.run_list = list + Devops::Db.connector.project_update project + "Updated environment '#{env.identifier}' with run_list '#{env.run_list.inspect}' in project '#{project.id}'" end - def self.delete_project - lambda { - check_privileges("project", "w") - servers = settings.mongo.servers params[:project] - raise DependencyError.new "Deleting #{params[:project]} is forbidden: Project has servers" if !servers.empty? - body = create_object_from_json_body(Hash, true) - deploy_env = unless body.nil? - check_string(body["deploy_env"], "Parameter 'deploy_env' should be a not empty string", true) - end - project = settings.mongo.project(params[:project]) - info = if deploy_env.nil? - project.delete - "Project '#{params[:project]}' is deleted" - else - project.remove_env deploy_env - settings.mongo.project_update project - "Project '#{params[:project]}'. Deploy environment '#{deploy_env}' has been deleted" - end - create_response(info) - } + def delete_project id, deploy_env + servers = Devops::Db.connector.servers id + raise DependencyError.new "Deleting #{id} is forbidden: Project has servers" if !servers.empty? + project = Devops::Db.connector.project(id) + info = if deploy_env.nil? + project.delete + "Project '#{id}' is deleted" + else + project.remove_env deploy_env + Devops::Db.connector.project_update project + "Project '#{id}'. Deploy environment '#{deploy_env}' has been deleted" + end end - def self.deploy_project - lambda { - check_privileges("project", "x") - obj = create_object_from_json_body - check_string(obj["deploy_env"], "Parameter 'deploy_env' should be a not empty string", true) - check_array(obj["servers"], "Parameter 'servers' should be a not empty array of strings", String, true) - project = settings.mongo.project(params[:id]) - servers = settings.mongo.servers(params[:id], obj["deploy_env"], obj["servers"], true) - keys = {} - if obj.key?("trace") - stream() do |out| - begin - out << (servers.empty? ? "No reserved servers to deploy\n" : "Deploy servers: '#{servers.map{|s| s.chef_node_name}.join("', '")}'\n") - status = [] - servers.each do |s| - logger.debug "Deploy server: #{s.inspect}" - - begin - settings.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] - rescue InvalidPrivileges, RecordNotFound => e - out << e.message + "\n" - status.push 2 - next - end - unless keys.key? s.key - k = settings.mongo.key s.key - keys[s.key] = k.path - end - status.push(deploy_server(out, s, keys[s.key])) - end - out << create_status(status) - rescue IOError => e - logger.error e.message - end - end - else - dir = DevopsConfig[:report_dir_v2] - files = [] - uri = URI.parse(request.url) - servers.each do |s| - project = begin - settings.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] - rescue InvalidPrivileges, RecordNotFound => e - next - end - jid = DeployWorker.perform_async(dir, s.to_hash, [], DevopsConfig.config) - logger.info "Job '#{jid}' has been started" - uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid - files.push uri.to_s - end - json files + def deploy_project_stream out, id, deploy_env, servers, body + keys = {} + dbserver = servers(id, deploy_env, servers) + out << (dbservers.empty? ? "No reserved servers to deploy\n" : "Deploy servers: '#{dbservers.map{|s| s.chef_node_name}.join("', '")}'\n") + status = [] + servers.each do |s| + begin + Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER'] + rescue InvalidPrivileges, RecordNotFound => e + out << e.message + "\n" + status.push 2 + next end - } + unless keys.key? s.key + k = Devops::Db.connector.key s.key + keys[s.key] = k.path + end + status.push(deploy_server(out, s, keys[s.key])) + end + status end - def self.archive_project - lambda { - check_privileges("project", "w") - project = settings.mongo.project(params[:project]) - if project.nil? - create_response("Project '#{params[:project]}' not found", nil, 404) - else - settings.mongo.archive_project(params[:project]) - info = "Project '#{params[:project]}' has been archived" - create_response(info) + def deploy_project id, deploy_env, servers, body + dir = DevopsConfig[:report_dir_v2] + files = [] + uri = URI.parse(request.url) + servers(id, deploy_env, servers).each do |s| + project = begin + Devops::Db.connector.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] + rescue InvalidPrivileges, RecordNotFound => e + next end - } + jid = DeployWorker.perform_async(dir, s.to_hash, [], DevopsConfig.config) + #logger.info "Job '#{jid}' has been started" + uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid + files.push uri.to_s + end + files end - def self.unarchive_project - lambda { - check_privileges("project", "w") - project = settings.mongo.project(params[:project]) - if project.nil? - create_response("Project '#{params[:project]}' not found", nil, 404) - else - settings.mongo.unarchive_project(params[:project]) - info = "Project '#{params[:project]}' has been unarchived" - create_response(info) - end - } + def servers project_id, deploy_env, servers + project = Devops::Db.connector.project(project_id) + dbservers = Devops::Db.connector.servers(project_id, deploy_env, servers, true) end - def self.test_project - lambda { - check_privileges("project", "r") - project = settings.mongo.project(params[:id]) - env = project.deploy_env params[:env] - logger.info "Test project '#{project.id}' and environment '#{env.identifier}'" - if env.provider == ::Provider::Static::PROVIDER - msg = "Can not test environment with provider '#{::Provider::Static::PROVIDER}'" - Logger.warn msg - return [400, msg] - end - - dir = DevopsConfig[:report_dir_v2] - uri = URI.parse(request.url) - p = { - :project => project.id, - :env => env.identifier, - :user => request.env['REMOTE_USER'] - } - jid = ProjectTestWorker.perform_async(dir, p, DevopsConfig.config) - Worker.set_status jid, Worker::STATUS::IN_QUEUE - logger.info "Job '#{jid}' has been created" - uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid - files = [uri.to_s] - sleep 1 - json files - } + def archive_project id + project = Devops::Db.connector.project(id) + Devops::Db.connector.archive_project(id) + "Project '#{id}' has been archived" end - def self.create_roles project_id, envs, logger + def unarchive_project id + project = Devops::Db.connector.project(id) + Devops::Db.connector.unarchive_project(id) + "Project '#{id}' has been unarchived" + end + + def test_project id, deploy_env + project = Devops::Db.connector.project(id) + env = project.deploy_env deploy_env + #logger.info "Test project '#{project.id}' and environment '#{env.identifier}'" + if env.provider == ::Provider::Static::PROVIDER + msg = "Can not test environment with provider '#{::Provider::Static::PROVIDER}'" + Logger.warn msg + raise InvalidRecord.new(msg) + end + + dir = DevopsConfig[:report_dir_v2] + uri = URI.parse(request.url) + p = { + :project => project.id, + :env => env.identifier, + :user => @request.env['REMOTE_USER'] + } + jid = ProjectTestWorker.perform_async(dir, p, DevopsConfig.config) + Worker.set_status jid, Worker::STATUS::IN_QUEUE + #logger.info "Job '#{jid}' has been created" + uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid + sleep 1 + return [uri.to_s] + end + + def create_roles project_id, envs, logger all_roles = KnifeCommands.roles return " Can't get roles list" if all_roles.nil? roles = {:new => [], :error => [], :exist => []} @@ -279,14 +205,14 @@ module Devops roles end - def self.create_new_roles old_project, new_project, logger + def create_new_roles old_project, new_project, logger old_project.deploy_envs.each do |e| new_project.remove_env(e.identifier) end - Devops::Version2_0::Handler::Project.create_roles new_project.id, new_project.deploy_envs, logger + create_roles new_project.id, new_project.deploy_envs, logger end - def self.create_roles_response roles + def create_roles_response roles if roles.is_a?(String) roles else diff --git a/devops-service/app/api2/handlers/provider.rb b/devops-service/app/api2/handlers/provider.rb index 56aec3e..51f1167 100644 --- a/devops-service/app/api2/handlers/provider.rb +++ b/devops-service/app/api2/handlers/provider.rb @@ -1,9 +1,10 @@ require "providers/provider_factory" +require_relative "request_handler" module Devops module API2_0 module Handler - class Provider + class Provider < RequestHandler def providers ::Provider::ProviderFactory.providers diff --git a/devops-service/app/api2/handlers/server.rb b/devops-service/app/api2/handlers/server.rb index f1e5d44..202d68b 100644 --- a/devops-service/app/api2/handlers/server.rb +++ b/devops-service/app/api2/handlers/server.rb @@ -36,264 +36,200 @@ module Devops ::Provider::ProviderFactory.get(provider).servers end - def self.get_server - lambda { - check_privileges("server", "r") - json Server.get_server_by_key(params[:name], params[:key]).to_hash - } + def server id + get_server_by_key(id, @params[:key]) end - def self.delete_server - lambda { - check_privileges("server", "w") - body = create_object_from_json_body(Hash, true) - key = (body.nil? ? nil : body["key"]) - s = Server.get_server_by_key(params[:id], key) - ### Authorization - settings.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] - info, r = delete_server(s, settings.mongo, logger) - create_response(info, r) - } + def delete id, key + s = get_server_by_key(params[:id], key) + ### Authorization + Devops::Db.connector.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] + delete_server(s, Devops::Db.connector, logger) end - def self.create_server - lambda { - check_privileges("server", "w") - body = create_object_from_json_body - user = request.env['REMOTE_USER'] - project_name = check_string(body["project"], "Parameter 'project' must be a not empty string") - env_name = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string") - server_name = check_string(body["name"], "Parameter 'name' should be null or not empty string", true) - without_bootstrap = body["without_bootstrap"] - halt_response("Parameter 'without_bootstrap' should be a null or true") unless without_bootstrap.nil? or without_bootstrap == true - force = body["force"] - halt_response("Parameter 'force' should be a null or true") unless force.nil? or force == true - groups = check_array(body["groups"], "Parameter 'groups' should be null or not empty array of string", String, true) - key_name = check_string(body["key"], "Parameter 'key' should be null or not empty string", true) - new_key = settings.mongo.key(key_name) unless key_name.nil? - - p = settings.mongo.check_project_auth(project_name, env_name, user) - env = p.deploy_env(env_name) - - provider = ::Provider::ProviderFactory.get(env.provider) - Server.check_chef_node_name(server_name, provider) unless server_name.nil? - unless groups.nil? - buf = groups - provider.groups.keys - halt_response("Invalid security groups '#{buf.join("', '")}' for provider '#{provider.name}'") if buf.empty? - end - - servers = Server.extract_servers(provider, p, env, body, user, settings.mongo) - if body.key?("trace") - stream() do |out| - begin - status = [] - servers.each do |s| - res = create_server_proc.call(out, s, provider, settings.mongo) - status.push res - end - out << create_status(status) - rescue IOError => e - logger.error e.message - end - end - else - dir = DevopsConfig[:report_dir_v2] - files = [] - uri = URI.parse(request.url) - servers.each do |s| - h = s.to_hash - h["options"] = s.options - jid = CreateServerWorker.perform_async(dir, env.provider, h, request.env['REMOTE_USER'], DevopsConfig.config) - Worker.set_status jid, Worker::STATUS::IN_QUEUE - logger.info "Job '#{jid}' has been started" - uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid - files.push uri.to_s - end - sleep 1 - json files - end - } + def create_server_stream out, body + status = [] + prepare_create_server(body).each do |s| + res = create_server_proc.call(out, s, provider, Devops::Db.connector) + status.push res + end + status end - def self.pause_server - lambda { - check_privileges("server", "w") - body = create_object_from_json_body(Hash, true) - key = (body.nil? ? nil : body["key"]) - s = Server.get_server_by_key(params[:node_name], key) - ## Authorization - settings.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] - provider = ::Provider::ProviderFactory.get(s.provider) - r = provider.pause_server s - if r.nil? - create_response("Server with instance ID '#{s.id}' and node name '#{params[:node_name]}' is paused") - else - halt_response("Server with instance ID '#{s.id}' and node name '#{params[:node_name]}' can not be paused, It in state '#{r}'", 409) - end - } + def create_server body + dir = DevopsConfig[:report_dir_v2] + files = [] + uri = URI.parse(request.url) + prepare_create_server(body).each do |s| + h = s.to_hash + h["options"] = s.options + jid = CreateServerWorker.perform_async(dir, env.provider, h, @request.env['REMOTE_USER'], DevopsConfig.config) + Worker.set_status jid, Worker::STATUS::IN_QUEUE + #logger.info "Job '#{jid}' has been started" + uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid + files.push uri.to_s + end + sleep 1 + files end - def self.unpause_server - lambda { - check_privileges("server", "w") - body = create_object_from_json_body(Hash, true) - key = (body.nil? ? nil : body["key"]) - s = Server.get_server_by_key(params[:node_name], key) - ## Authorization - settings.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] - provider = ::Provider::ProviderFactory.get(s.provider) - r = provider.unpause_server s - if r.nil? - create_response("Server with instance ID '#{s.id}' and node name '#{params[:node_name]}' is unpaused") - else - halt_response("Server with instance ID '#{s.id}' and node name '#{params[:node_name]}' can not be unpaused, It in state '#{r}'", 409) - end - } + def prepare_create_server body + user = @request.env['REMOTE_USER'] + key_name = body["key"] + new_key = Devops::Db.connector.key(key_name) unless key_name.nil? + + 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) + server_name = body["name"] + check_chef_node_name(server_name, provider) unless server_name.nil? + groups = body["groups"] + unless groups.nil? + buf = groups - provider.groups.keys + halt_response("Invalid security groups '#{buf.join("', '")}' for provider '#{provider.name}'") if buf.empty? + end + + Server.extract_servers(provider, p, env, body, user, Devops::Db.connector) end - def self.reserve_server - lambda { - check_privileges("server", "w") - body = create_object_from_json_body(Hash, true) - key = (body.nil? ? nil : body["key"]) - s = Server.get_server_by_key(params[:node_name], key) - user = request.env['REMOTE_USER'] - settings.mongo.check_project_auth s.project, s.deploy_env, user - halt_response(400, "Server '#{params[:node_name]}' already reserved") unless s.reserved_by.nil? - s.reserved_by = user - settings.mongo.server_update(s) - create_response("Server '#{params[:node_name]}' has been reserved") - } + def pause_server node_name, key + s = Server.get_server_by_key(node_name, key) + ## Authorization + Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER'] + provider = ::Provider::ProviderFactory.get(s.provider) + r = provider.pause_server s + if r.nil? + "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) + end end - def self.unreserve_server - lambda { - check_privileges("server", "w") - body = create_object_from_json_body(Hash, true) - key = (body.nil? ? nil : body["key"]) - s = Server.get_server_by_key(params[:node_name], key) - settings.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] - halt_response(400, "Server '#{params[:node_name]}' is not reserved") if s.reserved_by.nil? - s.reserved_by = nil - settings.mongo.server_update(s) - create_response("Server '#{params[:node_name]}' has been unreserved") - } + def unpause_server node_name, key + s = Server.get_server_by_key(params[:node_name], key) + ## Authorization + Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER'] + provider = ::Provider::ProviderFactory.get(s.provider) + r = provider.unpause_server s + if r.nil? + "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}'") + end + end + + def reserve_server node_name, key + s = get_server_by_key(node_name, key) + Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER'] + raise ConflictException.new("Server '#{node_name}' already reserved") unless s.reserved_by.nil? + s.reserved_by = user + Devops::Db.connector.server_update(s) + end + + def unreserve_server node_name, key + s = get_server_by_key(node_name, key) + Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_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) end # TODO: check bootstrap template name - def self.bootstrap_server - lambda { - check_privileges("server", "w") - body = create_object_from_json_body(Hash, true) - id = check_string(body["instance_id"], "Parameter 'instance_id' must be a not empty string") - name = check_string(body["name"], "Parameter 'name' should be a not empty string", true) - rl = check_array(body["run_list"], "Parameter 'run_list' should be a not empty array of string", String, true) - unless rl.nil? - validator = Validators::Helpers::RunList.new(rl) - halt_response(validator.message) unless validator.valid? - end - t = check_string(body["bootstrap_template"], "Parameter 'bootstrap_template' should be a not empty string", true) - s = settings.mongo.server_by_instance_id(id) - - p = settings.mongo.check_project_auth s.project, s.deploy_env, request.env['REMOTE_USER'] - d = p.deploy_env s.deploy_env - - provider = ::Provider::ProviderFactory.get(s.provider) - - Server.check_chef_node_name(name, provider) unless name.nil? - s.options = { - :run_list => rl || d.run_list, - } - unless t.nil? - templates = get_templates - halt_response("Invalid bootstrap template '#{t}', available values: #{templates.join(", ")}", 400) unless templates.include?(t) - s.options[:bootstrap_template] = t - end - s.chef_node_name = name || provider.create_default_chef_node_name(s) - logger.debug "Chef node name: '#{s.chef_node_name}'" - status = [] - if body.key?("trace") - stream() do |out| - begin - cert = settings.mongo.key s.key - logger.debug "Bootstrap certificate path: #{cert.path}" - bootstrap s, out, cert.path, logger - str = nil - r = if check_server(s) - settings.mongo.server_set_chef_node_name s - str = "Server with id '#{s.id}' is bootstraped" - logger.info str - 0 - else - str = "Server with id '#{s.id}' is not bootstraped" - logger.warn str - 1 - end - status.push r - out << str - out << "\n" - out << create_status(status) - rescue IOError => e - logger.error e.message - end - end - else - dir = DevopsConfig[:report_dir_v2] - files = [] - uri = URI.parse(request.url) - h = s.to_hash - h["options"] = s.options - h["_id"] = s.id - jid = BootstrapWorker.perform_async(dir, d.provider, h, request.env['REMOTE_USER'], DevopsConfig.config) - Worker.set_status jid, Worker::STATUS::IN_QUEUE - logger.info "Job '#{jid}' has been started" - uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid - uri.query = nil - uri.fragment = nil - files.push uri.to_s - sleep 1 - json files - end - } + def bootstrap_server_stream out, body + s = prepare_create_server body + status = [] + cert = Devops::Db.connector.key s.key + logger.debug "Bootstrap certificate path: #{cert.path}" + bootstrap s, out, cert.path, logger + str = nil + r = if check_server(s) + Devops::Db.connector.server_set_chef_node_name s + str = "Server with id '#{s.id}' is bootstraped" + logger.info str + 0 + else + str = "Server with id '#{s.id}' is not bootstraped" + logger.warn str + 1 + end + status.push r + out << str + out << "\n" + status end - def self.add_server - lambda { - check_privileges("server", "w") - body = create_object_from_json_body - project = check_string(body["project"], "Parameter 'project' must be a not empty string") - deploy_env = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string") - key = check_string(body["key"], "Parameter 'key' must be a not empty string") - remote_user = check_string(body["remote_user"], "Parameter 'remote_user' must be a not empty string") - private_ip = check_string(body["private_ip"], "Parameter 'private_ip' must be a not empty string") - public_ip = check_string(body["public_ip"], "Parameter 'public_ip' should be a not empty string", true) - p = settings.mongo.check_project_auth project, deploy_env, request.env['REMOTE_USER'] - - d = p.deploy_env(deploy_env) - - cert = settings.mongo.key(key) - provider = ::Provider::ProviderFactory.get("static") - s = Devops::Model::Server.new - s.provider = provider.name - s.project = project - s.deploy_env = deploy_env - s.remote_user = remote_user - s.private_ip = private_ip - s.public_ip = public_ip - s.static = true - s.id = "static_#{cert.id}-#{Time.now.to_i}" - s.key = cert.id - settings.mongo.server_insert s - create_response("Server '#{s.id}' has been added") - } + def bootstrap_server body + s = prepare_create_server body + dir = DevopsConfig[:report_dir_v2] + files = [] + uri = URI.parse(@request.url) + h = s.to_hash + h["options"] = s.options + h["_id"] = s.id + jid = BootstrapWorker.perform_async(dir, d.provider, h, @request.env['REMOTE_USER'], DevopsConfig.config) + Worker.set_status jid, Worker::STATUS::IN_QUEUE + logger.info "Job '#{jid}' has been started" + uri.path = "#{DevopsConfig[:url_prefix]}/v2.0/report/" + jid + uri.query = nil + uri.fragment = nil + files.push uri.to_s + sleep 1 + files end - def self.get_server_by_key id, key + def prepare_bootstrap_server body + id = body["instance_id"] + name = body["name"] + s = Devops::Db.connector.server_by_instance_id(id) + + p = Devops::Db.connector.check_project_auth s.project, s.deploy_env, @request.env['REMOTE_USER'] + d = p.deploy_env s.deploy_env + + provider = ::Provider::ProviderFactory.get(s.provider) + + check_chef_node_name(name, provider) unless name.nil? + s.options = { + :run_list => rl || d.run_list, + } + unless t.nil? + templates = get_templates + halt_response("Invalid bootstrap template '#{t}', available values: #{templates.join(", ")}", 400) unless templates.include?(t) + s.options[:bootstrap_template] = t + end + s.chef_node_name = name || provider.create_default_chef_node_name(s) + s + end + + def add_server body + project = body["project"] + deploy_env = body["deploy_env"] + p = Devops::Db.connector.check_project_auth project, deploy_env, @request.env['REMOTE_USER'] + + d = p.deploy_env(deploy_env) + + cert = Devops::Db.connector.key(body["key"]) + provider = ::Provider::ProviderFactory.get("static") + s = Devops::Model::Server.new + s.provider = provider.name + s.project = project + s.deploy_env = deploy_env + s.remote_user = body["remote_user"] + s.private_ip = body["private_ip"] + s.public_ip = body["public_ip"] + s.static = true + s.id = "static_#{cert.id}-#{Time.now.to_i}" + s.key = cert.id + Devops::Db.connector.server_insert s + "Server '#{s.id}' has been added" + end + + def get_server_by_key id, key mongo = Devops::Db.connector key == "instance" ? mongo.server_by_instance_id(id) : mongo.server_by_chef_node_name(id) end - def self.check_chef_node_name name, provider + 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") diff --git a/devops-service/app/api2/routes/image.rb b/devops-service/app/api2/routes/image.rb index 8b71857..3eb228c 100644 --- a/devops-service/app/api2/routes/image.rb +++ b/devops-service/app/api2/routes/image.rb @@ -1,12 +1,9 @@ module Devops - module Version2_0 + module API2_0 module Routes module ImageRoutes def self.registered(app) - app.after %r{\A/image(/[\w]+)?\z} do - statistic - end # Get devops images list # @@ -27,7 +24,12 @@ module Devops # "id": "36dc7618-4178-4e29-be43-286fbfe90f50" # } # ] - app.get_with_headers "/images", :headers => [:accept], &Devops::Version2_0::Handler::Image.get_images + app.get_with_headers "/images", :headers => [:accept] do + check_privileges("image", "r") + provider = params[:provider] + check_provider(provider) if provider + json Devops::API2_0::Handler::Image.new(request, params).images(provider).map(&:to_hash) + end # Get raw images for :provider # @@ -53,7 +55,11 @@ module Devops # "status": "ACTIVE" # } # ] - app.get_with_headers "/images/provider/:provider", :headers => [:accept], &Devops::Version2_0::Handler::Image.get_provider_images + app.get_with_headers "/images/provider/:provider", :headers => [:accept] do |provider| + check_privileges("image", "r") + check_provider(provider) + json Devops::API2_0::Handler::Image.new(request, params).provider_images(provider) + end # Create devops image # @@ -73,7 +79,12 @@ module Devops # # * *Returns* : # 201 - Created - app.post_with_headers "/image", :headers => [:accept, :content_type], &Devops::Version2_0::Handler::Image.create_image + app.post_with_headers "/image", :headers => [:accept, :content_type] do + check_privileges("image", "w") + image = create_object_from_json_body + Devops::API2_0::Handler::Image.new(request, params).create_image(image) + create_response "Created", nil, 201 + end hash = {} # Get devops image by id @@ -91,7 +102,10 @@ module Devops # "bootstrap_template": null, # "id": "36dc7618-4178-4e29-be43-286fbfe90f50" # } - hash["GET"] = Devops::Version2_0::Handler::Image.get_image + hash["GET"] = lambda { |image_id| + check_privileges("image", "r") + json Devops::API2_0::Handler::Image.new(request, params).image(image_id) + } # Update devops image # @@ -111,7 +125,12 @@ module Devops # # * *Returns* : # 200 - Updated - hash["PUT"] = Devops::Version2_0::Handler::Image.update_image + hash["PUT"] = lambda {|image_id| + check_privileges("image", "w") + image = create_object_from_json_body + Devops::API2_0::Handler::Image.new(request, params).update_image(image_id, image) + create_response("Image '#{image_id}' has been updated") + } # Delete devops image # @@ -122,7 +141,11 @@ module Devops # # * *Returns* : # 200 - Deleted - hash["DELETE"] = Devops::Version2_0::Handler::Image.delete_image + hash["DELETE"] = lambda {|image_id| + check_privileges("image", "w") + Devops::API2_0::Handler::Image.delete_image + create_response("Image '#{image_id}' has been removed") + } app.multi_routes "/image/:image_id", {}, hash diff --git a/devops-service/app/api2/routes/network.rb b/devops-service/app/api2/routes/network.rb index c449de0..13c13f4 100644 --- a/devops-service/app/api2/routes/network.rb +++ b/devops-service/app/api2/routes/network.rb @@ -1,6 +1,6 @@ # encoding: UTF-8 module Devops - module Version2_0 + module API2_0 module Routes module NetworkRoutes @@ -32,7 +32,11 @@ module Devops # "id": "b14f8df9-ac27-48e2-8d65-f7ef78dc2654" # } # ] - app.get_with_headers "/networks/:provider", :headers => [:accept], &Devops::Version2_0::Handler::Network.get_networks + app.get_with_headers "/networks/:provider", :headers => [:accept] do |provider| + check_privileges("network", "r") + check_provider(provider) + json Devops::API2_0::Handler::Network.new(request, params).networks + end puts "Network routes initialized" end diff --git a/devops-service/app/api2/routes/project.rb b/devops-service/app/api2/routes/project.rb index 7a2eb1c..bca4825 100644 --- a/devops-service/app/api2/routes/project.rb +++ b/devops-service/app/api2/routes/project.rb @@ -1,5 +1,5 @@ module Devops - module Version2_0 + module API2_0 module Routes module ProjectRoutes @@ -18,7 +18,10 @@ module Devops # [ # {"name" : "project_1"} # ] - app.get_with_headers "/projects", :headers => [:accept], &Devops::Version2_0::Handler::Project.get_projects + app.get_with_headers "/projects", :headers => [:accept] do + check_privileges("project", "r") + json Devops::API2_0::Handler::Project.new(request, params).projects.map(&:to_hash) + end # Get project by id # @@ -53,7 +56,10 @@ module Devops # "name": "project_1" # } hash = {} - hash["GET"] = Devops::Version2_0::Handler::Project.get_project + hash["GET"] = lambda {|project| + check_privileges("project", "r") + json Devops::API2_0::Handler::Project.new(request, params).project(project) + } # Update project and create chef roles # @@ -90,7 +96,13 @@ module Devops # # * *Returns* : # 200 - Updated - hash["PUT"] = Devops::Version2_0::Handler::Project.update_project + hash["PUT"] = lambda { |project| + check_privileges("project", "w") + body = create_object_from_json_body + r = Devops::API2_0::Handler::Project.new(request, params).update_project project, body + info = "Project '#{project.id}' has been updated." + r + create_response(info) + } # Delete project # @@ -106,7 +118,15 @@ module Devops # # * *Returns* : # 200 - Deleted - hash["DELETE"] = Devops::Version2_0::Handler::Project.delete_project + hash["DELETE"] = lambda {|project| + check_privileges("project", "w") + body = create_object_from_json_body(Hash, true) + deploy_env = unless body.nil? + check_string(body["deploy_env"], "Parameter 'deploy_env' should be a not empty string", true) + end + info = Devops::API2_0::Handler::Project.new(request, params).delete_project(project, deploy_env) + create_response(info) + } app.multi_routes "/project/:project", {}, hash # Get project servers @@ -135,7 +155,10 @@ module Devops # "id": "nstance id" # } # ] - app.get_with_headers "/project/:project/servers", :headers => [:accept], &Devops::Version2_0::Handler::Project.get_project_servers + app.get_with_headers "/project/:project/servers", :headers => [:accept] do |project| + check_privileges("project", "r") + json Devops::API2_0::Handler::Project.new(request, params).project_servers(project).map(&:to_hash) + end # Create project and chef roles # @@ -172,7 +195,15 @@ module Devops # # * *Returns* : # 201 - Created - app.post_with_headers "/project", :headers => [:accept, :content_type], &Devops::Version2_0::Handler::Project.create_project + app.post_with_headers "/project", :headers => [:accept, :content_type] do + check_privileges("project", "w") + body = create_object_from_json_body + check_string(body["name"], "Parameter 'name' must be a not empty string") + check_array(body["deploy_envs"], "Parameter 'deploy_envs' must be a not empty array of objects", Hash) + res = Devops::API2_0::Handler::Project.new(request, params).create_project body + res = "Created. " + res + create_response(res, nil, 201) + end users_hash = {} # Add users to project environment @@ -192,7 +223,14 @@ module Devops # # * *Returns* : # 200 - Updated - users_hash["PUT"] = Devops::Version2_0::Handler::Project.update_project_users + users_hash["PUT"] = lambda { |project| + check_privileges("project", "w") + body = create_object_from_json_body + users = check_array(body["users"], "Parameter 'users' must be a not empty array of strings") + deploy_env = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string", true) + info = Devops::API2_0::Handler::Project.new(request, params).update_project_users(project, deploy_env, users) + create_response(info) + } # Delete users from project environment # @@ -211,7 +249,14 @@ module Devops # # * *Returns* : # 200 - Updated - users_hash["DELETE"] = Devops::Version2_0::Handler::Project.delete_project_users + users_hash["DELETE"] = lambda {|project| + check_privileges("project", "w") + body = create_object_from_json_body + users = check_array(body["users"], "Parameter 'users' must be a not empty array of strings") + deploy_env = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string", true) + info = Devops::API2_0::Handler::Project.new(request, params).delete_project_users(project, deploy_env, users) + create_response(info) + } app.multi_routes "/project/:id/user", {}, users_hash # Set run_list to project environment @@ -229,7 +274,13 @@ module Devops # # * *Returns* : # 200 - Updated - app.put_with_headers "/project/:id/:env/run_list", :headers => [:accept, :content_type], &Devops::Version2_0::Handler::Project.set_project_env_run_list + app.put_with_headers "/project/:id/:env/run_list", :headers => [:accept, :content_type] do |project, deploy_env| + check_privileges("project", "w") + list = create_object_from_json_body(Array) + check_array(list, "Body must contains not empty array of strings") + info = Devops::API2_0::Handler::Project.new(request, params).set_project_env_run_list(project, deploy_env, list) + create_response(info) + end # Run chef-client on reserved project servers # @@ -246,7 +297,25 @@ module Devops # } # # * *Returns* : text stream - app.post_with_headers "/project/:id/deploy", :headers => [:content_type], &Devops::Version2_0::Handler::Project.deploy_project + app.post_with_headers "/project/:id/deploy", :headers => [:content_type] do |project| + check_privileges("project", "x") + obj = create_object_from_json_body + deploy_env = check_string(obj["deploy_env"], "Parameter 'deploy_env' should be a not empty string", true) + servers = check_array(obj["servers"], "Parameter 'servers' should be a not empty array of strings", String, true) + handler = Devops::API2_0::Handler::Project.new(request, params) + if obj.key?("trace") + stream() do |out| + begin + status = handler.deploy_project_stream out, project, deploy_env, servers + out << create_status(status) + rescue IOError => e + logger.error e.message + end + end + else + json handler.deploy_project project, deploy_env, servers + end + end # Set project to archivated state # @@ -254,7 +323,11 @@ module Devops # - method : POST # - headers : # - Content-Type: application/json - app.post_with_headers "/project/:project/archive", :headers => [:content_type], &Devops::Version2_0::Handler::Project.archive_project + app.post_with_headers "/project/:project/archive", :headers => [:content_type] do |project| + check_privileges("project", "w") + info = Devops::API2_0::Handler::Project.new(request, params).archive_project(project) + create_response(info) + end # Set project to normal state # @@ -262,7 +335,11 @@ module Devops # - method : POST # - headers : # - Content-Type: application/json - app.post_with_headers "/project/:project/unarchive", :headers => [:content_type], &Devops::Version2_0::Handler::Project.unarchive_project + app.post_with_headers "/project/:project/unarchive", :headers => [:content_type] do |project| + check_privileges("project", "w") + info = Devops::API2_0::Handler::Project.new(request, params).unarchive_project(project) + create_response(info) + end # Test project environment # @@ -330,7 +407,10 @@ module Devops # }, # "message": "Test project 'project_1' and environment 'prod'" # } - app.post_with_headers "/project/test/:id/:env", :headers => [:accept, :content_type], &Devops::Version2_0::Handler::Project.test_project + app.post_with_headers "/project/test/:id/:env", :headers => [:accept, :content_type] do |project, deploy_env| + check_privileges("project", "r") + json Devops::API2_0::Handler::Project.new(request, params).test_project(project, deploy_env) + end puts "Project routes initialized" end diff --git a/devops-service/app/api2/routes/provider.rb b/devops-service/app/api2/routes/provider.rb index d625ed2..400a6d4 100644 --- a/devops-service/app/api2/routes/provider.rb +++ b/devops-service/app/api2/routes/provider.rb @@ -1,6 +1,5 @@ # encoding: UTF-8 -require "json" require "providers/provider_factory" module Devops @@ -24,7 +23,7 @@ module Devops # ] app.get_with_headers "/providers", :headers => [:accept] do#, &Devops::Version2_0::Handler::Provider.get_providers check_privileges("provider", "r") - json Devops::API2_0::Handler::Provider.new.providers + json Devops::API2_0::Handler::Provider.new(request, params).providers end puts "Provider routes initialized" diff --git a/devops-service/app/api2/routes/server.rb b/devops-service/app/api2/routes/server.rb index ccb199f..b82f35a 100644 --- a/devops-service/app/api2/routes/server.rb +++ b/devops-service/app/api2/routes/server.rb @@ -32,7 +32,7 @@ module Devops end end reserved = (params.key?("reserved") ? true : nil) - json Devops::Version2_0::Handler::Server.new.servers(fields, reserved) + json Devops::API2_0::Handler::Server.new(request, params).servers(fields, reserved) end # Get chef nodes list @@ -50,7 +50,7 @@ module Devops # ] app.get_with_headers "/servers/chef", :headers => [:accept] do check_privileges("server", "r") - json Devops::Version2_0::Handler::Server.new.chef_servers + json Devops::API2_0::Handler::Server.new(request, params).chef_servers end # Get provider servers list @@ -91,7 +91,7 @@ module Devops # ] app.get_with_headers "/servers/:provider", :headers => [:accept] do check_privileges("server", "r") - json Devops::Version2_0::Handler::Server.provider_servers(params[:provider]) + json Devops::API2_0::Handler::Server.new(request, params).provider_servers(params[:provider]) end # Get server info by :name @@ -110,7 +110,10 @@ module Devops # } # ] hash = {} - hash["GET"] = Devops::Version2_0::Handler::Server.get_server + hash["GET"] = lambda {|id| + check_privileges("server", "r") + json Devops::API2_0::Handler::Server.new(request, params).server(id).to_hash + } # Delete devops server # @@ -126,7 +129,13 @@ module Devops # # * *Returns* : # 200 - Deleted - hash["DELETE"] = Devops::Version2_0::Handler::Server.delete_server + hash["DELETE"] = lambda {|id| + check_privileges("server", "w") + body = create_object_from_json_body(Hash, true) + key = (body.nil? ? nil : body["key"]) + info, r = Devops::API2_0::Handler::Server.new(request, params).delete(id, key) + create_response(info, r) + } app.multi_routes "/server/:id", {:headers => [:accept, :content_type]}, hash # Create devops server @@ -149,7 +158,32 @@ module Devops # } # # * *Returns* : text stream - app.post_with_headers "/server", :headers => [:content_type], &Devops::Version2_0::Handler::Server.create_server + app.post_with_headers "/server", :headers => [:content_type] do + check_privileges("server", "w") + body = create_object_from_json_body + project_name = check_string(body["project"], "Parameter 'project' must be a not empty string") + env_name = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string") + server_name = check_string(body["name"], "Parameter 'name' should be null or not empty string", true) + without_bootstrap = body["without_bootstrap"] + force = body["force"] + halt_response("Parameter 'without_bootstrap' should be a null or true") unless without_bootstrap.nil? or without_bootstrap == true + halt_response("Parameter 'force' should be a null or true") unless force.nil? or force == true + groups = check_array(body["groups"], "Parameter 'groups' should be null or not empty array of string", String, true) + key_name = check_string(body["key"], "Parameter 'key' should be null or not empty string", true) + handler = Devops::API2_0::Handler::Server.new(request, params) + if body.key?("trace") + stream() do |out| + begin + status = handler.create_server_stream out, body + out << create_status(status) + rescue IOError => e + logger.error e.message + end + end + else + json handler.create_server body + end + end # Pause devops server by name # @@ -165,7 +199,13 @@ module Devops # # * *Returns* : # 200 - Paused - app.post_with_headers "/server/:node_name/pause", :headers => [:accept, :content_type], &Devops::Version2_0::Handler::Server.pause_server + app.post_with_headers "/server/:node_name/pause", :headers => [:accept, :content_type] do |node_name| + check_privileges("server", "w") + body = create_object_from_json_body(Hash, true) + key = (body.nil? ? nil : body["key"]) + info = Devops::API2_0::Handler::Server.new(request, params).pause_server(node_name, key) + create_response(info) + end # Unpause devops server by name # @@ -181,7 +221,13 @@ module Devops # # * *Returns* : # 200 - Unpaused - app.post_with_headers "/server/:node_name/unpause", :headers => [:accept, :content_type], &Devops::Version2_0::Handler::Server.unpause_server + app.post_with_headers "/server/:node_name/unpause", :headers => [:accept, :content_type] do |node_name| + check_privileges("server", "w") + body = create_object_from_json_body(Hash, true) + key = (body.nil? ? nil : body["key"]) + info = Devops::API2_0::Handler::Server.new(request, params).unpause_server(node_name, key) + create_response(info) + end # Reserve devops server # @@ -197,7 +243,13 @@ module Devops # # * *Returns* : # 200 - Reserved - app.post_with_headers "/server/:node_name/reserve", :headers => [:accept, :content_type], &Devops::Version2_0::Handler::Server.reserve_server + app.post_with_headers "/server/:node_name/reserve", :headers => [:accept, :content_type] do |node_name| + check_privileges("server", "w") + body = create_object_from_json_body(Hash, true) + key = (body.nil? ? nil : body["key"]) + Devops::API2_0::Handler::Server.new(request, params).reserve_server(node_name, key) + create_response("Server '#{node_name}' has been reserved") + end # Unreserve devops server # @@ -213,7 +265,13 @@ module Devops # # * *Returns* : # 200 - Unreserved - app.post_with_headers "/server/:node_name/unreserve", :headers => [:accept, :content_type], &Devops::Version2_0::Handler::Server.unreserve_server + app.post_with_headers "/server/:node_name/unreserve", :headers => [:accept, :content_type] do |node_name| + check_privileges("server", "w") + body = create_object_from_json_body(Hash, true) + key = (body.nil? ? nil : body["key"]) + Devops::API2_0::Handler::Server.new(request, params).unreserve_server(node_name, key) + create_response("Server '#{node_name}' has been unreserved") + end # Bootstrap devops server # @@ -231,7 +289,32 @@ module Devops # } # # * *Returns* : text stream - app.post_with_headers "/server/bootstrap", :headers => [:accept, :content_type], &Devops::Version2_0::Handler::Server.bootstrap_server + app.post_with_headers "/server/bootstrap", :headers => [:accept, :content_type] do + check_privileges("server", "w") + body = create_object_from_json_body(Hash, true) + id = check_string(body["instance_id"], "Parameter 'instance_id' must be a not empty string") + name = check_string(body["name"], "Parameter 'name' should be a not empty string", true) + rl = check_array(body["run_list"], "Parameter 'run_list' should be a not empty array of string", String, true) + unless rl.nil? + validator = Validators::Helpers::RunList.new(rl) + halt_response(validator.message) unless validator.valid? + end + t = check_string(body["bootstrap_template"], "Parameter 'bootstrap_template' should be a not empty string", true) + + handler = Devops::API2_0::Handler::Server.new(request, params) + if body.key?("trace") + stream() do |out| + begin + status = handler.bootstrap_server_stream out, body + out << create_status(status) + rescue IOError => e + logger.error e.message + end + end + else + handler.bootstrap_server(body) + end + end # Add external server to devops # @@ -252,7 +335,19 @@ module Devops # # * *Returns* : # 200 - Added - app.post_with_headers "/server/add", :headers => [:accept, :content_type], &Devops::Version2_0::Handler::Server.add_server + app.post_with_headers "/server/add", :headers => [:accept, :content_type] do + check_privileges("server", "w") + body = create_object_from_json_body + project = check_string(body["project"], "Parameter 'project' must be a not empty string") + deploy_env = check_string(body["deploy_env"], "Parameter 'deploy_env' must be a not empty string") + key = check_string(body["key"], "Parameter 'key' must be a not empty string") + remote_user = check_string(body["remote_user"], "Parameter 'remote_user' must be a not empty string") + private_ip = check_string(body["private_ip"], "Parameter 'private_ip' must be a not empty string") + public_ip = check_string(body["public_ip"], "Parameter 'public_ip' should be a not empty string", true) + + info = Devops::API2_0::Handler::Server.new(request, params).add_server(body) + create_response(info) + end puts "Server routes initialized" end diff --git a/devops-service/app/api2/routes/v2.0.rb b/devops-service/app/api2/routes/v2.0.rb index 79b13cf..f39a344 100644 --- a/devops-service/app/api2/routes/v2.0.rb +++ b/devops-service/app/api2/routes/v2.0.rb @@ -8,6 +8,7 @@ require "auth/devops_auth" require "exceptions/invalid_record" require "exceptions/record_not_found" require "exceptions/dependency_error" +require "exceptions/conflict_exception" require 'core/devops-logger' require_relative "../helpers/version_2" @@ -72,6 +73,12 @@ module Devops halt_response(e.message, 400) end + error ConflictException do + e = env["sinatra.error"] + logger.warn e.message + halt_response(e.message, 409) + end + error InvalidPrivileges do e = env["sinatra.error"] logger.warn e.message diff --git a/devops-service/app/devops-api2.rb b/devops-service/app/devops-api2.rb index b309ceb..b8be63d 100644 --- a/devops-service/app/devops-api2.rb +++ b/devops-service/app/devops-api2.rb @@ -8,7 +8,7 @@ module Devops require_relative "api2/handlers/filter" require_relative "api2/handlers/group" require_relative "api2/handlers/user" -<<<<<<< HEAD + require_relative "api2/handlers/network" require_relative "api2/handlers/report" require_relative "api2/handlers/deploy" require_relative "api2/handlers/script" @@ -16,16 +16,12 @@ module Devops require_relative "api2/handlers/key" require_relative "api2/handlers/tag" require_relative "api2/handlers/server" + require_relative "api2/handlers/image" + require_relative "api2/handlers/project" require_relative "api2/handlers/stack" require_relative "api2/handlers/stack_template" require_relative "api2/handlers/stack_template_preset" -=begin - require "routes/v2.0/handlers/image" - require "routes/v2.0/handlers/network" - require "routes/v2.0/handlers/project" - require "routes/v2.0/handlers/status" -=end require 'lib/stubber' end diff --git a/devops-service/exceptions/conflict_exception.rb b/devops-service/exceptions/conflict_exception.rb new file mode 100644 index 0000000..a4e78c2 --- /dev/null +++ b/devops-service/exceptions/conflict_exception.rb @@ -0,0 +1,4 @@ +class ConflictException < Exception#StandardError + +end +