Merge branch 'devops_3' into devops_3_achuchkalov
This commit is contained in:
commit
beca955f60
14
devops-service/app/api2/handlers/bootstrap_templates.rb
Normal file
14
devops-service/app/api2/handlers/bootstrap_templates.rb
Normal file
@ -0,0 +1,14 @@
|
||||
require "commands/bootstrap_templates"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class BootstrapTemplates
|
||||
|
||||
include BootstrapTemplatesCommands
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
61
devops-service/app/api2/handlers/deploy.rb
Normal file
61
devops-service/app/api2/handlers/deploy.rb
Normal file
@ -0,0 +1,61 @@
|
||||
require "commands/deploy"
|
||||
require "commands/status"
|
||||
require "workers/deploy_worker"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Deploy
|
||||
extend DeployCommands
|
||||
extend StatusCommands
|
||||
|
||||
def initialize req, params
|
||||
@request = req
|
||||
@params = params
|
||||
end
|
||||
|
||||
def deploy names, tags
|
||||
dir = DevopsConfig.config[:report_dir_v2]
|
||||
files = []
|
||||
uri = URI.parse(@request.url)
|
||||
servers(names).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, tags, @request.env['REMOTE_USER'], DevopsConfig.config)
|
||||
files.push jid
|
||||
end
|
||||
files
|
||||
end
|
||||
|
||||
def deploy_stream out, names, tags
|
||||
status = []
|
||||
servers(names).each do |s|
|
||||
project = 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
|
||||
res = deploy_server_proc.call(out, s, tags)
|
||||
status.push(res)
|
||||
end
|
||||
out << create_status(status)
|
||||
rescue RecordNotFound => e
|
||||
out << e.message
|
||||
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
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
24
devops-service/app/api2/handlers/filter.rb
Normal file
24
devops-service/app/api2/handlers/filter.rb
Normal file
@ -0,0 +1,24 @@
|
||||
require_relative "request_handler"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Filter < RequestHandler
|
||||
|
||||
def available_images provider
|
||||
Devops::Db.connector.available_images(provider)
|
||||
end
|
||||
|
||||
def add_images images, provider
|
||||
Devops::Db.connector.add_available_images(images, provider)
|
||||
end
|
||||
|
||||
def delete_images images, provider
|
||||
Devops::Db.connector.delete_available_images(images, provider)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
22
devops-service/app/api2/handlers/flavor.rb
Normal file
22
devops-service/app/api2/handlers/flavor.rb
Normal file
@ -0,0 +1,22 @@
|
||||
require_relative "request_handler"
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Flavor < RequestHandler
|
||||
|
||||
def initialize request, params
|
||||
@provider = params[:provider]
|
||||
end
|
||||
|
||||
def flavors
|
||||
p = ::Provider::ProviderFactory.get @provider
|
||||
p.flavors
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
20
devops-service/app/api2/handlers/group.rb
Normal file
20
devops-service/app/api2/handlers/group.rb
Normal file
@ -0,0 +1,20 @@
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Group
|
||||
|
||||
def initialize provider
|
||||
@provider = provider
|
||||
end
|
||||
|
||||
def groups params
|
||||
p = ::Provider::ProviderFactory.get @provider
|
||||
p.groups(params)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
51
devops-service/app/api2/handlers/image.rb
Normal file
51
devops-service/app/api2/handlers/image.rb
Normal file
@ -0,0 +1,51 @@
|
||||
require "providers/provider_factory"
|
||||
require "commands/image"
|
||||
require_relative "request_handler"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Image < RequestHandler
|
||||
|
||||
extend ImageCommands
|
||||
|
||||
def images provider
|
||||
Devops::Db.connector.images(provider)
|
||||
end
|
||||
|
||||
def provider_images provider
|
||||
Image.get_available_provider_images(Devops::Db.connector, provider)
|
||||
end
|
||||
|
||||
def get_image id
|
||||
Devops::Db.connector.image(id)
|
||||
end
|
||||
|
||||
def create_image image
|
||||
Devops::Db.connector.image_insert Devops::Model::Image.new(image)
|
||||
end
|
||||
|
||||
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 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
|
||||
|
||||
Devops::Db.connector.image_delete id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
45
devops-service/app/api2/handlers/key.rb
Normal file
45
devops-service/app/api2/handlers/key.rb
Normal file
@ -0,0 +1,45 @@
|
||||
require "db/mongo/models/key"
|
||||
require "fileutils"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Key
|
||||
|
||||
def keys
|
||||
keys = Devops::DB.connector.keys.map {|i| i.to_hash}
|
||||
keys.each {|k| k.delete("path")} # We should not return path to the key
|
||||
end
|
||||
|
||||
def create body, file_name
|
||||
File.open(file_name, "w") do |f|
|
||||
f.write(body["content"])
|
||||
f.chmod(0400)
|
||||
end
|
||||
|
||||
key = Devops::Model::Key.new({"path" => file_name, "id" => body["key_name"]})
|
||||
Devops::DB.connector.key_insert key
|
||||
end
|
||||
|
||||
def delete key_id
|
||||
mongo = Devops::DB.connector
|
||||
servers = mongo.servers_by_key key_id
|
||||
unless servers.empty?
|
||||
s_str = servers.map{|s| s.id}.join(", ")
|
||||
raise DependencyError.new "Deleting is forbidden: Key is used in servers: #{s_str}"
|
||||
end
|
||||
|
||||
k = mongo.key key_id
|
||||
begin
|
||||
FileUtils.rm(k.path)
|
||||
rescue
|
||||
logger.error "Missing key file for #{key_id} - #{k.filename}"
|
||||
end
|
||||
mongo.key_delete key_id
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
17
devops-service/app/api2/handlers/network.rb
Normal file
17
devops-service/app/api2/handlers/network.rb
Normal file
@ -0,0 +1,17 @@
|
||||
require "providers/provider_factory"
|
||||
require_relative "request_handler"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Network < RequestHandler
|
||||
|
||||
def networks provider
|
||||
p = ::Provider::ProviderFactory.get provider
|
||||
p.networks_detail
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
231
devops-service/app/api2/handlers/project.rb
Normal file
231
devops-service/app/api2/handlers/project.rb
Normal file
@ -0,0 +1,231 @@
|
||||
require "commands/deploy"
|
||||
require "commands/status"
|
||||
require "commands/server"
|
||||
require "db/mongo/models/project"
|
||||
require "workers/project_test_worker"
|
||||
require_relative "request_handler"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Project < RequestHandler
|
||||
|
||||
extend DeployCommands
|
||||
extend StatusCommands
|
||||
extend ServerCommands
|
||||
|
||||
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
|
||||
end
|
||||
archived = @params.include?("archived")
|
||||
Devops::Db.connector.projects(nil, nil, fields, archived)
|
||||
end
|
||||
|
||||
def project id
|
||||
Devops::Db.connector.project(id)
|
||||
end
|
||||
|
||||
def project_servers id
|
||||
Devops::Db.connector.project(id)
|
||||
Devops::Db.connector.servers(id, @params[:deploy_env])
|
||||
end
|
||||
|
||||
# TODO: multi project
|
||||
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 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 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 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 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 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 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 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 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 archive_project id
|
||||
project = Devops::Db.connector.project(id)
|
||||
Devops::Db.connector.archive_project(id)
|
||||
"Project '#{id}' has been archived"
|
||||
end
|
||||
|
||||
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 => []}
|
||||
envs.each do |e|
|
||||
role_name = KnifeCommands.role_name(project_id, e.identifier)
|
||||
begin
|
||||
if all_roles.include? role_name
|
||||
roles[:exist].push role_name
|
||||
else
|
||||
KnifeCommands.create_role role_name, project_id, e.identifier
|
||||
roles[:new].push role_name
|
||||
logger.info "Role '#{role_name}' created"
|
||||
end
|
||||
rescue => er
|
||||
roles[:error].push role_name
|
||||
logger.error "Role '#{role_name}' can not be created: #{er.message}"
|
||||
end
|
||||
end
|
||||
roles
|
||||
end
|
||||
|
||||
def create_new_roles old_project, new_project, logger
|
||||
old_project.deploy_envs.each do |e|
|
||||
new_project.remove_env(e.identifier)
|
||||
end
|
||||
create_roles new_project.id, new_project.deploy_envs, logger
|
||||
end
|
||||
|
||||
def create_roles_response roles
|
||||
if roles.is_a?(String)
|
||||
roles
|
||||
else
|
||||
info = ""
|
||||
info += " Project roles '#{roles[:new].join("', '")}' have been automaticaly created" unless roles[:new].empty?
|
||||
info += " Project roles '#{roles[:exist].join("', '")}' weren't created because they exist" unless roles[:exist].empty?
|
||||
info += " Project roles '#{roles[:error].join("', '")}' weren't created because of internal error" unless roles[:error].empty?
|
||||
info
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
16
devops-service/app/api2/handlers/provider.rb
Normal file
16
devops-service/app/api2/handlers/provider.rb
Normal file
@ -0,0 +1,16 @@
|
||||
require "providers/provider_factory"
|
||||
require_relative "request_handler"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Provider < RequestHandler
|
||||
|
||||
def providers
|
||||
::Provider::ProviderFactory.providers
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
64
devops-service/app/api2/handlers/report.rb
Normal file
64
devops-service/app/api2/handlers/report.rb
Normal file
@ -0,0 +1,64 @@
|
||||
require_relative "request_handler"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Report < RequestHandler
|
||||
|
||||
def initialize request, params
|
||||
@params = params
|
||||
end
|
||||
|
||||
def options
|
||||
options = {}
|
||||
["project", "deploy_env", "type", "created_by", "date_from", "date_to", "sort", "status", "chef_node_name", "max_number"].each do |k|
|
||||
options[k] = @params[k] unless @params[k].nil?
|
||||
end
|
||||
attributes_keys = @params.keys.select{|k| k =~ /attributes\.*/}
|
||||
attributes_keys.each do |ak|
|
||||
options[ak] = @params[ak]
|
||||
end
|
||||
options
|
||||
end
|
||||
|
||||
def all
|
||||
Devops::Db.connector.reports(options)
|
||||
end
|
||||
|
||||
def all_latest
|
||||
Devops::Db.connector.latest_reports(options())
|
||||
end
|
||||
|
||||
def attributes name
|
||||
Devops::Db.connector.reports_attributes_values(name)
|
||||
end
|
||||
|
||||
def report id
|
||||
r = Devops::Db.connector.report(id)
|
||||
file = r.file
|
||||
raise RecordNotFound.new("Report '#{id}' does not exist") unless File.exists? file
|
||||
return Rack::Utils.escape_html(File.read(file)), completed?(id)
|
||||
rescue RecordNotFound => e
|
||||
if status(id) == Worker::STATUS::IN_QUEUE
|
||||
return "Task '#{id}' has been queued", false
|
||||
else
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
def status id
|
||||
Sidekiq.redis do |connection|
|
||||
connection.hget("devops", id)
|
||||
end
|
||||
end
|
||||
|
||||
def completed? id
|
||||
r = self.status(id)
|
||||
r == "completed" or r == "failed"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
12
devops-service/app/api2/handlers/request_handler.rb
Normal file
12
devops-service/app/api2/handlers/request_handler.rb
Normal file
@ -0,0 +1,12 @@
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class RequestHandler
|
||||
def initialize request, params
|
||||
@request = request
|
||||
@params = params
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
98
devops-service/app/api2/handlers/script.rb
Normal file
98
devops-service/app/api2/handlers/script.rb
Normal file
@ -0,0 +1,98 @@
|
||||
require "providers/provider_factory"
|
||||
require "fileutils"
|
||||
require "commands/status"
|
||||
require_relative "request_handler"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Script < RequestHandler
|
||||
|
||||
def scripts
|
||||
res = []
|
||||
Dir.foreach(DevopsConfig.config[:scripts_dir]) {|f| res.push(f) unless f.start_with?(".")}
|
||||
end
|
||||
|
||||
def execute_command out, cmd, node_name
|
||||
user = @request.env['REMOTE_USER']
|
||||
s = ::Devops::Db.connector.server_by_chef_node_name node_name
|
||||
::Devops::Db.connector.check_project_auth s.project, s.deploy_env, user
|
||||
cert = ::Devops::Db.connector.key s.key
|
||||
addr = "#{s.remote_user}@#{s.public_ip || s.private_ip}"
|
||||
ssh_cmd = "ssh -i %s #{addr} '#{cmd}'"
|
||||
out << ssh_cmd % File.basename(cert.path)
|
||||
out << "\n"
|
||||
IO.popen((ssh_cmd % cert.path) + " 2>&1") do |so|
|
||||
while line = so.gets do
|
||||
out << line
|
||||
end
|
||||
end
|
||||
out << "\nDone"
|
||||
end
|
||||
|
||||
def run_script out, file_name, nodes, script_params
|
||||
file = File.join(DevopsConfig.config[:scripts_dir], file_name)
|
||||
unless File.exists?(file)
|
||||
out << "File '#{file_name}' does not exist\n"
|
||||
return
|
||||
end
|
||||
servers = ::Devops::Db.connector.servers_by_names(nodes)
|
||||
if servers.empty?
|
||||
out << "No servers found for names '#{nodes.join("', '")}'\n"
|
||||
return
|
||||
end
|
||||
user = @request.env['REMOTE_USER']
|
||||
servers.each do |s|
|
||||
::Devops::Db.connector.check_project_auth s.project, s.deploy_env, user
|
||||
end
|
||||
status = []
|
||||
servers.each do |s|
|
||||
cert = begin
|
||||
::Devops::Db.connector.key s.key
|
||||
rescue
|
||||
out << "No key found for '#{s.chef_node_name}'"
|
||||
status.push 2
|
||||
next
|
||||
end
|
||||
ssh_cmd = "ssh -i #{cert.path} #{s.remote_user}@#{s.public_ip || s.private_ip} 'bash -s' < %s"
|
||||
out << "\nRun script on '#{s.chef_node_name}'\n"
|
||||
unless script_params.nil?
|
||||
ssh_cmd += " " + script_params.join(" ")
|
||||
end
|
||||
out << (ssh_cmd % [file_name])
|
||||
out << "\n"
|
||||
|
||||
begin
|
||||
IO.popen( (ssh_cmd % [file]) + " 2>&1") do |so|
|
||||
while line = so.gets do
|
||||
out << line
|
||||
end
|
||||
so.close
|
||||
status.push $?.to_i
|
||||
end
|
||||
rescue IOError => e
|
||||
logger.error e.message
|
||||
out << e.message
|
||||
status.push 3
|
||||
end
|
||||
end
|
||||
out << create_status(status)
|
||||
end
|
||||
|
||||
def create_script file_name
|
||||
file = File.join(settings.scripts_dir, file_name)
|
||||
raise RecordNotFound.new("File '#{file_name}' already exist") if File.exists?(file)
|
||||
File.open(file, "w") {|f| f.write(@request.body.read)}
|
||||
end
|
||||
|
||||
def delete_script file_name
|
||||
file = File.join(settings.scripts_dir, file_nsme)
|
||||
raise RecordNotFound.new("File '#{file_name}' does not exist", 404) unless File.exists?(file)
|
||||
FileUtils.rm(file)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
269
devops-service/app/api2/handlers/server.rb
Normal file
269
devops-service/app/api2/handlers/server.rb
Normal file
@ -0,0 +1,269 @@
|
||||
require 'rufus-scheduler'
|
||||
require "uri"
|
||||
|
||||
require "commands/status"
|
||||
require "commands/server"
|
||||
require "commands/bootstrap_templates"
|
||||
require "commands/knife_commands"
|
||||
|
||||
require "providers/provider_factory"
|
||||
|
||||
require "db/mongo/models/server"
|
||||
|
||||
require "workers/create_server_worker"
|
||||
require "workers/bootstrap_worker"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Server
|
||||
|
||||
extend StatusCommands
|
||||
extend ServerCommands
|
||||
extend BootstrapTemplatesCommands
|
||||
|
||||
scheduler = Rufus::Scheduler.new
|
||||
|
||||
def servers fields, reserved
|
||||
Devops::DB.connector.servers(nil, nil, nil, reserved, fields).map {|s| s.to_hash}
|
||||
end
|
||||
|
||||
def chef_servers
|
||||
KnifeCommands.chef_node_list
|
||||
end
|
||||
|
||||
def provider_servers provider
|
||||
::Provider::ProviderFactory.get(provider).servers
|
||||
end
|
||||
|
||||
def server id
|
||||
get_server_by_key(id, @params[:key])
|
||||
end
|
||||
|
||||
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 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 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 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 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 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 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 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 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 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")
|
||||
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 = KnifeCommands.chef_node_list.detect {|n| n == name}
|
||||
halt(400, "Chef node with name '#{name}' already exist") unless s.nil?
|
||||
s = KnifeCommands.chef_client_list.detect {|c| c == name}
|
||||
halt(400, "Chef client with name '#{name}' already exist") unless s.nil?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class ExpireHandler
|
||||
include ServerCommands
|
||||
|
||||
def initialize server, logger
|
||||
@server = server
|
||||
@logger = logger
|
||||
end
|
||||
|
||||
def call(job)
|
||||
@logger.info("Removing node '#{@server.chef_node_name}' form project '#{@server.project}' and env '#{@server.deploy_env}'")
|
||||
begin
|
||||
delete_server(@server, Devops::Db.connector, @logger)
|
||||
rescue => e
|
||||
logger.error "ExpiredHandler error: " + e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
51
devops-service/app/api2/handlers/stack.rb
Normal file
51
devops-service/app/api2/handlers/stack.rb
Normal file
@ -0,0 +1,51 @@
|
||||
require 'db/mongo/models/stack/stack_factory'
|
||||
require_relative "request_handler"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Stack < RequestHandler
|
||||
|
||||
def stacks
|
||||
Devops::Db.connector.stacks
|
||||
end
|
||||
|
||||
def stacks_for_provider provider
|
||||
Devops::Db.connector.stacks(provider)
|
||||
end
|
||||
|
||||
def create_stack object
|
||||
stack_model = Model::StackFactory.create(object['provider'], object)
|
||||
Devops::Db.connector.stack_insert(stack_model)
|
||||
stack_model
|
||||
end
|
||||
|
||||
def stack id
|
||||
Devops::Db.connector.stack(id)
|
||||
end
|
||||
|
||||
def delete_stack id
|
||||
stack = self.stack(id)
|
||||
stack.delete_stack_in_cloud!
|
||||
Devops::Db.connector.stack_delete(id)
|
||||
end
|
||||
|
||||
def sync_details id
|
||||
stack = self.stack(id)
|
||||
stack.sync_details!
|
||||
Devops::Db.connector.stack_update(stack)
|
||||
end
|
||||
|
||||
def resources id
|
||||
stack = Devops::Db.connector.stack(id)
|
||||
stack.resources
|
||||
end
|
||||
|
||||
def resources id, resource_id
|
||||
stack = Devops::Db.connector.stack(id)
|
||||
stack.resource(resource_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
28
devops-service/app/api2/handlers/stack_preset.rb
Normal file
28
devops-service/app/api2/handlers/stack_preset.rb
Normal file
@ -0,0 +1,28 @@
|
||||
require 'json'
|
||||
require 'lib/stack_presets/factory'
|
||||
require_relative "request_handler"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class StackPreset < RequestHandler
|
||||
|
||||
def presets
|
||||
Devops::StackPresetsFactory.list
|
||||
end
|
||||
|
||||
def preset id
|
||||
Devops::StackPresetsFactory.get(id)
|
||||
end
|
||||
|
||||
def apply id, body
|
||||
preset = Devops::StackPresetsFactory.get(id)
|
||||
preset.create_stack_from_preset(body)
|
||||
Devops::Db.connector.stack_insert(stack)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
34
devops-service/app/api2/handlers/stack_template.rb
Normal file
34
devops-service/app/api2/handlers/stack_template.rb
Normal file
@ -0,0 +1,34 @@
|
||||
require 'db/mongo/models/stack_template/stack_template_factory'
|
||||
require_relative "request_handler"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class StackTemplate < RequestHandler
|
||||
|
||||
def stack_templates
|
||||
Devops::Db.connector.stack_templates
|
||||
end
|
||||
|
||||
def stack_templates_for_provider provider
|
||||
Devops::Db.connector.stack_templates(provider)
|
||||
end
|
||||
|
||||
def create_stack_template body
|
||||
template_model = Model::StackTemplateFactory.create(body['provider'], body)
|
||||
Devops::Db.connector.stack_template_insert(template_model)
|
||||
template_model
|
||||
end
|
||||
|
||||
def get_stack_template id
|
||||
Devops::Db.connector.stack_template(id)
|
||||
end
|
||||
|
||||
def delete_stack_template id
|
||||
Devops::Db.connector.stack_template_delete id
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
34
devops-service/app/api2/handlers/tag.rb
Normal file
34
devops-service/app/api2/handlers/tag.rb
Normal file
@ -0,0 +1,34 @@
|
||||
require "commands/knife_commands"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class Tag
|
||||
|
||||
def initialize node_name
|
||||
@node_name = node_name
|
||||
@server = Devops::DB.connector.server_by_chef_node_name(@node_name)
|
||||
#TODO: raise
|
||||
halt_response("No servers found for name '#{@node_name}'", 404) if @server.nil?
|
||||
end
|
||||
|
||||
def tags
|
||||
KnifeCommands.tags_list(@node_name)
|
||||
end
|
||||
|
||||
def set_tags tags
|
||||
tagsStr = tags.join(" ")
|
||||
cmd = KnifeCommands.tags_create(@node_name, tagsStr)
|
||||
halt_response("Error: Cannot add tags #{tagsStr} to server #{@node_name}", 500) unless cmd[1]
|
||||
end
|
||||
|
||||
def self.unset_tags
|
||||
tagsStr = tags.join(" ")
|
||||
cmd = KnifeCommands.tags_delete(@node_name, tagsStr)
|
||||
halt_response("Cannot delete tags #{tagsStr} from server #{@node_name}: #{cmd[0]}", 500) unless cmd[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
47
devops-service/app/api2/handlers/user.rb
Normal file
47
devops-service/app/api2/handlers/user.rb
Normal file
@ -0,0 +1,47 @@
|
||||
require "db/mongo/models/user"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Handler
|
||||
class User
|
||||
|
||||
def users
|
||||
Devops::Db.connector.users
|
||||
end
|
||||
|
||||
def create body
|
||||
Devops::Db.connector.user_insert Devops::Model::User.new(body)
|
||||
end
|
||||
|
||||
def delete user_id
|
||||
Devops::Db.connector.user_delete user_id
|
||||
end
|
||||
|
||||
def change_user_privileges user_id, cmd, privileges
|
||||
change_user(user_id) do
|
||||
user.grant(cmd, privileges)
|
||||
end
|
||||
end
|
||||
|
||||
def change_email user_id, val
|
||||
change_user(user_id) do
|
||||
user.email = val
|
||||
end
|
||||
end
|
||||
|
||||
def change_password user_id, val
|
||||
change_user(user_id) do
|
||||
user.password = val
|
||||
end
|
||||
end
|
||||
|
||||
def change_user user_id
|
||||
user = Devops::Db.connector.user user_id
|
||||
yield(user)
|
||||
Devops::Db.connector.user_update user
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -5,7 +5,7 @@ require "sinatra/json"
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module API2_0
|
||||
module Helpers
|
||||
|
||||
def create_response msg, obj=nil, rstatus=200
|
||||
@ -23,11 +23,10 @@ module Devops
|
||||
|
||||
def check_privileges cmd, p
|
||||
# somewhy REMOTE_USER is missing
|
||||
user = request.env['HTTP_REMOTE_USER'] || request.env['REMOTE_USER']
|
||||
settings.mongo.check_user_privileges(user, cmd, p)
|
||||
user = request.env['USER']
|
||||
user.check_privileges(cmd, p)
|
||||
end
|
||||
|
||||
|
||||
def check_provider provider
|
||||
list = ::Provider::ProviderFactory.providers
|
||||
halt_response("Invalid provider '#{provider}', available providers: '#{list.join("', '")}'", 404) unless list.include?(provider)
|
||||
@ -1,5 +1,5 @@
|
||||
module Devops
|
||||
module Version2_0
|
||||
module API2_0
|
||||
module Routes
|
||||
module BootstrapTemplatesRoutes
|
||||
|
||||
@ -18,7 +18,10 @@ module Devops
|
||||
# [
|
||||
# "omnibus"
|
||||
# ]
|
||||
app.get_with_headers "/templates", :headers => [:accept], &Devops::Version2_0::Handler::BootstrapTemplates.get_bootstrap_templates
|
||||
app.get_with_headers "/templates", :headers => [:accept] do
|
||||
check_privileges("templates", "r")
|
||||
json Devops::API2_0::Handler::BootstrapTemplates.new.get_templates
|
||||
end
|
||||
|
||||
puts "Bootstrap templates routes initialized"
|
||||
end
|
||||
60
devops-service/app/api2/routes/deploy.rb
Normal file
60
devops-service/app/api2/routes/deploy.rb
Normal file
@ -0,0 +1,60 @@
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Routes
|
||||
module DeployRoutes
|
||||
|
||||
def self.registered(app)
|
||||
|
||||
# Run chef-client 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
|
||||
# "trace": true -> return output in stream
|
||||
# }
|
||||
#
|
||||
# * *Returns* : text stream
|
||||
app.post_with_headers "/deploy", :headers => [:content_type] do
|
||||
check_privileges("server", "x")
|
||||
# TODO: send message
|
||||
#broadcast(:devops_deploy, "deploy")
|
||||
r = create_object_from_json_body
|
||||
names = check_array(r["names"], "Parameter 'names' should be a not empty array of strings")
|
||||
tags = check_array(r["tags"], "Parameter 'tags' should be an array of strings", String, true) || []
|
||||
|
||||
if r.key?("trace")
|
||||
stream() do |out|
|
||||
status = []
|
||||
begin
|
||||
Devops::API2_0::Handler::Deploy.new(request, params).deploy_stream(out, names, tags)
|
||||
rescue IOError => e
|
||||
logger.error e.message
|
||||
break
|
||||
end
|
||||
end # stream
|
||||
else
|
||||
ids = Devops::API2_0::Handler::Deploy.new(request, params).deploy(names, tags)
|
||||
sleep 1
|
||||
ids.each do |jid|
|
||||
logger.info "Job '#{jid}' has been queued"
|
||||
uri.path = "#{DevopsConfig.config[:url_prefix]}/v2.0/report/" + jid
|
||||
files.push uri.to_s
|
||||
end
|
||||
json files
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
puts "Deploy routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,20 +1,10 @@
|
||||
module Devops
|
||||
module Version2_0
|
||||
module API2_0
|
||||
module Routes
|
||||
module FilterRoutes
|
||||
|
||||
def self.registered(app)
|
||||
|
||||
app.before "/filter/:provider/image" do
|
||||
protect!
|
||||
check_headers :accept, :content_type
|
||||
check_privileges("filter", "w")
|
||||
check_provider(params[:provider])
|
||||
@images = create_object_from_json_body(Array)
|
||||
halt_response("Request body should not be an empty array") if @images.empty?
|
||||
check_array(@images, "Request body should contains an array with strings")
|
||||
end
|
||||
|
||||
# Get list of images filters for :provider
|
||||
#
|
||||
# Devops can works with images from filters list only
|
||||
@ -33,7 +23,11 @@ module Devops
|
||||
# [
|
||||
# "36dc7618-4178-4e29-be43-286fbfe90f50"
|
||||
# ]
|
||||
app.get_with_headers "/filter/:provider/images", :headers => [:accept], &Devops::Version2_0::Handler::Filter.get_filters
|
||||
app.get_with_headers "/filter/:provider/images", :headers => [:accept] do |provider|
|
||||
check_privileges("filter", "r")
|
||||
check_provider(provider)
|
||||
json Devops::API2_0::Handler::Filter.new(request, params).available_images(provider)
|
||||
end
|
||||
|
||||
hash = {}
|
||||
|
||||
@ -50,7 +44,14 @@ module Devops
|
||||
# ] -> array of image ids to add to filter
|
||||
#
|
||||
# * *Returns* : list of images filters for :provider
|
||||
hash["PUT"] = Devops::Version2_0::Handler::Filter.add_filter
|
||||
hash["PUT"] = lambda { |provider|
|
||||
check_privileges("filter", "w")
|
||||
check_provider(provider)
|
||||
images = create_object_from_json_body(Array)
|
||||
halt_response("Request body should not be an empty array") if images.empty?
|
||||
check_array(images, "Request body should contains an array with strings")
|
||||
create_response("Updated", {:images => Devops::API2_0::Handler::Filter.new(request, params).add_images(images, provider)})
|
||||
}
|
||||
|
||||
# Delete image ids from filter for :provider
|
||||
#
|
||||
@ -65,7 +66,14 @@ module Devops
|
||||
# ] -> array of image ids to delete from filter
|
||||
#
|
||||
# * *Returns* : list of images filters for :provider
|
||||
hash["DELETE"] = Devops::Version2_0::Handler::Filter.delete_filter
|
||||
hash["DELETE"] = lambda { |provider|
|
||||
check_privileges("filter", "w")
|
||||
check_provider(provider)
|
||||
images = create_object_from_json_body(Array)
|
||||
halt_response("Request body should not be an empty array") if images.empty?
|
||||
check_array(images, "Request body should contains an array with strings")
|
||||
create_response("Deleted", {:images => Devops::API2_0::Handler::Filter.new(request, params).delete_images(images, provider)})
|
||||
}
|
||||
|
||||
app.multi_routes "/filter/:provider/image", {:headers => [:accept, :content_type]}, hash
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
module Devops
|
||||
module Version2_0
|
||||
module API2_0
|
||||
module Routes
|
||||
module FlavorRoutes
|
||||
|
||||
@ -31,7 +31,12 @@ module Devops
|
||||
# "disk": 20
|
||||
# }
|
||||
# ]
|
||||
app.get_with_headers "/flavors/:provider", :headers => [:accept], &Devops::Version2_0::Handler::Flavor.get_flavors
|
||||
app.get_with_headers "/flavors/:provider", :headers => [:accept] do
|
||||
check_privileges("flavor", "r")
|
||||
provider = params[:provider]
|
||||
check_provider(provider)
|
||||
json Devops::API2_0::Handler::Flavor.new(request, params).flavors
|
||||
end
|
||||
|
||||
puts "Flavor routes initialized"
|
||||
end
|
||||
@ -1,6 +1,6 @@
|
||||
# encoding: UTF-8
|
||||
module Devops
|
||||
module Version2_0
|
||||
module API2_0
|
||||
module Routes
|
||||
module GroupRoutes
|
||||
|
||||
@ -44,7 +44,12 @@ module Devops
|
||||
# }
|
||||
# }
|
||||
# TODO: vpc support for ec2
|
||||
app.get_with_headers "/groups/:provider", :headers => [:accept], &Devops::Version2_0::Handler::Group.get_groups
|
||||
app.get_with_headers "/groups/:provider", :headers => [:accept] do#, &Devops::Version2_0::Handler::Group.get_groups
|
||||
check_privileges("group", "r")
|
||||
provider = params[:provider]
|
||||
check_provider(provider)
|
||||
json Devops::API2_0::Handler::Group.new(provider).groups(params)
|
||||
end
|
||||
|
||||
puts "Group routes initialized"
|
||||
end
|
||||
@ -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
|
||||
|
||||
93
devops-service/app/api2/routes/key.rb
Normal file
93
devops-service/app/api2/routes/key.rb
Normal file
@ -0,0 +1,93 @@
|
||||
require "json"
|
||||
|
||||
module Devops
|
||||
module API2_0
|
||||
module Routes
|
||||
module KeyRoutes
|
||||
|
||||
def self.registered(app)
|
||||
# Get list of available ssh keys
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* : array of strings
|
||||
# [
|
||||
# {
|
||||
# "scope": "system", -> 'system' - key was added by server, 'user' - key was added by user
|
||||
# "id": "devops"
|
||||
# }
|
||||
# ]
|
||||
app.get_with_headers "/keys", :headers => [:accept] do
|
||||
check_privileges("key", "r")
|
||||
json Devops::API2_0::Handler::Key.new.keys
|
||||
end
|
||||
|
||||
# Create ssh key on devops server
|
||||
#
|
||||
# * *Request*
|
||||
# - method : POST
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# {
|
||||
# "file_name": "key file name",
|
||||
# "key_name": "key name",
|
||||
# "content": "key content"
|
||||
# }
|
||||
#
|
||||
# * *Returns* :
|
||||
# 201 - Created
|
||||
app.post_with_headers "/key", :headers => [:accept, :content_type] do
|
||||
check_privileges("key", "w")
|
||||
key = create_object_from_json_body
|
||||
fname = check_filename(key["file_name"], "Parameter 'file_name' must be a not empty string")
|
||||
kname = check_string(key["key_name"], "Parameter 'key_name' should be a not empty string")
|
||||
content = check_string(key["content"], "Parameter 'content' should be a not empty string")
|
||||
file_name = File.join(settings.keys_dir, fname)
|
||||
halt(400, "File '#{fname}' already exist") if File.exists?(file_name)
|
||||
Devops::API2_0::Handler::Key.new.create(key, file_name)
|
||||
create_response("Created", nil, 201)
|
||||
end
|
||||
|
||||
# Delete ssh key from devops server
|
||||
#
|
||||
# * *Request*
|
||||
# - method : DELETE
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Deleted
|
||||
app.delete_with_headers "/key/:key", :headers => [:accept] do
|
||||
check_privileges("key", "w")
|
||||
servers = settings.mongo.servers_by_key params[:key]
|
||||
unless servers.empty?
|
||||
s_str = servers.map{|s| s.id}.join(", ")
|
||||
raise DependencyError.new "Deleting is forbidden: Key is used in servers: #{s_str}"
|
||||
end
|
||||
|
||||
k = settings.mongo.key params[:key]
|
||||
begin
|
||||
FileUtils.rm(k.path)
|
||||
rescue
|
||||
logger.error "Missing key file for #{params[:key]} - #{k.filename}"
|
||||
end
|
||||
r = settings.mongo.key_delete params[:key]
|
||||
|
||||
r = Devops::API2_0::Handler::Key.new.delete params[:key]
|
||||
return [500, r["err"].inspect] unless r["err"].nil?
|
||||
create_response("Key '#{params[:key]}' removed")
|
||||
|
||||
end
|
||||
|
||||
puts "Key routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
# Get project stacks
|
||||
#
|
||||
@ -199,7 +222,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
|
||||
@ -219,7 +250,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
|
||||
#
|
||||
@ -238,7 +276,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
|
||||
@ -256,7 +301,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
|
||||
#
|
||||
@ -273,7 +324,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
|
||||
#
|
||||
@ -281,7 +350,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
|
||||
#
|
||||
@ -289,7 +362,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
|
||||
#
|
||||
@ -357,7 +434,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
|
||||
@ -1,10 +1,9 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require "json"
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module API2_0
|
||||
module Routes
|
||||
module ProviderRoutes
|
||||
|
||||
@ -22,7 +21,10 @@ module Devops
|
||||
# "ec2",
|
||||
# "openstack"
|
||||
# ]
|
||||
app.get_with_headers "/providers", :headers => [:accept], &Devops::Version2_0::Handler::Provider.get_providers
|
||||
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(request, params).providers
|
||||
end
|
||||
|
||||
puts "Provider routes initialized"
|
||||
end
|
||||
61
devops-service/app/api2/routes/report.rb
Normal file
61
devops-service/app/api2/routes/report.rb
Normal file
@ -0,0 +1,61 @@
|
||||
module Devops
|
||||
module API2_0
|
||||
module Routes
|
||||
module ReportRoutes
|
||||
|
||||
def self.registered(app)
|
||||
|
||||
app.get_with_headers "/report/all", headers: [:accept] do
|
||||
json Devops::API2_0::Handler::Report.new(request, params).all.map{|r| r.to_hash}
|
||||
end
|
||||
|
||||
app.get_with_headers "/report/all/latest", headers: [:accept] do
|
||||
json Devops::API2_0::Handler::Report.new(request, params).all_latest.map{|r| r.to_hash}
|
||||
end
|
||||
|
||||
app.get_with_headers "/report/all/attributes/:name", headers: [:accept] do |name|
|
||||
json Devops::API2_0::Handler::Report.new(request, params).attributes(name)
|
||||
end
|
||||
|
||||
app.get_with_headers "/report/:id", headers: [:accept] do |id|
|
||||
@text, @done = Devops::API2_0::Handler::Report.new(request, params).report(id)
|
||||
erb :index
|
||||
end
|
||||
|
||||
app.get "/status/:id" do
|
||||
r = Devops::API2_0::Handler::Report.new(request, params).status(params[:id])
|
||||
return [404, "Job with id '#{params[:id]}' not found"] if r.nil?
|
||||
r
|
||||
end
|
||||
|
||||
puts "Report routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
__END__
|
||||
|
||||
@@ layout
|
||||
<html>
|
||||
<head>
|
||||
<% unless @done %>
|
||||
<script>
|
||||
function reload() {
|
||||
location.reload();
|
||||
}
|
||||
setTimeout(reload, 5000);
|
||||
</script>
|
||||
<% end %>
|
||||
</head>
|
||||
<body>
|
||||
<%= yield %>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ index
|
||||
<pre>
|
||||
<%= @text %>
|
||||
</pre>
|
||||
115
devops-service/app/api2/routes/script.rb
Normal file
115
devops-service/app/api2/routes/script.rb
Normal file
@ -0,0 +1,115 @@
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Routes
|
||||
module ScriptRoutes
|
||||
|
||||
def self.registered(app)
|
||||
# Get scripts names
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# [
|
||||
# "script_1"
|
||||
# ]
|
||||
app.get_with_headers "/scripts", :headers => [:accept] do
|
||||
check_privileges("script", "r")
|
||||
json Devops::API2_0::Handler::Script.new(request, params).scripts
|
||||
end
|
||||
|
||||
# Run command on node :node_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : POST
|
||||
# - body :
|
||||
# command to run
|
||||
#
|
||||
# * *Returns* : text stream
|
||||
app.post_with_statistic "/script/command/:node_name" do |node_name|
|
||||
check_privileges("script", "x")
|
||||
stream() do |out|
|
||||
begin
|
||||
Devops::API2_0::Handler::Script.new(request, params).execute_command(out, request.body.read, node_name)
|
||||
rescue IOError => e
|
||||
logger.error e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Run script :script_name on nodes
|
||||
#
|
||||
# * *Request*
|
||||
# - method : POST
|
||||
# - headers :
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# {
|
||||
# "nodes": [], -> array of nodes names
|
||||
# "params": [] -> array of script arguments
|
||||
# }
|
||||
#
|
||||
# * *Returns* : text stream
|
||||
app.post_with_headers "/script/run/:script_name", :headers => [:content_type] do |script_name|
|
||||
check_privileges("script", "x")
|
||||
file_name = check_filename(script_name, "Parameter 'script_name' must be a not empty string", false)
|
||||
body = create_object_from_json_body
|
||||
nodes = check_array(body["nodes"], "Parameter 'nodes' must be a not empty array of strings")
|
||||
p = check_array(body["params"], "Parameter 'params' should be a not empty array of strings", String, true)
|
||||
|
||||
stream() do |out|
|
||||
begin
|
||||
Devops::API2_0::Handler::Script.new(request, params).run_script out, file_name, nodes, p
|
||||
rescue IOError => e
|
||||
logger.error e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
hash = {}
|
||||
# Create script :script_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : PUT
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - body : script content
|
||||
#
|
||||
# * *Returns* :
|
||||
# 201 - Created
|
||||
hash["PUT"] = lambda {
|
||||
check_privileges("script", "w")
|
||||
file_name = params[:script_name]
|
||||
check_filename(file_name, "Parameter 'script_name' must be a not empty string")
|
||||
Devops::API2_0::Handler::Script.new(request, params).create_script(file_name)
|
||||
create_response("File '#{file_name}' created", nil, 201)
|
||||
}
|
||||
|
||||
# Delete script :script_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : Delete
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Deleted
|
||||
hash["DELETE"] = lambda {
|
||||
check_privileges("script", "w")
|
||||
file_name = params[:script_name]
|
||||
check_filename(file_name, "Parameter 'script_name' must be a not empty string")
|
||||
Devops::API2_0::Handler::Script.new(request, params).delete_script file_name
|
||||
create_response("File '#{file_name}' deleted")
|
||||
}
|
||||
app.multi_routes "/script/:script_name", {:headers => [:accept]}, hash
|
||||
|
||||
puts "Script routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,7 +1,7 @@
|
||||
require "json"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module API2_0
|
||||
module Routes
|
||||
module ServerRoutes
|
||||
|
||||
@ -23,7 +23,17 @@ module Devops
|
||||
# "chef_node_name": "chef name"
|
||||
# }
|
||||
# ]
|
||||
app.get_with_headers "/servers", :headers => [:accept], &Devops::Version2_0::Handler::Server.get_servers
|
||||
app.get_with_headers "/servers", :headers => [:accept] do
|
||||
check_privileges("server", "r")
|
||||
fields = []
|
||||
if params.key?("fields") and params["fields"].is_a?(Array)
|
||||
Devops::Model::Server.fields.each do |k|
|
||||
fields.push k if params["fields"].include?(k)
|
||||
end
|
||||
end
|
||||
reserved = (params.key?("reserved") ? true : nil)
|
||||
json Devops::API2_0::Handler::Server.new(request, params).servers(fields, reserved)
|
||||
end
|
||||
|
||||
# Get chef nodes list
|
||||
#
|
||||
@ -38,7 +48,10 @@ module Devops
|
||||
# "chef_node_name": "chef name"
|
||||
# }
|
||||
# ]
|
||||
app.get_with_headers "/servers/chef", :headers => [:accept], &Devops::Version2_0::Handler::Server.get_chef_servers
|
||||
app.get_with_headers "/servers/chef", :headers => [:accept] do
|
||||
check_privileges("server", "r")
|
||||
json Devops::API2_0::Handler::Server.new(request, params).chef_servers
|
||||
end
|
||||
|
||||
# Get provider servers list
|
||||
#
|
||||
@ -76,7 +89,10 @@ module Devops
|
||||
# "private_ip": "172.17.0.1"
|
||||
# }
|
||||
# ]
|
||||
app.get_with_headers "/servers/:provider", :headers => [:accept], &Devops::Version2_0::Handler::Server.get_provider_servers
|
||||
app.get_with_headers "/servers/:provider", :headers => [:accept] do
|
||||
check_privileges("server", "r")
|
||||
json Devops::API2_0::Handler::Server.new(request, params).provider_servers(params[:provider])
|
||||
end
|
||||
|
||||
# Get server info by :name
|
||||
#
|
||||
@ -94,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
|
||||
#
|
||||
@ -110,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
|
||||
@ -133,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
|
||||
#
|
||||
@ -149,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
|
||||
#
|
||||
@ -165,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
|
||||
#
|
||||
@ -181,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
|
||||
#
|
||||
@ -197,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
|
||||
#
|
||||
@ -215,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
|
||||
#
|
||||
@ -236,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
|
||||
61
devops-service/app/api2/routes/stack.rb
Normal file
61
devops-service/app/api2/routes/stack.rb
Normal file
@ -0,0 +1,61 @@
|
||||
module Devops
|
||||
module API2_0
|
||||
module Routes
|
||||
module StackRoutes
|
||||
|
||||
def self.registered(app)
|
||||
|
||||
app.get_with_headers '/stacks', :headers => [:accept] do
|
||||
check_privileges("stack", "r")
|
||||
json Devops::API2_0::Handler::Stack.new(request, params).stacks.map(&:to_hash)
|
||||
end
|
||||
|
||||
app.get_with_headers '/stacks/provider/:provider', :headers => [:accept] do |provider|
|
||||
check_privileges("stack", "r")
|
||||
check_provider(provider)
|
||||
json Devops::API2_0::Handler::Stack.new(request, params).stacks_for_provider(provider).map(&:to_hash)
|
||||
end
|
||||
|
||||
app.post_with_headers "/stack", :headers => [:accept] do
|
||||
check_privileges("stack", "w")
|
||||
object = create_object_from_json_body
|
||||
m = Devops::API2_0::Handler::Stack.new(request, params).create_stack object
|
||||
create_response "Created", m.to_hash, 201
|
||||
end
|
||||
|
||||
hash = {}
|
||||
|
||||
hash['GET'] = lambda { |stack_id|
|
||||
check_privileges("stack", "r")
|
||||
json Devops::API2_0::Handler::Stack.new(request, params).stack(stack_id).to_hash
|
||||
}
|
||||
|
||||
hash['DELETE'] = lambda { |stack_id|
|
||||
check_privileges("stack", "w")
|
||||
Devops::API2_0::Handler::Stack.new(request, params).delete_stack(stack_id)
|
||||
create_response("Stack '#{stack_id}' has been removed")
|
||||
}
|
||||
app.multi_routes '/stack/:stack_id', {:headers => [:accept]}, hash
|
||||
|
||||
app.post_with_headers "/stack/:stack_id/sync_details", :headers => [:accept] do |stack_id|
|
||||
check_privileges("stack", "w")
|
||||
json Devops::API2_0::Handler::Stack.new(request, params).sync_details(stack_id).to_hash
|
||||
end
|
||||
|
||||
app.get_with_headers "/stack/:stack_id/resources", :headers => [:accept] do |stack_id|
|
||||
check_privileges("stack", "r")
|
||||
json Devops::API2_0::Handler::Stack.new(request, params).resources(stack_id)
|
||||
end
|
||||
|
||||
app.get_with_headers "/stack/:stack_id/resources/:resource_id", :headers => [:accept] do |stack_id, resource_id|
|
||||
check_privileges("stack", "r")
|
||||
json Devops::API2_0::Handler::Stack.new(request, params).resource(stack_id, resource_id)
|
||||
end
|
||||
|
||||
puts "Stack routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,10 +1,10 @@
|
||||
module Devops
|
||||
module Version2_0
|
||||
module API2_0
|
||||
module Routes
|
||||
module StackPresetRoutes
|
||||
|
||||
def self.registered(app)
|
||||
# Get list of available stack_presets
|
||||
# Get list of available stack_template_presets
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
@ -14,10 +14,12 @@ module Devops
|
||||
# * *Returns* : array of hashes
|
||||
# [ {id: 'preset id', template_preset_body: 'long body'} ]
|
||||
#
|
||||
app.get_with_headers "/stack_presets", :headers => [:accept], &Devops::Version2_0::Handler::StackPreset.get_presets
|
||||
app.get_with_headers "/stack_presets", :headers => [:accept] do
|
||||
# check_privileges("stack_template_presets", "r")
|
||||
json Devops::API2_0::Handler::StackPreset.new(request, params).presets.map(&:to_hash)
|
||||
end
|
||||
|
||||
|
||||
# Get information about stack_preset
|
||||
# Get information about stack_template_preset
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
@ -27,8 +29,10 @@ module Devops
|
||||
# * *Returns* : hash
|
||||
# {id: 'preset id', template_preset_body: 'long body'}
|
||||
#
|
||||
app.get_with_headers "/stack_presets/:id", :headers => [:accept], &Devops::Version2_0::Handler::StackPreset.get_preset
|
||||
|
||||
app.get_with_headers "/stack_presets/:id", :headers => [:accept] do |id|
|
||||
# check_privileges("stack_template_presets", "r")
|
||||
json Devops::API2_0::Handler::StackPreset.new(request, params).preset(id).to_hash
|
||||
end
|
||||
|
||||
# Build stack template from preset
|
||||
#
|
||||
@ -38,7 +42,7 @@ module Devops
|
||||
# - Accept: application/json
|
||||
# - params :
|
||||
# - provider: string
|
||||
# - stack_id: id of stack template to create
|
||||
# - stack_template_id: id of stack template to create
|
||||
# - template_attrs: hash with template attributes
|
||||
#
|
||||
# TODO: not stack template, but stack itself
|
||||
@ -50,7 +54,13 @@ module Devops
|
||||
# template_body: 'long body'
|
||||
# }
|
||||
#
|
||||
app.post_with_headers "/stack_presets/:id/apply", :headers => [:accept], &Devops::Version2_0::Handler::StackPreset.apply
|
||||
app.post_with_headers "/stack_presets/:id/apply", :headers => [:accept] do |id|
|
||||
# check_privileges("stack_template_presets", "r")
|
||||
check_privileges('stack_template', 'w')
|
||||
body = create_object_from_json_body
|
||||
stack = Devops::API2_0::Handler::StackPreset.new(request, params).apply(id, body)
|
||||
create_response 'Created', stack.to_hash, 201
|
||||
end
|
||||
|
||||
puts "Stack template presets routes initialized"
|
||||
end
|
||||
46
devops-service/app/api2/routes/stack_template.rb
Normal file
46
devops-service/app/api2/routes/stack_template.rb
Normal file
@ -0,0 +1,46 @@
|
||||
module Devops
|
||||
module API2_0
|
||||
module Routes
|
||||
module StackTemplateRoutes
|
||||
|
||||
def self.registered(app)
|
||||
app.get_with_headers '/stack_templates', :headers => [:accept] do
|
||||
check_privileges('stack_template', 'r')
|
||||
json Devops::API2_0::Handler::StackTemplate.new(request, params).stack_templates.map(&:to_hash)
|
||||
end
|
||||
|
||||
app.get_with_headers '/stack_templates/provider/:provider', :headers => [:accept] do |provider|
|
||||
check_privileges('stack_template', 'r')
|
||||
check_provider(provider)
|
||||
json Devops::API2_0::Handler::StackTemplate.new(request, params).stack_templates_for_provider(provider).map(&:to_hash)
|
||||
end
|
||||
|
||||
app.post_with_headers "/stack_template", :headers => [:accept] do
|
||||
check_privileges('stack_template', 'w')
|
||||
body = create_object_from_json_body
|
||||
model = Devops::API2_0::Handler::StackTemplate.new(request, params).create_stack_template(body)
|
||||
create_response 'Created', model.to_hash, 201
|
||||
end
|
||||
|
||||
hash = {}
|
||||
|
||||
hash['GET'] = lambda {|stack_template_id|
|
||||
check_privileges('stack_template', 'r')
|
||||
json Devops::API2_0::Handler::StackTemplate.new(request, params).stack_template(stack_template_id).to_hash
|
||||
}
|
||||
|
||||
hash['DELETE'] = lambda {|stack_template_id|
|
||||
check_privileges('stack_template', 'w')
|
||||
Devops::API2_0::Handler::StackTemplate.new(request, params).delete_stack_template(stack_template_id)
|
||||
create_response("Template '#{stack_template_id}' has been removed")
|
||||
}
|
||||
|
||||
app.multi_routes '/stack_template/:stack_template_id', {}, hash
|
||||
|
||||
puts "Stack_template routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,5 +1,5 @@
|
||||
module Devops
|
||||
module Version2_0
|
||||
module API2_0
|
||||
module Routes
|
||||
module TagRoutes
|
||||
|
||||
@ -17,7 +17,10 @@ module Devops
|
||||
# [
|
||||
# "tag_1"
|
||||
# ]
|
||||
hash["GET"] = Devops::Version2_0::Handler::Tag.get_tags
|
||||
hash["GET"] = lambda {
|
||||
check_privileges("server", "r")
|
||||
json Devops::API2_0::Handler::Tag.new(params[:node_name]).tags()
|
||||
}
|
||||
|
||||
# Set tags list to :node_name
|
||||
#
|
||||
@ -33,7 +36,13 @@ module Devops
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200
|
||||
hash["POST"] = Devops::Version2_0::Handler::Tag.set_tags
|
||||
hash["POST"] = lambda {
|
||||
check_privileges("server", "w")
|
||||
tags = create_object_from_json_body(Array)
|
||||
check_array(tags, "Request body should be a not empty array of strings")
|
||||
Devops::Version2_0::Handler::Tag.new(params[:node_name]).set_tags(tags)
|
||||
create_response("Set tags for #{params[:node_name]}", tags: tags)
|
||||
}
|
||||
|
||||
# Delete tags from :node_name
|
||||
#
|
||||
@ -49,7 +58,13 @@ module Devops
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200
|
||||
hash["DELETE"] = Devops::Version2_0::Handler::Tag.unset_tags
|
||||
hash["DELETE"] = lambda {
|
||||
check_privileges("server", "w")
|
||||
tags = create_object_from_json_body(Array)
|
||||
check_array(tags, "Request body should be a not empty array of strings")
|
||||
Devops::Version2_0::Handler::Tag.new(params[:node_name]).unset_tags(tags)
|
||||
create_response("Deleted tags for #{params[:node_name]}", tags: tags)
|
||||
}
|
||||
app.multi_routes "/tags/:node_name", {:headers => [:accept, :content_type]}, hash
|
||||
|
||||
puts "Tag routes initialized"
|
||||
@ -1,5 +1,5 @@
|
||||
module Devops
|
||||
module Version2_0
|
||||
module API2_0
|
||||
module Routes
|
||||
module UserRoutes
|
||||
|
||||
@ -33,7 +33,11 @@ module Devops
|
||||
# "id": "test"
|
||||
# }
|
||||
# ]
|
||||
app.get_with_headers "/users", :headers => [:accept], &Devops::Version2_0::Handler::User.get_users
|
||||
app.get_with_headers "/users", :headers => [:accept] do#, &Devops::API2_0::Handler::User.get_users
|
||||
check_privileges("user", "r")
|
||||
users = Devops::API2_0::Handler::User.new.users.map {|i| h = i.to_hash; h.delete("password"); h}
|
||||
json users
|
||||
end
|
||||
|
||||
# Create user
|
||||
#
|
||||
@ -51,7 +55,15 @@ module Devops
|
||||
#
|
||||
# * *Returns* :
|
||||
# 201 - Created
|
||||
app.post_with_headers "/user", :headers => [:accept, :content_type], &Devops::Version2_0::Handler::User.create_user
|
||||
app.post_with_headers "/user", :headers => [:accept, :content_type] do#, &Devops::API2_0::Handler::User.create_user
|
||||
check_privileges("user", "w")
|
||||
user = create_object_from_json_body
|
||||
["username", "password", "email"].each do |p|
|
||||
check_string(user[p], "Parameter '#{p}' must be a not empty string")
|
||||
end
|
||||
Devops::API2_0::Handler::User.new.create(user)
|
||||
create_response("Created", nil, 201)
|
||||
end
|
||||
|
||||
hash = {}
|
||||
# Delete user
|
||||
@ -63,7 +75,24 @@ module Devops
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Deleted
|
||||
hash["DELETE"] = Devops::Version2_0::Handler::User.delete_user
|
||||
hash["DELETE"] = lambda {
|
||||
check_privileges("user", "w")
|
||||
projects = Devops::Db.connector.projects_by_user params[:user]
|
||||
if !projects.empty?
|
||||
str = ""
|
||||
projects.each do |p|
|
||||
p.deploy_envs.each do |e|
|
||||
str+="#{p.id}.#{e.identifier} " if e.users.include? params[:user]
|
||||
end
|
||||
end
|
||||
logger.info projects
|
||||
raise DependencyError.new "Deleting is forbidden: User is included in #{str}"
|
||||
#return [400, "Deleting is forbidden: User is included in #{str}"]
|
||||
end
|
||||
|
||||
Devops::API2_0::Handler::User.new.delete(params[:user])
|
||||
create_response("User '#{params[:user]}' removed")
|
||||
}
|
||||
|
||||
# Change user privileges
|
||||
#
|
||||
@ -80,7 +109,14 @@ module Devops
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Updated
|
||||
hash["PUT"] = Devops::Version2_0::Handler::User.change_user_privileges
|
||||
hash["PUT"] = lambda {
|
||||
check_privileges("user", "w")
|
||||
data = create_object_from_json_body
|
||||
cmd = check_string(data["cmd"], "Parameter 'cmd' should be a not empty string", true) || ""
|
||||
privileges = check_string(data["privileges"], "Parameter 'privileges' should be a not empty string", true) || ""
|
||||
Devops::API2_0::Handler::User.new.change_user_privileges(params[:user], cmd, privileges)
|
||||
create_response("Updated")
|
||||
}
|
||||
app.multi_routes "/user/:user", {:headers => [:accept, :content_type]}, hash
|
||||
|
||||
# Change user email/password
|
||||
@ -97,7 +133,20 @@ module Devops
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Updated
|
||||
app.put_with_headers %r{\A/user/#{DevopsConfig::OBJECT_NAME}/(email|password)\z}, :headers => [:accept, :content_type], &Devops::Version2_0::Handler::User.change_user_email_or_password
|
||||
app.put_with_headers %r{\A/user/#{DevopsConfig::OBJECT_NAME}/(email|password)\z}, :headers => [:accept, :content_type] do#, &Devops::API2_0::Handler::User.change_user_email_or_password
|
||||
check_privileges("user", "w")
|
||||
action = File.basename(request.path)
|
||||
u = File.basename(File.dirname(request.path))
|
||||
raise InvalidPrivileges.new("Access denied for '#{request.env['REMOTE_USER']}'") if u == Devops::Model::User::ROOT_USER_NAME and request.env['REMOTE_USER'] != Devops::Model::User::ROOT_USER_NAME
|
||||
|
||||
check_privileges("user", "w") unless request.env['REMOTE_USER'] == u
|
||||
|
||||
body = create_object_from_json_body
|
||||
p = check_string(body[action], "Parameter '#{action}' must be a not empty string")
|
||||
h = Devops::API2_0::Handler::User.new
|
||||
h.send("change_#{action}=", p)
|
||||
create_response("Updated")
|
||||
end
|
||||
|
||||
puts "User routes initialized"
|
||||
end
|
||||
@ -1,20 +1,32 @@
|
||||
require "sinatra/base"
|
||||
require "sinatra/streaming"
|
||||
require "helpers/version_2"
|
||||
require "json"
|
||||
|
||||
require "fog"
|
||||
|
||||
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"
|
||||
|
||||
module Devops
|
||||
class Api2 < Sinatra::Base
|
||||
|
||||
include Sinatra::JSON
|
||||
helpers Sinatra::Streaming
|
||||
helpers Devops::Version2_0::Helpers
|
||||
helpers Devops::API2_0::Helpers
|
||||
|
||||
register Sinatra::DevopsAuth
|
||||
|
||||
configure :production do
|
||||
config = DevopsConfig.config
|
||||
log_file = File.join(config[:log_dir], "devops-api2.log")
|
||||
logger = DevopsLogger.create(log_file, Logger::DEBUG)
|
||||
use Rack::CommonLogger, logger
|
||||
disable :dump_errors
|
||||
disable :show_exceptions
|
||||
set :logging, Logger::INFO
|
||||
@ -22,11 +34,14 @@ module Devops
|
||||
end
|
||||
|
||||
configure :development do
|
||||
set :logging, Logger::DEBUG
|
||||
config = DevopsConfig.config
|
||||
log_file = File.join(config[:log_dir], "devops-api2.log")
|
||||
logger = DevopsLogger.create(log_file, Logger::DEBUG)
|
||||
use Rack::CommonLogger, logger
|
||||
disable :raise_errors
|
||||
# disable :dump_errors
|
||||
set :show_exceptions, :after_handler
|
||||
puts "Development mode"
|
||||
logger.info "Development mode"
|
||||
end
|
||||
|
||||
not_found do
|
||||
@ -58,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
|
||||
@ -1,4 +1,6 @@
|
||||
require 'sinatra/base'
|
||||
require 'core/devops-logger'
|
||||
require 'core/devops-config'
|
||||
|
||||
class Client < Sinatra::Base
|
||||
|
||||
@ -7,6 +9,29 @@ class Client < Sinatra::Base
|
||||
@@config = DevopsConfig.config
|
||||
end
|
||||
|
||||
configure :production do
|
||||
config = DevopsConfig.config
|
||||
log_file = File.join(config[:log_dir], "devops-client.log")
|
||||
logger = DevopsLogger.create(log_file, Logger::INFO)
|
||||
use Rack::CommonLogger, logger
|
||||
disable :dump_errors
|
||||
disable :show_exceptions
|
||||
# set :logging, Logger::INFO
|
||||
logger.info "Production mode"
|
||||
end
|
||||
|
||||
configure :development do
|
||||
config = DevopsConfig.config
|
||||
log_file = File.join(config[:log_dir], "devops-client.log")
|
||||
logger = DevopsLogger.create(log_file, Logger::DEBUG)
|
||||
use Rack::CommonLogger, logger
|
||||
# set :logging, Logger::DEBUG
|
||||
disable :raise_errors
|
||||
# disable :dump_errors
|
||||
set :show_exceptions, :after_handler
|
||||
logger.info "Development mode"
|
||||
end
|
||||
|
||||
# Route to download devops client
|
||||
get "/devops-client.gem" do
|
||||
begin
|
||||
|
||||
@ -1,81 +1,78 @@
|
||||
module Devops
|
||||
module Application
|
||||
class DevopsApi2Application < Application
|
||||
class DevopsApi2Application < Application
|
||||
|
||||
def prepare
|
||||
require "routes/v2.0"
|
||||
require "routes/v2.0/handlers/provider"
|
||||
require "routes/v2.0/handlers/bootstrap_templates"
|
||||
require "routes/v2.0/handlers/deploy"
|
||||
require "routes/v2.0/handlers/filter"
|
||||
require "routes/v2.0/handlers/flavor"
|
||||
require "routes/v2.0/handlers/group"
|
||||
require "routes/v2.0/handlers/image"
|
||||
require "routes/v2.0/handlers/network"
|
||||
require "routes/v2.0/handlers/key"
|
||||
require "routes/v2.0/handlers/project"
|
||||
require "routes/v2.0/handlers/script"
|
||||
require "routes/v2.0/handlers/status"
|
||||
require "routes/v2.0/handlers/tag"
|
||||
require "routes/v2.0/handlers/user"
|
||||
require "routes/v2.0/handlers/server"
|
||||
require "routes/v2.0/handlers/stack"
|
||||
require "routes/v2.0/handlers/stack_template"
|
||||
require "routes/v2.0/stack_presets"
|
||||
require "routes/v2.0/handlers/report"
|
||||
def prepare
|
||||
require_relative "api2/routes/v2.0"
|
||||
require_relative "api2/handlers/provider"
|
||||
require_relative "api2/handlers/flavor"
|
||||
require_relative "api2/handlers/filter"
|
||||
require_relative "api2/handlers/group"
|
||||
require_relative "api2/handlers/user"
|
||||
require_relative "api2/handlers/network"
|
||||
require_relative "api2/handlers/report"
|
||||
require_relative "api2/handlers/deploy"
|
||||
require_relative "api2/handlers/script"
|
||||
require_relative "api2/handlers/bootstrap_templates"
|
||||
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 'lib/stubber'
|
||||
end
|
||||
|
||||
def init
|
||||
config = DevopsConfig.config
|
||||
Devops::Api2.set :devops_home, config[:devops_dir]
|
||||
#set :config, config
|
||||
|
||||
Devops::Api2.set :keys_dir, (config[:keys_dir] || File.join(config[:devops_dir], "files/keys"))
|
||||
Devops::Api2.set :scripts_dir, (config[:scripts_dir] || File.join(config[:devops_dir], "files/scripts"))
|
||||
[:keys_dir, :scripts_dir].each {|key| d = Devops::Api2.settings.send(key); FileUtils.mkdir_p(d) unless File.exists?(d) }
|
||||
init_mongo
|
||||
Devops::Api2.settings.mongo.create_root_user
|
||||
::Provider::ProviderFactory.init(config)
|
||||
|
||||
Stubber.stub_providers!(config[:stub_providers])
|
||||
end
|
||||
|
||||
def routes
|
||||
require "routes/v2.0/flavor"
|
||||
require "routes/v2.0/image"
|
||||
require "routes/v2.0/filter"
|
||||
require "routes/v2.0/network"
|
||||
require "routes/v2.0/group"
|
||||
require "routes/v2.0/deploy"
|
||||
require "routes/v2.0/project"
|
||||
require "routes/v2.0/key"
|
||||
require "routes/v2.0/user"
|
||||
require "routes/v2.0/provider"
|
||||
require "routes/v2.0/tag"
|
||||
require "routes/v2.0/server"
|
||||
require "routes/v2.0/script"
|
||||
require "routes/v2.0/status"
|
||||
require "routes/v2.0/bootstrap_templates"
|
||||
require "routes/v2.0/stack"
|
||||
require "routes/v2.0/stack_template"
|
||||
require "routes/v2.0/handlers/stack_preset"
|
||||
require "routes/v2.0/report"
|
||||
|
||||
routes = Devops::Version2_0::Routes.constants.collect{|s| Devops::Version2_0::Routes.const_get(s)}.select {|const| const.class == Module}
|
||||
routes.each do |r|
|
||||
Devops::Api2.register r
|
||||
end
|
||||
Routes.route "/v2.0", Devops::Api2
|
||||
end
|
||||
|
||||
private
|
||||
def init_mongo
|
||||
Devops::Api2.set :mongo, Devops::Db.connector
|
||||
end
|
||||
require_relative "api2/handlers/stack"
|
||||
require_relative "api2/handlers/stack_template"
|
||||
require_relative "api2/handlers/stack_preset"
|
||||
|
||||
require 'lib/stubber'
|
||||
end
|
||||
|
||||
def init
|
||||
config = DevopsConfig.config
|
||||
Devops::Api2.set :devops_home, config[:devops_dir]
|
||||
#set :config, config
|
||||
|
||||
Devops::Api2.set :keys_dir, (config[:keys_dir] || File.join(config[:devops_dir], "files/keys"))
|
||||
Devops::Api2.set :scripts_dir, (config[:scripts_dir] || File.join(config[:devops_dir], "files/scripts"))
|
||||
[:keys_dir, :scripts_dir].each {|key| d = Devops::Api2.settings.send(key); FileUtils.mkdir_p(d) unless File.exists?(d) }
|
||||
init_mongo
|
||||
Devops::Api2.settings.mongo.create_root_user
|
||||
::Provider::ProviderFactory.init(config)
|
||||
|
||||
Stubber.stub_providers! if config[:stub_classes]
|
||||
end
|
||||
|
||||
def routes
|
||||
require_relative "api2/routes/flavor"
|
||||
require_relative "api2/routes/image"
|
||||
require_relative "api2/routes/filter"
|
||||
require_relative "api2/routes/network"
|
||||
require_relative "api2/routes/group"
|
||||
require_relative "api2/routes/deploy"
|
||||
require_relative "api2/routes/project"
|
||||
require_relative "api2/routes/key"
|
||||
require_relative "api2/routes/user"
|
||||
require_relative "api2/routes/provider"
|
||||
require_relative "api2/routes/tag"
|
||||
require_relative "api2/routes/server"
|
||||
require_relative "api2/routes/script"
|
||||
require_relative "api2/routes/bootstrap_templates"
|
||||
require_relative "api2/routes/stack"
|
||||
require_relative "api2/routes/stack_template"
|
||||
require_relative "api2/routes/stack_presets"
|
||||
require_relative "api2/routes/report"
|
||||
|
||||
routes = Devops::API2_0::Routes.constants.collect{|s| Devops::API2_0::Routes.const_get(s)}.select {|const| const.class == Module}
|
||||
routes.each do |r|
|
||||
Devops::Api2.register r
|
||||
end
|
||||
Routes.route "/v2.0", Devops::Api2
|
||||
end
|
||||
|
||||
private
|
||||
def init_mongo
|
||||
Devops::Api2.set :mongo, Devops::Db.connector
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
module Devops
|
||||
module Application
|
||||
class Application
|
||||
|
||||
@@applications = []
|
||||
|
||||
def self.inherited(base)
|
||||
@@applications << base.new
|
||||
puts "Devops application '#{base}' has been added"
|
||||
end
|
||||
|
||||
def self.applications
|
||||
@@applications
|
||||
end
|
||||
|
||||
def prepare
|
||||
|
||||
end
|
||||
|
||||
def init
|
||||
|
||||
end
|
||||
|
||||
def routes
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,14 +1,12 @@
|
||||
module Devops
|
||||
module Application
|
||||
class DevopsClientApplication < Application
|
||||
class DevopsClientApplication < Application
|
||||
|
||||
def prepare
|
||||
require "app/client/devops-client"
|
||||
end
|
||||
def prepare
|
||||
require "app/client/devops-client"
|
||||
end
|
||||
|
||||
def routes
|
||||
Routes.route "/client", ::Client.new
|
||||
end
|
||||
def routes
|
||||
Routes.route "/client", ::Client.new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
module Devops
|
||||
module Application
|
||||
class DevopsVersionApplication < Application
|
||||
class DevopsVersionApplication < Application
|
||||
|
||||
def prepare
|
||||
require "app/version/version"
|
||||
end
|
||||
def prepare
|
||||
require "app/version/version"
|
||||
end
|
||||
|
||||
def routes
|
||||
Routes.route "/version", ::DevopsVersion.new
|
||||
end
|
||||
def routes
|
||||
Routes.route "/version", ::DevopsVersion.new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,17 +1,22 @@
|
||||
require 'core/devops-logger'
|
||||
require 'core/devops-config'
|
||||
|
||||
module Devops
|
||||
module Application
|
||||
|
||||
class SidekiqApplication < Application
|
||||
|
||||
def prepare
|
||||
require "sidekiq/web"
|
||||
end
|
||||
|
||||
def routes
|
||||
Devops::Routes.route "/sidekiq", Sidekiq::Web
|
||||
end
|
||||
class SidekiqApplication < Application
|
||||
|
||||
def prepare
|
||||
require "sidekiq/web"
|
||||
end
|
||||
|
||||
def routes
|
||||
config = DevopsConfig.config
|
||||
log_file = File.join(config[:log_dir], "devops-sidekiq-web.log")
|
||||
logger = DevopsLogger.create(log_file, Logger::INFO)
|
||||
Sidekiq::Web.use Rack::CommonLogger, logger
|
||||
Devops::Routes.route "/sidekiq", Sidekiq::Web
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ require 'sinatra/base'
|
||||
|
||||
class DevopsVersion < Sinatra::Base
|
||||
|
||||
VERSION = "3.0.0"
|
||||
VERSION = "2.3.0"
|
||||
|
||||
get "/" do
|
||||
VERSION
|
||||
|
||||
4
devops-service/applications.rb
Normal file
4
devops-service/applications.rb
Normal file
@ -0,0 +1,4 @@
|
||||
require "app/sidekiq_web"
|
||||
require "app/devops-client"
|
||||
require "app/devops-version"
|
||||
require "app/devops-api2"
|
||||
@ -12,8 +12,9 @@ module Sinatra
|
||||
if @auth.provided? and @auth.basic? and @auth.credentials
|
||||
c = @auth.credentials
|
||||
begin
|
||||
Devops::Db.connector.user_auth(c[0], c[1])
|
||||
u = Devops::Db.connector.user_auth(c[0], c[1])
|
||||
request.env['REMOTE_USER'] = c[0]
|
||||
request.env['USER'] = u
|
||||
true
|
||||
rescue RecordNotFound => e
|
||||
false
|
||||
|
||||
@ -2,7 +2,8 @@ module BootstrapTemplatesCommands
|
||||
|
||||
def get_templates
|
||||
res = []
|
||||
Dir.foreach("#{ENV["HOME"]}/.chef/bootstrap/") {|f| res.push(f[0..-5]) if f.end_with?(".erb")} if File.exists? "#{ENV["HOME"]}/.chef/bootstrap/"
|
||||
dir = "#{ENV["HOME"]}/.chef/bootstrap/"
|
||||
Dir.foreach(dir) {|f| res.push(f[0..-5]) if f.end_with?(".erb")} if File.exists? dir
|
||||
res
|
||||
end
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
require "db/exceptions/invalid_record"
|
||||
require "commands/image"
|
||||
|
||||
module DeployEnvCommands
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
require "commands/knife_commands"
|
||||
require "commands/deploy"
|
||||
require "db/exceptions/record_not_found"
|
||||
require "exceptions/record_not_found"
|
||||
|
||||
module ServerCommands
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# path to log file
|
||||
config[:log_file] = "/path/to/log"
|
||||
# path to log dir
|
||||
config[:log_dir] = "/path/to/log"
|
||||
# path to chef knife.rb file
|
||||
config[:knife_config_file] = "/path/to/.chef/knife.rb"
|
||||
# role name separator
|
||||
@ -43,4 +43,4 @@ config[:debug] = true
|
||||
|
||||
# set it to :all or [:ec2] to stub calls to selected providers
|
||||
# or to false to disable stubbing
|
||||
config[:stub_providers] = false
|
||||
config[:stub_providers] = false
|
||||
|
||||
@ -4,11 +4,12 @@ require "rubygems"
|
||||
require "bundler/setup"
|
||||
require 'byebug'
|
||||
|
||||
require_relative "devops-service"
|
||||
require_relative "devops_config"
|
||||
require_relative "devops-routes"
|
||||
|
||||
root = File.dirname(__FILE__)
|
||||
$:.push root
|
||||
|
||||
require_relative "core/devops-service"
|
||||
require_relative "core/devops-config"
|
||||
require_relative "core/devops-routes"
|
||||
|
||||
# Read configuration file
|
||||
DevopsConfig.read
|
||||
@ -27,6 +28,10 @@ config[:report_dir_v2] = File.expand_path(File.join(config[:devops_dir], "report
|
||||
|
||||
DevopsService.init
|
||||
puts Devops::Routes.routes
|
||||
if Devops::Routes.routes.empty?
|
||||
puts "No applications"
|
||||
exit -1
|
||||
end
|
||||
Devops::Routes.routes.each do |p, c|
|
||||
map(p) do
|
||||
run c
|
||||
|
||||
26
devops-service/core/devops-application.rb
Normal file
26
devops-service/core/devops-application.rb
Normal file
@ -0,0 +1,26 @@
|
||||
module Devops
|
||||
class Application
|
||||
|
||||
@@applications = []
|
||||
|
||||
def self.inherited(base)
|
||||
@@applications << base.new
|
||||
puts "Devops application '#{base}' has been added"
|
||||
end
|
||||
|
||||
def self.applications
|
||||
@@applications
|
||||
end
|
||||
|
||||
def prepare
|
||||
|
||||
end
|
||||
|
||||
def init
|
||||
|
||||
end
|
||||
|
||||
def routes
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -9,7 +9,7 @@ class DevopsConfig
|
||||
class << self
|
||||
def read config_file=nil
|
||||
if config_file.nil?
|
||||
config_file = ENV['DEVOPS_CONFIG'] || ENV['CONFIG'] || File.join(File.dirname(__FILE__), 'config.rb')
|
||||
config_file = ENV['DEVOPS_CONFIG'] || ENV['CONFIG'] || File.join(File.dirname(__FILE__), '../config.rb')
|
||||
end
|
||||
config = {:url_prefix => ""}
|
||||
if File.exists? config_file
|
||||
@ -1,3 +1,5 @@
|
||||
require "db/mongo/mongo_connector"
|
||||
|
||||
module Devops
|
||||
class Db
|
||||
|
||||
16
devops-service/core/devops-logger.rb
Normal file
16
devops-service/core/devops-logger.rb
Normal file
@ -0,0 +1,16 @@
|
||||
require "logger"
|
||||
|
||||
class DevopsLogger
|
||||
|
||||
def self.create out, level=Logger::INFO, format='%a %d-%m-%Y %H%M '
|
||||
@_logger = Logger.new out
|
||||
@_logger.level = level
|
||||
@_logger.datetime_format = format
|
||||
@_logger.debug("Logger has been created")
|
||||
@_logger
|
||||
end
|
||||
|
||||
def self.logger
|
||||
@_logger
|
||||
end
|
||||
end
|
||||
@ -1,29 +1,29 @@
|
||||
require "wisper"
|
||||
|
||||
$:.push File.dirname(__FILE__)
|
||||
=begin
|
||||
require "db/exceptions/invalid_record"
|
||||
require "db/exceptions/record_not_found"
|
||||
require "exceptions/dependency_error"
|
||||
require "db/validators/all"
|
||||
require "db/mongo/mongo_connector"
|
||||
require "providers/provider_factory"
|
||||
|
||||
require "fog"
|
||||
|
||||
require "loader"
|
||||
require "devops_db"
|
||||
require "devops_logger"
|
||||
|
||||
require_relative "routes/v2.0"
|
||||
|
||||
require "hooks"
|
||||
require "app/devops-application"
|
||||
require "app/devops-client"
|
||||
require "app/sidekiq_web"
|
||||
require "app/devops-version"
|
||||
require "app/devops-api2"
|
||||
=end
|
||||
|
||||
require_relative "sinatra/methods_with_headers"
|
||||
require_relative "devops-loader"
|
||||
require_relative "devops-db"
|
||||
require_relative "devops-logger"
|
||||
require_relative "devops-application"
|
||||
|
||||
require_relative "../sinatra/methods_with_headers"
|
||||
|
||||
require_relative "../applications"
|
||||
#root = File.expand_path("../", __FILE__)
|
||||
#$:.push root
|
||||
|
||||
class DevopsService
|
||||
|
||||
@ -51,7 +51,7 @@ class DevopsService
|
||||
DevopsLogger.create STDOUT
|
||||
|
||||
routes
|
||||
apps = Devops::Application::Application.applications
|
||||
apps = Devops::Application.applications
|
||||
apps.each do |a|
|
||||
a.prepare
|
||||
end
|
||||
@ -91,4 +91,4 @@ class DevopsService
|
||||
|
||||
end
|
||||
|
||||
require "wisper_fix"
|
||||
require_relative "../wisper_fix"
|
||||
@ -1,5 +1,5 @@
|
||||
require "db/exceptions/record_not_found"
|
||||
require "db/exceptions/invalid_record"
|
||||
require "exceptions/record_not_found"
|
||||
require "exceptions/invalid_record"
|
||||
require "exceptions/invalid_command"
|
||||
require "exceptions/invalid_privileges"
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
require "db/mongo/models/user"
|
||||
module Connectors
|
||||
class User < Base
|
||||
include Helpers::InsertCommand,
|
||||
@ -13,6 +14,7 @@ module Connectors
|
||||
def user_auth user, password
|
||||
u = collection.find('_id' => user, 'password' => password).to_a.first
|
||||
raise RecordNotFound.new('Invalid username or password') if u.nil?
|
||||
model_from_bson(u)
|
||||
end
|
||||
|
||||
def users(ids=nil)
|
||||
@ -33,19 +35,6 @@ module Connectors
|
||||
collection.insert(root.to_mongo_hash)
|
||||
end
|
||||
|
||||
def check_user_privileges(id, cmd, required_privelege)
|
||||
user = show(id)
|
||||
|
||||
unless %w(r w x).include?(required_privelege)
|
||||
raise InvalidPrivileges.new("Access internal problem with privilege '#{required_privelege}'")
|
||||
end
|
||||
|
||||
unless user.can?(cmd, required_privelege)
|
||||
raise InvalidPrivileges.new("Access denied for '#{user.id}'")
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def model_from_bson(bson)
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
require "db/mongo/models/mongo_model"
|
||||
require "db/exceptions/invalid_record"
|
||||
require "providers/provider_factory"
|
||||
require "commands/deploy_env"
|
||||
|
||||
|
||||
@ -1,4 +1,11 @@
|
||||
require "db/mongo/models/deploy_env/deploy_env_base"
|
||||
require "db/validators/deploy_env/run_list"
|
||||
require "db/validators/deploy_env/expiration"
|
||||
require "db/validators/deploy_env/users"
|
||||
require "db/validators/deploy_env/flavor"
|
||||
require "db/validators/deploy_env/image"
|
||||
require "db/validators/deploy_env/subnet_belongs_to_provider"
|
||||
require "db/validators/deploy_env/groups"
|
||||
|
||||
module Devops
|
||||
module Model
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
require "db/mongo/models/mongo_model"
|
||||
require "db/exceptions/invalid_record"
|
||||
require "commands/deploy_env"
|
||||
|
||||
module Devops
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
require "db/mongo/models/deploy_env/deploy_env_base"
|
||||
require "providers/provider_factory"
|
||||
require "db/validators/deploy_env/run_list"
|
||||
require "db/validators/deploy_env/expiration"
|
||||
require "db/validators/deploy_env/users"
|
||||
require "db/validators/deploy_env/flavor"
|
||||
require "db/validators/deploy_env/image"
|
||||
require "db/validators/deploy_env/subnet_not_empty"
|
||||
require "db/validators/deploy_env/subnet_belongs_to_provider"
|
||||
require "db/validators/deploy_env/groups"
|
||||
|
||||
module Devops
|
||||
module Model
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
require "db/mongo/models/deploy_env/deploy_env_base"
|
||||
require "db/validators/deploy_env/run_list"
|
||||
require "db/validators/deploy_env/expiration"
|
||||
require "db/validators/deploy_env/users"
|
||||
|
||||
module Devops
|
||||
module Model
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
require "db/exceptions/invalid_record"
|
||||
require "db/mongo/models/mongo_model"
|
||||
require "db/validators/image/bootstrap_template"
|
||||
require "db/validators/image/image_in_filter"
|
||||
|
||||
module Devops
|
||||
module Model
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
require "db/exceptions/invalid_record"
|
||||
require "db/mongo/models/mongo_model"
|
||||
require "json"
|
||||
require "db/validators/key/file_existence"
|
||||
require "db/validators/key/scope"
|
||||
|
||||
module Devops
|
||||
module Model
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
require "providers/provider_factory"
|
||||
require "db/exceptions/invalid_record"
|
||||
require "exceptions/invalid_record"
|
||||
require "json"
|
||||
require 'db/validators/all'
|
||||
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
require "db/exceptions/invalid_record"
|
||||
require "db/exceptions/record_not_found"
|
||||
require "db/mongo/models/deploy_env/deploy_env_factory"
|
||||
require "db/mongo/models/user"
|
||||
require "db/mongo/models/deploy_env/deploy_env_multi"
|
||||
require "db/mongo/models/mongo_model"
|
||||
require "json"
|
||||
require "hooks"
|
||||
require "lib/project/handler/types_factory"
|
||||
|
||||
module Devops
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
require "db/exceptions/invalid_record"
|
||||
require "db/mongo/models/mongo_model"
|
||||
|
||||
module Devops
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
require "db/exceptions/invalid_record"
|
||||
require "db/mongo/models/mongo_model"
|
||||
|
||||
module Devops
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
require "db/exceptions/invalid_record"
|
||||
require "exceptions/invalid_record"
|
||||
require "exceptions/invalid_command"
|
||||
require "db/mongo/models/mongo_model"
|
||||
|
||||
@ -70,15 +70,11 @@ module Devops
|
||||
o
|
||||
end
|
||||
|
||||
def can?(command, privilege)
|
||||
p = self.privileges[command] || []
|
||||
p.include?(privilege)
|
||||
end
|
||||
|
||||
def check_privilege cmd, priv
|
||||
p = self.privileges[cmd]
|
||||
return false if p.nil?
|
||||
return p.include?(priv)
|
||||
def check_privileges cmd, required_privelege
|
||||
unless PRIVILEGES.include?(required_privelege)
|
||||
raise InvalidPrivileges.new("Access internal problem with privilege '#{required_privelege}'")
|
||||
end
|
||||
can?(cmd, required_privelege)
|
||||
end
|
||||
|
||||
def self.create_root
|
||||
@ -89,6 +85,12 @@ module Devops
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def can?(command, privilege)
|
||||
p = self.privileges[command] || []
|
||||
p.include?(privilege)
|
||||
end
|
||||
|
||||
def privileges_with_value value, options={}
|
||||
privileges = {}
|
||||
[
|
||||
|
||||
@ -1,40 +1,42 @@
|
||||
class Validators::Base
|
||||
module Validators
|
||||
class Base
|
||||
|
||||
def initialize(model, options={})
|
||||
@model = model
|
||||
@options = options
|
||||
end
|
||||
def initialize(model, options={})
|
||||
@model = model
|
||||
@options = options
|
||||
end
|
||||
|
||||
def validate!
|
||||
raise InvalidRecord.new(message) unless valid?
|
||||
end
|
||||
def validate!
|
||||
raise InvalidRecord.new(message) unless valid?
|
||||
end
|
||||
|
||||
def valid?
|
||||
raise 'override me'
|
||||
end
|
||||
def valid?
|
||||
raise 'override me'
|
||||
end
|
||||
|
||||
def message
|
||||
raise 'override me'
|
||||
end
|
||||
def message
|
||||
raise 'override me'
|
||||
end
|
||||
|
||||
class << self
|
||||
private
|
||||
class << self
|
||||
private
|
||||
|
||||
# this method delegates @valid? and @message methods to helper validator, passed as block
|
||||
def delegate_to_helper_validator(&block)
|
||||
# this method delegates @valid? and @message methods to helper validator, passed as block
|
||||
def delegate_to_helper_validator(&block)
|
||||
|
||||
define_method :helper_validator do
|
||||
@helper_validator ||= self.instance_eval(&block)
|
||||
end
|
||||
define_method :helper_validator do
|
||||
@helper_validator ||= self.instance_eval(&block)
|
||||
end
|
||||
|
||||
define_method :valid? do
|
||||
self.helper_validator.valid?
|
||||
end
|
||||
define_method :valid? do
|
||||
self.helper_validator.valid?
|
||||
end
|
||||
|
||||
define_method :message do
|
||||
self.helper_validator.message
|
||||
define_method :message do
|
||||
self.helper_validator.message
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -2,8 +2,10 @@
|
||||
# not only in deploy env model
|
||||
|
||||
module Validators
|
||||
class DeployEnv::RunList < Base
|
||||
module DeployEnv
|
||||
class RunList < Base
|
||||
|
||||
delegate_to_helper_validator { Helpers::RunList.new(@model.run_list) }
|
||||
delegate_to_helper_validator { Helpers::RunList.new(@model.run_list) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,20 +1,24 @@
|
||||
require "commands/bootstrap_templates"
|
||||
require "db/validators/base"
|
||||
|
||||
module Validators
|
||||
class Image::BootstrapTemplate < Base
|
||||
module Image
|
||||
class BootstrapTemplate < Base
|
||||
|
||||
include BootstrapTemplatesCommands
|
||||
include BootstrapTemplatesCommands
|
||||
|
||||
def valid?
|
||||
if @model.bootstrap_template
|
||||
templates = get_templates
|
||||
templates.include?(@model.bootstrap_template)
|
||||
else
|
||||
true
|
||||
def valid?
|
||||
if @model.bootstrap_template
|
||||
templates = get_templates
|
||||
templates.include?(@model.bootstrap_template)
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def message
|
||||
"Invalid bootstrap template '#{@model.bootstrap_template}' for image '#{@model.id}'"
|
||||
def message
|
||||
"Invalid bootstrap template '#{@model.bootstrap_template}' for image '#{@model.id}'"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
module Validators
|
||||
class Key::FileExistence < Base
|
||||
module Key
|
||||
class FileExistence < Base
|
||||
|
||||
delegate_to_helper_validator { Helpers::FileExistence.new(@model.path) }
|
||||
delegate_to_helper_validator { Helpers::FileExistence.new(@model.path) }
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
require "logger"
|
||||
|
||||
class DevopsLogger
|
||||
|
||||
def self.create out, level=Logger::INFO
|
||||
@_logger = Logger.new out
|
||||
@_logger.level = level
|
||||
@_logger.datetime_format = '%a %d-%m-%Y %H%M '
|
||||
@_logger.info("Logger has been created")
|
||||
@_logger
|
||||
end
|
||||
|
||||
def self.logger
|
||||
@_logger
|
||||
end
|
||||
end
|
||||
4
devops-service/exceptions/conflict_exception.rb
Normal file
4
devops-service/exceptions/conflict_exception.rb
Normal file
@ -0,0 +1,4 @@
|
||||
class ConflictException < Exception#StandardError
|
||||
|
||||
end
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Routes
|
||||
module DeployRoutes
|
||||
|
||||
def self.registered(app)
|
||||
|
||||
# Run chef-client 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
|
||||
# "trace": true -> return output in stream
|
||||
# }
|
||||
#
|
||||
# * *Returns* : text stream
|
||||
app.post_with_headers "/deploy", :headers => [:content_type], &Devops::Version2_0::Handler::Deploy.deploy
|
||||
|
||||
puts "Deploy routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,20 +0,0 @@
|
||||
require "commands/bootstrap_templates"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class BootstrapTemplates
|
||||
extend BootstrapTemplatesCommands
|
||||
|
||||
def self.get_bootstrap_templates
|
||||
lambda {
|
||||
check_privileges("templates", "r")
|
||||
# broadcast(:cancel_order_failed, "hello")
|
||||
json BootstrapTemplates.get_templates
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
require "commands/deploy"
|
||||
require "commands/status"
|
||||
require "workers/deploy_worker"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Deploy
|
||||
extend DeployCommands
|
||||
extend StatusCommands
|
||||
|
||||
def self.deploy
|
||||
lambda {
|
||||
check_privileges("server", "x")
|
||||
# TODO: send message
|
||||
#broadcast(:devops_deploy, "deploy")
|
||||
r = create_object_from_json_body
|
||||
names = check_array(r["names"], "Parameter 'names' should be a not empty array of strings")
|
||||
tags = check_array(r["tags"], "Parameter 'tags' should be an array of strings", String, true) || []
|
||||
|
||||
servers = settings.mongo.servers(nil, nil, names, true)
|
||||
halt(404, "No reserved servers found for names '#{names.join("', '")}'") if servers.empty?
|
||||
keys = {}
|
||||
servers.sort_by!{|s| names.index(s.chef_node_name)}
|
||||
if r.key?("trace")
|
||||
stream() do |out|
|
||||
status = []
|
||||
begin
|
||||
servers.each do |s|
|
||||
project = 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
|
||||
res = deploy_server_proc.call(out, s, settings.mongo, tags)
|
||||
status.push(res)
|
||||
end
|
||||
out << create_status(status)
|
||||
rescue IOError => e
|
||||
logger.error e.message
|
||||
break
|
||||
end
|
||||
end # stream
|
||||
else
|
||||
dir = DevopsService.config[: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, tags, request.env['REMOTE_USER'], DevopsService.config)
|
||||
logger.info "Job '#{jid}' has been started"
|
||||
uri.path = "#{DevopsService.config[:url_prefix]}/v2.0/report/" + jid
|
||||
files.push uri.to_s
|
||||
end
|
||||
sleep 1
|
||||
json files
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Filter
|
||||
|
||||
def self.get_filters
|
||||
lambda {
|
||||
check_privileges("filter", "r")
|
||||
check_provider(params[:provider])
|
||||
json settings.mongo.available_images(params[:provider])
|
||||
}
|
||||
end
|
||||
|
||||
def self.add_filter
|
||||
lambda {
|
||||
create_response("Updated", {:images => settings.mongo.add_available_images(@images, params[:provider])})
|
||||
}
|
||||
end
|
||||
|
||||
def self.delete_filter
|
||||
lambda {
|
||||
create_response("Deleted", {:images => settings.mongo.delete_available_images(@images, params[:provider])})
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Flavor
|
||||
def self.get_flavors
|
||||
lambda {
|
||||
check_privileges("flavor", "r")
|
||||
check_provider(params[:provider])
|
||||
p = ::Provider::ProviderFactory.get params[:provider]
|
||||
json p.flavors
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Group
|
||||
def self.get_groups
|
||||
lambda {
|
||||
check_privileges("group", "r")
|
||||
check_provider(params[:provider])
|
||||
p = ::Provider::ProviderFactory.get params[:provider]
|
||||
json p.groups(params)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
require "providers/provider_factory"
|
||||
require "commands/image"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Image
|
||||
|
||||
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})
|
||||
}
|
||||
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])
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_image
|
||||
lambda {
|
||||
check_privileges("image", "r")
|
||||
json settings.mongo.image(params[: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
|
||||
}
|
||||
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")
|
||||
}
|
||||
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(", ")}"
|
||||
end
|
||||
|
||||
r = settings.mongo.image_delete params[:image_id]
|
||||
create_response("Image '#{params[:image_id]}' has been removed")
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,60 +0,0 @@
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Key
|
||||
|
||||
def self.get_keys
|
||||
lambda {
|
||||
check_privileges("key", "r")
|
||||
keys = settings.mongo.keys.map {|i| i.to_hash}
|
||||
keys.each {|k| k.delete("path")} # We should not return path to the key
|
||||
json keys
|
||||
}
|
||||
end
|
||||
|
||||
def self.create_key
|
||||
lambda {
|
||||
check_privileges("key", "w")
|
||||
key = create_object_from_json_body
|
||||
fname = check_filename(key["file_name"], "Parameter 'file_name' must be a not empty string")
|
||||
kname = check_string(key["key_name"], "Parameter 'key_name' should be a not empty string")
|
||||
content = check_string(key["content"], "Parameter 'content' should be a not empty string")
|
||||
file_name = File.join(settings.keys_dir, fname)
|
||||
halt(400, "File '#{fname}' already exist") if File.exists?(file_name)
|
||||
File.open(file_name, "w") do |f|
|
||||
f.write(content)
|
||||
f.chmod(0400)
|
||||
end
|
||||
|
||||
key = Devops::Model::Key.new({"path" => file_name, "id" => kname})
|
||||
settings.mongo.key_insert key
|
||||
create_response("Created", nil, 201)
|
||||
}
|
||||
end
|
||||
|
||||
def self.delete_key
|
||||
lambda {
|
||||
check_privileges("key", "w")
|
||||
servers = settings.mongo.servers_by_key params[:key]
|
||||
unless servers.empty?
|
||||
s_str = servers.map{|s| s.id}.join(", ")
|
||||
raise DependencyError.new "Deleting is forbidden: Key is used in servers: #{s_str}"
|
||||
end
|
||||
|
||||
k = settings.mongo.key params[:key]
|
||||
begin
|
||||
FileUtils.rm(k.path)
|
||||
rescue
|
||||
logger.error "Missing key file for #{params[:key]} - #{k.filename}"
|
||||
end
|
||||
r = settings.mongo.key_delete params[:key]
|
||||
return [500, r["err"].inspect] unless r["err"].nil?
|
||||
create_response("Key '#{params[:key]}' removed")
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Network
|
||||
|
||||
def self.get_networks
|
||||
lambda {
|
||||
check_privileges("network", "r")
|
||||
check_provider(params[:provider])
|
||||
p = ::Provider::ProviderFactory.get params[:provider]
|
||||
json p.networks_detail
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,315 +0,0 @@
|
||||
require "commands/deploy"
|
||||
require "commands/status"
|
||||
require "commands/server"
|
||||
require "db/mongo/models/project"
|
||||
require "workers/project_test_worker"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Project
|
||||
|
||||
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
|
||||
end
|
||||
archived = params.include?("archived")
|
||||
json settings.mongo.projects(nil, nil, fields, archived).map {|p| p.to_hash}
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_project
|
||||
lambda {
|
||||
check_privileges("project", "r")
|
||||
json settings.mongo.project(params[:project])
|
||||
}
|
||||
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}
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_project_stacks
|
||||
lambda {
|
||||
check_privileges("project", "r")
|
||||
settings.mongo.project(params[:project])
|
||||
options = {project: params[:project]}
|
||||
options[:deploy_env] = params[:deploy_env] if params[:deploy_env]
|
||||
json settings.mongo.stacks(options).map{|s| s.to_hash}
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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}'")
|
||||
}
|
||||
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)
|
||||
}
|
||||
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
|
||||
end
|
||||
}
|
||||
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)
|
||||
end
|
||||
}
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
end
|
||||
|
||||
def self.create_roles project_id, envs, logger
|
||||
all_roles = KnifeCommands.roles
|
||||
return " Can't get roles list" if all_roles.nil?
|
||||
roles = {:new => [], :error => [], :exist => []}
|
||||
envs.each do |e|
|
||||
role_name = KnifeCommands.role_name(project_id, e.identifier)
|
||||
begin
|
||||
if all_roles.include? role_name
|
||||
roles[:exist].push role_name
|
||||
else
|
||||
KnifeCommands.create_role role_name, project_id, e.identifier
|
||||
roles[:new].push role_name
|
||||
logger.info "Role '#{role_name}' created"
|
||||
end
|
||||
rescue => er
|
||||
roles[:error].push role_name
|
||||
logger.error "Role '#{role_name}' can not be created: #{er.message}"
|
||||
end
|
||||
end
|
||||
roles
|
||||
end
|
||||
|
||||
def self.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
|
||||
end
|
||||
|
||||
def self.create_roles_response roles
|
||||
if roles.is_a?(String)
|
||||
roles
|
||||
else
|
||||
info = ""
|
||||
info += " Project roles '#{roles[:new].join("', '")}' have been automaticaly created" unless roles[:new].empty?
|
||||
info += " Project roles '#{roles[:exist].join("', '")}' weren't created because they exist" unless roles[:exist].empty?
|
||||
info += " Project roles '#{roles[:error].join("', '")}' weren't created because of internal error" unless roles[:error].empty?
|
||||
info
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Provider
|
||||
def self.get_providers
|
||||
lambda {
|
||||
check_privileges("provider", "r")
|
||||
json ::Provider::ProviderFactory.providers
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,63 +0,0 @@
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Report
|
||||
|
||||
def self.reports_all
|
||||
lambda {
|
||||
options = {}
|
||||
["project", "deploy_env", "type", "created_by", "date_from", "date_to", "sort", "status", "max_number", "chef_node_name"].each do |k|
|
||||
options[k] = params[k] unless params[k].nil?
|
||||
end
|
||||
attributes_keys = params.keys.select{|k| k =~ /attributes\.*/}
|
||||
attributes_keys.each do |ak|
|
||||
options[ak] = params[ak]
|
||||
end
|
||||
json Devops::Db.connector.reports(options).map{|r| r.to_hash}
|
||||
}
|
||||
end
|
||||
|
||||
def self.reports_latest
|
||||
lambda {
|
||||
options = {}
|
||||
["project", "deploy_env", "type", "created_by", "date_from", "date_to", "sort", "status", "chef_node_name"].each do |k|
|
||||
options[k] = params[k] unless params[k].nil?
|
||||
end
|
||||
attributes_keys = params.keys.select{|k| k =~ /attributes\.*/}
|
||||
attributes_keys.each do |ak|
|
||||
options[ak] = params[ak]
|
||||
end
|
||||
json Devops::Db.connector.latest_reports(options).map{|r| r.to_hash}
|
||||
}
|
||||
end
|
||||
|
||||
def self.attributes_all
|
||||
lambda{
|
||||
json Devops::Db.connector.reports_attributes_values(params["name"])
|
||||
}
|
||||
end
|
||||
|
||||
def self.report
|
||||
lambda{
|
||||
begin
|
||||
r = Devops::Db.connector.report(params[:id])
|
||||
file = r.file
|
||||
return [404, "Report '#{params[:id]}' does not exist"] unless File.exists? file
|
||||
@text = Rack::Utils.escape_html(File.read(file))
|
||||
@done = completed?(params[:id])
|
||||
rescue RecordNotFound => e
|
||||
if task_status(params[:id]) == Worker::STATUS::IN_QUEUE
|
||||
@text = "Task '#{params[:id]}' has been queued"
|
||||
@done = false
|
||||
else
|
||||
raise e
|
||||
end
|
||||
end
|
||||
erb :index
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,127 +0,0 @@
|
||||
require "providers/provider_factory"
|
||||
require "fileutils"
|
||||
require "commands/status"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Script
|
||||
|
||||
def self.get_scripts
|
||||
lambda {
|
||||
check_privileges("script", "r")
|
||||
res = []
|
||||
Dir.foreach(DevopsService.config[:scripts_dir]) {|f| res.push(f) unless f.start_with?(".")}
|
||||
json res
|
||||
}
|
||||
end
|
||||
|
||||
def self.execute_command
|
||||
lambda {
|
||||
check_privileges("script", "x")
|
||||
user = request.env['REMOTE_USER']
|
||||
s = ::Devops::Db.connector.server_by_chef_node_name params[:node_name]
|
||||
::Devops::Db.connector.check_project_auth s.project, s.deploy_env, user
|
||||
cert = ::Devops::Db.connector.key s.key
|
||||
cmd = request.body.read
|
||||
addr = "#{s.remote_user}@#{s.public_ip || s.private_ip}"
|
||||
ssh_cmd = "ssh -i %s #{addr} '#{cmd}'"
|
||||
stream() do |out|
|
||||
begin
|
||||
out << ssh_cmd % File.basename(cert.path)
|
||||
out << "\n"
|
||||
IO.popen((ssh_cmd % cert.path) + " 2>&1") do |so|
|
||||
while line = so.gets do
|
||||
out << line
|
||||
end
|
||||
end
|
||||
out << "\nDone"
|
||||
rescue IOError => e
|
||||
logger.error e.message
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def self.run_script
|
||||
lambda {
|
||||
check_privileges("script", "x")
|
||||
file_name = params[:script_name]
|
||||
@file = File.join(DevopsService.config[:scripts_dir], check_filename(file_name, "Parameter 'script_name' must be a not empty string", false))
|
||||
halt(404, "File '#{file_name}' does not exist") unless File.exists?(@file)
|
||||
body = create_object_from_json_body
|
||||
nodes = check_array(body["nodes"], "Parameter 'nodes' must be a not empty array of strings")
|
||||
p = check_array(body["params"], "Parameter 'params' should be a not empty array of strings", String, true)
|
||||
servers = ::Devops::Db.connector.servers_by_names(nodes)
|
||||
return [404, "No servers found for names '#{nodes.join("', '")}'"] if servers.empty?
|
||||
user = request.env['REMOTE_USER']
|
||||
servers.each do |s|
|
||||
::Devops::Db.connector.check_project_auth s.project, s.deploy_env, user
|
||||
end
|
||||
stream() do |out|
|
||||
begin
|
||||
status = []
|
||||
servers.each do |s|
|
||||
cert = begin
|
||||
::Devops::Db.connector.key s.key
|
||||
rescue
|
||||
out << "No key found for '#{s.chef_node_name}'"
|
||||
status.push 2
|
||||
next
|
||||
end
|
||||
ssh_cmd = "ssh -i #{cert.path} #{s.remote_user}@#{s.public_ip || s.private_ip} 'bash -s' < %s"
|
||||
out << "\nRun script on '#{s.chef_node_name}'\n"
|
||||
unless p.nil?
|
||||
ssh_cmd += " " + p.join(" ")
|
||||
end
|
||||
out << (ssh_cmd % [params[:script_name]])
|
||||
out << "\n"
|
||||
|
||||
begin
|
||||
IO.popen( (ssh_cmd % [@file]) + " 2>&1") do |so|
|
||||
while line = so.gets do
|
||||
out << line
|
||||
end
|
||||
so.close
|
||||
status.push $?.to_i
|
||||
end
|
||||
rescue IOError => e
|
||||
logger.error e.message
|
||||
out << e.message
|
||||
status.push 3
|
||||
end
|
||||
end
|
||||
out << create_status(status)
|
||||
rescue IOError => e
|
||||
logger.error e.message
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def self.create_script
|
||||
lambda {
|
||||
check_privileges("script", "w")
|
||||
file_name = params[:script_name]
|
||||
file = File.join(settings.scripts_dir, check_filename(file_name, "Parameter 'script_name' must be a not empty string"))
|
||||
halt_response("File '#{file_name}' already exist") if File.exists?(file)
|
||||
File.open(file, "w") {|f| f.write(request.body.read)}
|
||||
create_response("File '#{params[:script_name]}' created", nil, 201)
|
||||
}
|
||||
end
|
||||
|
||||
def self.delete_script
|
||||
lambda {
|
||||
check_privileges("script", "w")
|
||||
file_name = params[:script_name]
|
||||
file = File.join(settings.scripts_dir, check_filename(file_name, "Parameter 'script_name' must be a not empty string"))
|
||||
halt_response("File '#{file_name}' does not exist", 404) unless File.exists?(file)
|
||||
FileUtils.rm(file)
|
||||
create_response("File '#{params[:script_name]}' deleted")
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,349 +0,0 @@
|
||||
require 'rufus-scheduler'
|
||||
require "uri"
|
||||
|
||||
require "commands/status"
|
||||
require "commands/server"
|
||||
require "commands/bootstrap_templates"
|
||||
require "commands/knife_commands"
|
||||
|
||||
require "providers/provider_factory"
|
||||
|
||||
require "db/mongo/models/server"
|
||||
|
||||
require "workers/create_server_worker"
|
||||
require "workers/bootstrap_worker"
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Server
|
||||
|
||||
extend StatusCommands
|
||||
extend ServerCommands
|
||||
extend BootstrapTemplatesCommands
|
||||
|
||||
scheduler = Rufus::Scheduler.new
|
||||
|
||||
def self.get_servers
|
||||
lambda {
|
||||
check_privileges("server", "r")
|
||||
fields = []
|
||||
if params.key?("fields") and params["fields"].is_a?(Array)
|
||||
Devops::Model::Server.fields.each do |k|
|
||||
fields.push k if params["fields"].include?(k)
|
||||
end
|
||||
end
|
||||
reserved = (params.key?("reserved") ? true : nil)
|
||||
json settings.mongo.servers(nil, nil, nil, reserved, fields).map {|s| s.to_hash}
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_chef_servers
|
||||
lambda {
|
||||
check_privileges("server", "r")
|
||||
json KnifeCommands.chef_node_list
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_provider_servers
|
||||
lambda {
|
||||
check_privileges("server", "r")
|
||||
json ::Provider::ProviderFactory.get(params[:provider]).servers
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_server
|
||||
lambda {
|
||||
check_privileges("server", "r")
|
||||
json Server.get_server_by_key(params[:name], params[:key]).to_hash
|
||||
}
|
||||
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)
|
||||
}
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
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")
|
||||
}
|
||||
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")
|
||||
}
|
||||
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
|
||||
}
|
||||
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")
|
||||
}
|
||||
end
|
||||
|
||||
def self.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
|
||||
mongo = Devops::Db.connector
|
||||
mongo.server_by_chef_node_name name
|
||||
halt(400, "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 = KnifeCommands.chef_node_list.detect {|n| n == name}
|
||||
halt(400, "Chef node with name '#{name}' already exist") unless s.nil?
|
||||
s = KnifeCommands.chef_client_list.detect {|c| c == name}
|
||||
halt(400, "Chef client with name '#{name}' already exist") unless s.nil?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class ExpireHandler
|
||||
include ServerCommands
|
||||
|
||||
def initialize server, logger
|
||||
@server = server
|
||||
@logger = logger
|
||||
end
|
||||
|
||||
def call(job)
|
||||
@logger.info("Removing node '#{@server.chef_node_name}' form project '#{@server.project}' and env '#{@server.deploy_env}'")
|
||||
begin
|
||||
delete_server(@server, Devops::Db.connector, @logger)
|
||||
rescue => e
|
||||
logger.error "ExpiredHandler error: " + e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,88 +0,0 @@
|
||||
require 'db/mongo/models/stack/stack_factory'
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class Stack
|
||||
|
||||
def self.get_stacks
|
||||
lambda {
|
||||
check_privileges("stack", "r")
|
||||
stacks = settings.mongo.stacks
|
||||
json stacks.map(&:to_hash)
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_stacks_for_provider
|
||||
lambda {
|
||||
check_privileges("stack", "r")
|
||||
check_provider(params[:provider])
|
||||
stacks = settings.mongo.stacks(provider: params[:provider])
|
||||
json stacks.map(&:to_hash)
|
||||
}
|
||||
end
|
||||
|
||||
def self.create_stack
|
||||
lambda {
|
||||
check_privileges("stack", "w")
|
||||
|
||||
object = create_object_from_json_body
|
||||
stack_model = Model::StackFactory.create(object['provider'], object)
|
||||
settings.mongo.stack_insert(stack_model)
|
||||
|
||||
create_response "Created", stack_model.to_hash, 201
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_stack
|
||||
lambda {
|
||||
check_privileges("stack", "r")
|
||||
stack = settings.mongo.stack(params[:stack_id])
|
||||
json stack.to_hash
|
||||
}
|
||||
end
|
||||
|
||||
def self.delete_stack
|
||||
lambda {
|
||||
check_privileges("stack", "w")
|
||||
|
||||
stack = settings.mongo.stack(params[:stack_id])
|
||||
stack.delete_stack_in_cloud!
|
||||
settings.mongo.stack_delete(params[:stack_id])
|
||||
|
||||
create_response("Stack '#{params[:stack_id]}' has been removed")
|
||||
}
|
||||
end
|
||||
|
||||
def self.sync_details
|
||||
lambda {
|
||||
check_privileges("stack", "w")
|
||||
|
||||
stack = settings.mongo.stack(params[:stack_id])
|
||||
stack.sync_details!
|
||||
settings.mongo.stack_update(stack)
|
||||
|
||||
json stack.to_hash
|
||||
}
|
||||
end
|
||||
|
||||
def self.resources
|
||||
lambda {
|
||||
check_privileges("stack", "r")
|
||||
stack = settings.mongo.stack(params[:stack_id])
|
||||
json stack.resources
|
||||
}
|
||||
end
|
||||
|
||||
def self.resource
|
||||
lambda {
|
||||
check_privileges("stack", "r")
|
||||
stack = settings.mongo.stack(params[:stack_id])
|
||||
json stack.resource(params[:resource_id])
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,51 +0,0 @@
|
||||
require 'json'
|
||||
require 'lib/stack_presets/factory'
|
||||
require 'workers/stack_sync_worker'
|
||||
require 'workers/job_starter'
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class StackPreset
|
||||
|
||||
def self.get_presets
|
||||
lambda {
|
||||
# check_privileges("stack_presets", "r")
|
||||
json Devops::StackPresetsFactory.list.map(&:to_hash)
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_preset
|
||||
lambda {
|
||||
# check_privileges("stack_presets", "r")
|
||||
json Devops::StackPresetsFactory.get(params['id']).to_hash
|
||||
}
|
||||
end
|
||||
|
||||
def self.apply
|
||||
lambda {
|
||||
# check_privileges("stack_presets", "r")
|
||||
check_privileges('stack_template', 'w')
|
||||
|
||||
attrs = create_object_from_json_body
|
||||
preset = Devops::StackPresetsFactory.get(attrs.fetch('id'))
|
||||
stack = preset.create_stack_from_preset(attrs)
|
||||
settings.mongo.stack_insert(stack)
|
||||
|
||||
file = JobStarter.start_job(:worker, :sync_stack_till_not_in_progress,
|
||||
provider: stack.provider,
|
||||
stack_id: stack.id,
|
||||
request: request
|
||||
)
|
||||
|
||||
puts "Syncing report is located here: #{file}"
|
||||
|
||||
create_response 'Created', stack.to_hash, 201
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
require 'db/mongo/models/stack_template/stack_template_factory'
|
||||
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Handler
|
||||
class StackTemplate
|
||||
|
||||
def self.get_stack_templates
|
||||
lambda {
|
||||
check_privileges('stack_template', 'r')
|
||||
stack_templates = settings.mongo.stack_templates
|
||||
json stack_templates.map(&:to_hash)
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_stack_templates_for_provider
|
||||
lambda {
|
||||
check_privileges('stack_template', 'r')
|
||||
check_provider(params[:provider])
|
||||
stack_templates = settings.mongo.stack_templates(params[:provider])
|
||||
json stack_templates.map(&:to_hash)
|
||||
}
|
||||
end
|
||||
|
||||
def self.create_stack_template
|
||||
lambda {
|
||||
check_privileges('stack_template', 'w')
|
||||
|
||||
attrs = create_object_from_json_body
|
||||
template_model = Model::StackTemplateFactory.create(attrs['provider'], attrs)
|
||||
settings.mongo.stack_template_insert(template_model)
|
||||
|
||||
create_response 'Created', template_model.to_hash, 201
|
||||
}
|
||||
end
|
||||
|
||||
def self.get_stack_template
|
||||
lambda {
|
||||
check_privileges('stack_template', 'r')
|
||||
stack_template = settings.mongo.stack_template(params[:stack_template_id])
|
||||
json stack_template.to_hash
|
||||
}
|
||||
end
|
||||
|
||||
def self.delete_stack_template
|
||||
lambda {
|
||||
check_privileges('stack_template', 'w')
|
||||
|
||||
settings.mongo.stack_template_delete params[:stack_template_id]
|
||||
create_response("Template '#{params[:stack_template_id]}' has been removed")
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user