sinatra modules
This commit is contained in:
parent
cbf48145cd
commit
79e2811e0c
@ -20,11 +20,6 @@ else
|
||||
end
|
||||
|
||||
config[:devops_dir] = File.join(ENV["HOME"], ".devops") if config[:devops_dir].nil?
|
||||
puts "Devops home: #{config[:devops_dir]}"
|
||||
unless File.exists?(config[:devops_dir])
|
||||
FileUtils.mkdir_p config[:devops_dir]
|
||||
puts "Directory '#{config[:devops_dir]}' has been created"
|
||||
end
|
||||
|
||||
config[:report_dir_v2] = File.expand_path(File.join(config[:devops_dir], "report", "v2")) unless config[:report_dir_v2]
|
||||
[
|
||||
|
||||
@ -21,13 +21,32 @@ require "routes/v2.0/user"
|
||||
class DevopsService < Sinatra::Base
|
||||
|
||||
helpers Sinatra::Streaming
|
||||
helpers Sinatra::Version2_0::Helpers
|
||||
helpers Devops::Version2_0::Helpers
|
||||
|
||||
register Sinatra::Version2_0::Core::ProviderRoutes
|
||||
register Sinatra::Version2_0::Core::UserRoutes
|
||||
register Devops::Version2_0::Core::ProviderRoutes
|
||||
register Devops::Version2_0::Core::BootstrapTemplatesRoutes
|
||||
register Devops::Version2_0::Core::UserRoutes
|
||||
register Devops::Version2_0::Core::FilterRoutes
|
||||
register Devops::Version2_0::Core::FlavorRoutes
|
||||
register Devops::Version2_0::Core::GroupRoutes
|
||||
register Devops::Version2_0::Core::ImageRoutes
|
||||
register Devops::Version2_0::Core::KeyRoutes
|
||||
register Devops::Version2_0::Core::NetworkRoutes
|
||||
register Devops::Version2_0::Core::ProjectRoutes
|
||||
register Devops::Version2_0::Core::ScriptRoutes
|
||||
register Devops::Version2_0::Core::ServerRoutes
|
||||
register Devops::Version2_0::Core::StatusRoutes
|
||||
register Devops::Version2_0::Core::TagRoutes
|
||||
|
||||
def initialize config
|
||||
super()
|
||||
puts "Devops home: #{config[:devops_dir]}"
|
||||
unless File.exists?(config[:devops_dir])
|
||||
FileUtils.mkdir_p config[:devops_dir]
|
||||
puts "Directory '#{config[:devops_dir]}' has been created"
|
||||
end
|
||||
self.class.set :devops_home, config[:devops_dir]
|
||||
|
||||
self.class.set :config, config
|
||||
@@config = config
|
||||
root = File.dirname(__FILE__)
|
||||
@ -57,7 +76,7 @@ class DevopsService < Sinatra::Base
|
||||
|
||||
use Rack::Auth::Basic do |username, password|
|
||||
begin
|
||||
mongo.user_auth(username, password)
|
||||
settings.mongo.user_auth(username, password)
|
||||
true
|
||||
rescue RecordNotFound => e
|
||||
false
|
||||
@ -70,6 +89,7 @@ class DevopsService < Sinatra::Base
|
||||
disable :dump_errors
|
||||
disable :show_exceptions
|
||||
set :logging, Logger::INFO
|
||||
puts "TODO2"
|
||||
end
|
||||
|
||||
configure :development do
|
||||
@ -77,6 +97,7 @@ class DevopsService < Sinatra::Base
|
||||
disable :raise_errors
|
||||
# disable :dump_errors
|
||||
set :show_exceptions, :after_handler
|
||||
puts "TODO1"
|
||||
end
|
||||
|
||||
not_found do
|
||||
|
||||
@ -2,10 +2,9 @@ require "json"
|
||||
require 'sinatra/base'
|
||||
require "sinatra/json"
|
||||
|
||||
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Sinatra
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Helpers
|
||||
|
||||
|
||||
@ -1,35 +1,37 @@
|
||||
require "json"
|
||||
require "routes/v2.0/base_routes"
|
||||
require "providers/provider_factory"
|
||||
require "commands/bootstrap_templates"
|
||||
|
||||
module Version2_0
|
||||
class BootstrapTemplatesRoutes < BaseRoutes
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Core
|
||||
module BootstrapTemplatesRoutes
|
||||
|
||||
include BootstrapTemplatesCommands
|
||||
extend BootstrapTemplatesCommands
|
||||
|
||||
def initialize wrapper
|
||||
super wrapper
|
||||
puts "Bootstrap templates routes initialized"
|
||||
def self.registered(app)
|
||||
|
||||
# Get list of available bootstrap templates
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* : array of strings
|
||||
# [
|
||||
# "omnibus"
|
||||
# ]
|
||||
app.get "/templates" do
|
||||
check_headers :accept
|
||||
check_privileges("templates", "r")
|
||||
json BootstrapTemplatesRoutes.get_templates
|
||||
end
|
||||
|
||||
puts "Bootstrap templates routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# Get list of available bootstrap templates
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* : array of strings
|
||||
# [
|
||||
# "omnibus"
|
||||
# ]
|
||||
get "/templates" do
|
||||
check_headers :accept
|
||||
check_privileges("templates", "r")
|
||||
json get_templates
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -1,84 +1,87 @@
|
||||
require "routes/v2.0/base_routes"
|
||||
|
||||
module Version2_0
|
||||
class FilterRoutes < BaseRoutes
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Core
|
||||
module FilterRoutes
|
||||
|
||||
def initialize wrapper
|
||||
super wrapper
|
||||
puts "Filter routes initialized"
|
||||
def self.registered(app)
|
||||
|
||||
app.before "/filter/:provider/image" do
|
||||
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
|
||||
|
||||
app.after "/filter/:provider/image" do
|
||||
statistic
|
||||
end
|
||||
|
||||
# Get list of images filters for :provider
|
||||
#
|
||||
# Devops can works with images from filters list only
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* : array of strings
|
||||
# - ec2:
|
||||
# [
|
||||
# "ami-83e4bcea"
|
||||
# ]
|
||||
# - openstack:
|
||||
# [
|
||||
# "36dc7618-4178-4e29-be43-286fbfe90f50"
|
||||
# ]
|
||||
app.get "/filter/:provider/images" do
|
||||
check_headers :accept
|
||||
check_privileges("filter", "r")
|
||||
check_provider(params[:provider])
|
||||
json settings.mongo.available_images(params[:provider])
|
||||
end
|
||||
|
||||
# Add image ids to filter for :provider
|
||||
#
|
||||
# * *Request*
|
||||
# - method : PUT
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# [
|
||||
# "image_id"
|
||||
# ] -> array of image ids to add to filter
|
||||
#
|
||||
# * *Returns* : list of images filters for :provider
|
||||
app.put "/filter/:provider/image" do
|
||||
create_response("Updated", {:images => settings.mongo.add_available_images(@images, params[:provider])})
|
||||
end
|
||||
|
||||
# Delete image ids from filter for :provider
|
||||
#
|
||||
# * *Request*
|
||||
# - method : DELETE
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# [
|
||||
# "image_id"
|
||||
# ] -> array of image ids to delete from filter
|
||||
#
|
||||
# * *Returns* : list of images filters for :provider
|
||||
app.delete "/filter/:provider/image" do
|
||||
create_response("Deleted", {:images => settings.mongo.delete_available_images(@images, params[:provider])})
|
||||
end
|
||||
|
||||
puts "Filter routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
before "/filter/:provider/image" do
|
||||
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
|
||||
|
||||
after "/filter/:provider/image" do
|
||||
statistic
|
||||
end
|
||||
|
||||
# Get list of images filters for :provider
|
||||
#
|
||||
# Devops can works with images from filters list only
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* : array of strings
|
||||
# - ec2:
|
||||
# [
|
||||
# "ami-83e4bcea"
|
||||
# ]
|
||||
# - openstack:
|
||||
# [
|
||||
# "36dc7618-4178-4e29-be43-286fbfe90f50"
|
||||
# ]
|
||||
get "/filter/:provider/images" do
|
||||
check_headers :accept
|
||||
check_privileges("filter", "r")
|
||||
check_provider(params[:provider])
|
||||
json BaseRoutes.mongo.available_images(params[:provider])
|
||||
end
|
||||
|
||||
# Add image ids to filter for :provider
|
||||
#
|
||||
# * *Request*
|
||||
# - method : PUT
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# [
|
||||
# "image_id"
|
||||
# ] -> array of image ids to add to filter
|
||||
#
|
||||
# * *Returns* : list of images filters for :provider
|
||||
put "/filter/:provider/image" do
|
||||
create_response("Updated", {:images => BaseRoutes.mongo.add_available_images(@images, params[:provider])})
|
||||
end
|
||||
|
||||
# Delete image ids from filter for :provider
|
||||
#
|
||||
# * *Request*
|
||||
# - method : DELETE
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# [
|
||||
# "image_id"
|
||||
# ] -> array of image ids to delete from filter
|
||||
#
|
||||
# * *Returns* : list of images filters for :provider
|
||||
delete "/filter/:provider/image" do
|
||||
create_response("Deleted", {:images => BaseRoutes.mongo.delete_available_images(@images, params[:provider])})
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,49 +1,52 @@
|
||||
require "json"
|
||||
require "routes/v2.0/base_routes"
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Version2_0
|
||||
class FlavorRoutes < BaseRoutes
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Core
|
||||
module FlavorRoutes
|
||||
|
||||
def initialize wrapper
|
||||
super wrapper
|
||||
puts "Flavor routes initialized"
|
||||
def self.registered(app)
|
||||
|
||||
# Get list of flavors for :provider
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* : array of objects
|
||||
# - ec2:
|
||||
# [
|
||||
# {
|
||||
# "id": "t1.micro",
|
||||
# "cores": 2,
|
||||
# "disk": 0,
|
||||
# "name": "Micro Instance",
|
||||
# "ram": 613
|
||||
# }
|
||||
# ]
|
||||
# - openstack:
|
||||
# [
|
||||
# {
|
||||
# "id": "m1.small",
|
||||
# "v_cpus": 1,
|
||||
# "ram": 2048,
|
||||
# "disk": 20
|
||||
# }
|
||||
# ]
|
||||
app.get "/flavors/:provider" do
|
||||
check_headers :accept
|
||||
check_privileges("flavor", "r")
|
||||
check_provider(params[:provider])
|
||||
p = ::Provider::ProviderFactory.get params[:provider]
|
||||
json p.flavors
|
||||
end
|
||||
|
||||
puts "Flavor routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# Get list of flavors for :provider
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* : array of objects
|
||||
# - ec2:
|
||||
# [
|
||||
# {
|
||||
# "id": "t1.micro",
|
||||
# "cores": 2,
|
||||
# "disk": 0,
|
||||
# "name": "Micro Instance",
|
||||
# "ram": 613
|
||||
# }
|
||||
# ]
|
||||
# - openstack:
|
||||
# [
|
||||
# {
|
||||
# "id": "m1.small",
|
||||
# "v_cpus": 1,
|
||||
# "ram": 2048,
|
||||
# "disk": 20
|
||||
# }
|
||||
# ]
|
||||
get "/flavors/:provider" do
|
||||
check_headers :accept
|
||||
check_privileges("flavor", "r")
|
||||
check_provider(params[:provider])
|
||||
p = ::Provider::ProviderFactory.get params[:provider]
|
||||
json p.flavors
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,61 +1,63 @@
|
||||
# encoding: UTF-8
|
||||
require "json"
|
||||
require "routes/v2.0/base_routes"
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Version2_0
|
||||
class GroupRoutes < BaseRoutes
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Core
|
||||
module GroupRoutes
|
||||
|
||||
def initialize wrapper
|
||||
super wrapper
|
||||
puts "Group routes initialized"
|
||||
def self.registered(app)
|
||||
# Get security groups for :provider
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# - ec2:
|
||||
# {
|
||||
# "default": {
|
||||
# "description": "default group",
|
||||
# "id": "sg-565cf93f",
|
||||
# "rules": [
|
||||
# {
|
||||
# "protocol": "tcp",
|
||||
# "from": 22,
|
||||
# "to": 22,
|
||||
# "cidr": "0.0.0.0/0"
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
# }
|
||||
# - openstack:
|
||||
# {
|
||||
# "default": {
|
||||
# "description": "default",
|
||||
# "rules": [
|
||||
# {
|
||||
# "protocol": null,
|
||||
# "from": null,
|
||||
# "to": null,
|
||||
# "cidr": null
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
# }
|
||||
# TODO: vpc support for ec2
|
||||
app.get "/groups/:provider" do
|
||||
check_headers :accept
|
||||
check_privileges("group", "r")
|
||||
check_provider(params[:provider])
|
||||
p = ::Provider::ProviderFactory.get params[:provider]
|
||||
json p.groups(params)
|
||||
end
|
||||
|
||||
puts "Group routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# Get security groups for :provider
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# - ec2:
|
||||
# {
|
||||
# "default": {
|
||||
# "description": "default group",
|
||||
# "id": "sg-565cf93f",
|
||||
# "rules": [
|
||||
# {
|
||||
# "protocol": "tcp",
|
||||
# "from": 22,
|
||||
# "to": 22,
|
||||
# "cidr": "0.0.0.0/0"
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
# }
|
||||
# - openstack:
|
||||
# {
|
||||
# "default": {
|
||||
# "description": "default",
|
||||
# "rules": [
|
||||
# {
|
||||
# "protocol": null,
|
||||
# "from": null,
|
||||
# "to": null,
|
||||
# "cidr": null
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
# }
|
||||
# TODO: vpc support for ec2
|
||||
get "/groups/:provider" do
|
||||
check_headers :accept
|
||||
check_privileges("group", "r")
|
||||
check_provider(params[:provider])
|
||||
p = ::Provider::ProviderFactory.get params[:provider]
|
||||
json p.groups(params)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,178 +1,180 @@
|
||||
require "providers/provider_factory"
|
||||
require "routes/v2.0/base_routes"
|
||||
require "commands/image"
|
||||
|
||||
module Version2_0
|
||||
class ImageRoutes < BaseRoutes
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Core
|
||||
module ImageRoutes
|
||||
|
||||
include ImageCommands
|
||||
extend ImageCommands
|
||||
|
||||
def initialize wrapper
|
||||
super wrapper
|
||||
puts "Image routes initialized"
|
||||
end
|
||||
def self.registered(app)
|
||||
app.after %r{\A/image(/[\w]+)?\z} do
|
||||
statistic
|
||||
end
|
||||
|
||||
after %r{\A/image(/[\w]+)?\z} do
|
||||
statistic
|
||||
end
|
||||
# Get devops images list
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - parameters:
|
||||
# - provider=ec2|openstack -> return images for provider
|
||||
#
|
||||
# * *Returns* :
|
||||
# [
|
||||
# {
|
||||
# "provider": "openstack",
|
||||
# "name": "centos-6.4-x86_64",
|
||||
# "remote_user": "root",
|
||||
# "bootstrap_template": null,
|
||||
# "id": "36dc7618-4178-4e29-be43-286fbfe90f50"
|
||||
# }
|
||||
# ]
|
||||
app.get "/images" do
|
||||
check_headers :accept
|
||||
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
|
||||
|
||||
# Get devops images list
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - parameters:
|
||||
# - provider=ec2|openstack -> return images for provider
|
||||
#
|
||||
# * *Returns* :
|
||||
# [
|
||||
# {
|
||||
# "provider": "openstack",
|
||||
# "name": "centos-6.4-x86_64",
|
||||
# "remote_user": "root",
|
||||
# "bootstrap_template": null,
|
||||
# "id": "36dc7618-4178-4e29-be43-286fbfe90f50"
|
||||
# }
|
||||
# ]
|
||||
get "/images" do
|
||||
check_headers :accept
|
||||
check_privileges("image", "r")
|
||||
check_provider(params[:provider]) if params[:provider]
|
||||
images = BaseRoutes.mongo.images(params[:provider])
|
||||
json(images.map {|i| i.to_hash})
|
||||
end
|
||||
# Get raw images for :provider
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# - ec2
|
||||
# [
|
||||
# {
|
||||
# "id": "ami-83e4bcea",
|
||||
# "name": "amzn-ami-pv-2013.09.1.x86_64-ebs",
|
||||
# "status": "available"
|
||||
# }
|
||||
# ]
|
||||
# - openstack
|
||||
# [
|
||||
# {
|
||||
# "id": "36dc7618-4178-4e29-be43-286fbfe90f50",
|
||||
# "name": "centos-6.4-x86_64",
|
||||
# "status": "ACTIVE"
|
||||
# }
|
||||
# ]
|
||||
app.get "/images/provider/:provider" do
|
||||
check_headers :accept
|
||||
check_privileges("image", "r")
|
||||
check_provider(params[:provider])
|
||||
json get_images(settings.mongo, params[:provider])
|
||||
end
|
||||
|
||||
# Get raw images for :provider
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# - ec2
|
||||
# [
|
||||
# {
|
||||
# "id": "ami-83e4bcea",
|
||||
# "name": "amzn-ami-pv-2013.09.1.x86_64-ebs",
|
||||
# "status": "available"
|
||||
# }
|
||||
# ]
|
||||
# - openstack
|
||||
# [
|
||||
# {
|
||||
# "id": "36dc7618-4178-4e29-be43-286fbfe90f50",
|
||||
# "name": "centos-6.4-x86_64",
|
||||
# "status": "ACTIVE"
|
||||
# }
|
||||
# ]
|
||||
get "/images/provider/:provider" do
|
||||
check_headers :accept
|
||||
check_privileges("image", "r")
|
||||
check_provider(params[:provider])
|
||||
json get_images(BaseRoutes.mongo, params[:provider])
|
||||
end
|
||||
# Get devops image by id
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# {
|
||||
# "provider": "openstack",
|
||||
# "name": "centos-6.4-x86_64",
|
||||
# "remote_user": "root",
|
||||
# "bootstrap_template": null,
|
||||
# "id": "36dc7618-4178-4e29-be43-286fbfe90f50"
|
||||
# }
|
||||
app.get "/image/:image_id" do
|
||||
check_headers :accept
|
||||
check_privileges("image", "r")
|
||||
json settings.mongo.image(params[:image_id])
|
||||
end
|
||||
|
||||
# Get devops image by id
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# {
|
||||
# "provider": "openstack",
|
||||
# "name": "centos-6.4-x86_64",
|
||||
# "remote_user": "root",
|
||||
# "bootstrap_template": null,
|
||||
# "id": "36dc7618-4178-4e29-be43-286fbfe90f50"
|
||||
# }
|
||||
get "/image/:image_id" do
|
||||
check_headers :accept
|
||||
check_privileges("image", "r")
|
||||
json BaseRoutes.mongo.image(params[:image_id])
|
||||
end
|
||||
# Create devops image
|
||||
#
|
||||
# * *Request*
|
||||
# - method : POST
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# {
|
||||
# "id": "image id",
|
||||
# "provider": "image provider",
|
||||
# "remote_user": "user", -> the ssh username
|
||||
# "bootstrap_template": null, -> specific bootstrap template name or nil
|
||||
# "name": "image name"
|
||||
# }
|
||||
#
|
||||
# * *Returns* :
|
||||
# 201 - Created
|
||||
app.post "/image" do
|
||||
check_headers
|
||||
check_privileges("image", "w")
|
||||
image = create_object_from_json_body
|
||||
settings.mongo.image_insert Image.new(image)
|
||||
create_response "Created", nil, 201
|
||||
end
|
||||
|
||||
# Create devops image
|
||||
#
|
||||
# * *Request*
|
||||
# - method : POST
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# {
|
||||
# "id": "image id",
|
||||
# "provider": "image provider",
|
||||
# "remote_user": "user", -> the ssh username
|
||||
# "bootstrap_template": null, -> specific bootstrap template name or nil
|
||||
# "name": "image name"
|
||||
# }
|
||||
#
|
||||
# * *Returns* :
|
||||
# 201 - Created
|
||||
post "/image" do
|
||||
check_headers
|
||||
check_privileges("image", "w")
|
||||
image = create_object_from_json_body
|
||||
BaseRoutes.mongo.image_insert Image.new(image)
|
||||
create_response "Created", nil, 201
|
||||
end
|
||||
# Update devops image
|
||||
#
|
||||
# * *Request*
|
||||
# - method : PUT
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# {
|
||||
# "id": "image id",
|
||||
# "provider": "image provider",
|
||||
# "remote_user": "user" -> the ssh username
|
||||
# "bootstrap_template": null -> specific bootstrap template name or nil
|
||||
# "name": "image name"
|
||||
# }
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Updated
|
||||
app.put "/image/:image_id" do
|
||||
check_headers
|
||||
check_privileges("image", "w")
|
||||
settings.mongo.image params[:image_id]
|
||||
image = 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
|
||||
|
||||
# Update devops image
|
||||
#
|
||||
# * *Request*
|
||||
# - method : PUT
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# {
|
||||
# "id": "image id",
|
||||
# "provider": "image provider",
|
||||
# "remote_user": "user" -> the ssh username
|
||||
# "bootstrap_template": null -> specific bootstrap template name or nil
|
||||
# "name": "image name"
|
||||
# }
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Updated
|
||||
put "/image/:image_id" do
|
||||
check_headers
|
||||
check_privileges("image", "w")
|
||||
BaseRoutes.mongo.image params[:image_id]
|
||||
image = Image.new(create_object_from_json_body)
|
||||
image.id = params[:image_id]
|
||||
BaseRoutes.mongo.image_update image
|
||||
create_response("Image '#{params[:image_id]}' has been updated")
|
||||
end
|
||||
# Delete devops image
|
||||
#
|
||||
# * *Request*
|
||||
# - method : DELETE
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Deleted
|
||||
app.delete "/image/:image_id" do
|
||||
check_headers
|
||||
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.image == params[:image_id]}.map{|e| "#{p.id}.#{e.identifier}"}
|
||||
end
|
||||
raise DependencyError.new "Deleting is forbidden: Image is used in #{ar.join(", ")}"
|
||||
end
|
||||
|
||||
# Delete devops image
|
||||
#
|
||||
# * *Request*
|
||||
# - method : DELETE
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Deleted
|
||||
delete "/image/:image_id" do
|
||||
check_headers
|
||||
check_privileges("image", "w")
|
||||
projects = BaseRoutes.mongo.projects_by_image params[:image_id]
|
||||
unless projects.empty?
|
||||
ar = []
|
||||
projects.each do |p|
|
||||
ar += p.deploy_envs.select{|e| e.image == params[:image_id]}.map{|e| "#{p.id}.#{e.identifier}"}
|
||||
r = settings.mongo.image_delete params[:image_id]
|
||||
create_response("Image '#{params[:image_id]}' has been removed")
|
||||
end
|
||||
|
||||
puts "Image routes initialized"
|
||||
end
|
||||
raise DependencyError.new "Deleting is forbidden: Image is used in #{ar.join(", ")}"
|
||||
|
||||
end
|
||||
|
||||
r = BaseRoutes.mongo.image_delete params[:image_id]
|
||||
create_response("Image '#{params[:image_id]}' has been removed")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -3,108 +3,111 @@ require "db/exceptions/invalid_record"
|
||||
require "db/mongo/models/key"
|
||||
require "fileutils"
|
||||
|
||||
module Version2_0
|
||||
class KeyRoutes < BaseRoutes
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Core
|
||||
module KeyRoutes
|
||||
|
||||
def initialize wrapper
|
||||
super wrapper
|
||||
puts "Key routes initialized"
|
||||
end
|
||||
def self.registered(app)
|
||||
app.before %r{\A/key(/[\w]+)?\z} do
|
||||
if request.delete?
|
||||
check_headers :accept
|
||||
else
|
||||
check_headers :accept, :content_type
|
||||
end
|
||||
check_privileges("key", "w")
|
||||
end
|
||||
|
||||
app.after %r{\A/key(/[\w]+)?\z} do
|
||||
statistic
|
||||
end
|
||||
|
||||
# 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 "/keys" do
|
||||
check_headers :accept
|
||||
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
|
||||
|
||||
# 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 "/key" do
|
||||
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(DevopsService.config[: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 = Key.new({"path" => file_name, "id" => kname})
|
||||
settings.mongo.key_insert key
|
||||
create_response("Created", nil, 201)
|
||||
end
|
||||
|
||||
# Delete ssh key from devops server
|
||||
#
|
||||
# * *Request*
|
||||
# - method : DELETE
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Deleted
|
||||
app.delete "/key/:key" do
|
||||
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
|
||||
|
||||
puts "Key routes initialized"
|
||||
end
|
||||
|
||||
before %r{\A/key(/[\w]+)?\z} do
|
||||
if request.delete?
|
||||
check_headers :accept
|
||||
else
|
||||
check_headers :accept, :content_type
|
||||
end
|
||||
check_privileges("key", "w")
|
||||
end
|
||||
|
||||
after %r{\A/key(/[\w]+)?\z} do
|
||||
statistic
|
||||
end
|
||||
|
||||
# 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"
|
||||
# }
|
||||
# ]
|
||||
get "/keys" do
|
||||
check_headers :accept
|
||||
check_privileges("key", "r")
|
||||
keys = BaseRoutes.mongo.keys.map {|i| i.to_hash}
|
||||
keys.each {|k| k.delete("path")} # We should not return path to the key
|
||||
json 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
|
||||
post "/key" do
|
||||
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(DevopsService.config[: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 = Key.new({"path" => file_name, "id" => kname})
|
||||
BaseRoutes.mongo.key_insert key
|
||||
create_response("Created", nil, 201)
|
||||
end
|
||||
|
||||
# Delete ssh key from devops server
|
||||
#
|
||||
# * *Request*
|
||||
# - method : DELETE
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Deleted
|
||||
delete "/key/:key" do
|
||||
servers = BaseRoutes.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 = BaseRoutes.mongo.key params[:key]
|
||||
begin
|
||||
FileUtils.rm(k.path)
|
||||
rescue
|
||||
logger.error "Missing key file for #{params[:key]} - #{k.filename}"
|
||||
end
|
||||
r = BaseRoutes.mongo.key_delete params[:key]
|
||||
return [500, r["err"].inspect] unless r["err"].nil?
|
||||
create_response("Key '#{params[:key]}' removed")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,49 +1,51 @@
|
||||
# encoding: UTF-8
|
||||
require "json"
|
||||
require "routes/v2.0/base_routes"
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Version2_0
|
||||
class NetworkRoutes < BaseRoutes
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Core
|
||||
module NetworkRoutes
|
||||
|
||||
def initialize wrapper
|
||||
super wrapper
|
||||
puts "Network routes initialized"
|
||||
def self.registered(app)
|
||||
# Get list of networks for :provider
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* : array of strings
|
||||
# - ec2:
|
||||
# [
|
||||
# {
|
||||
# "cidr": "0.0.0.0/16",
|
||||
# "vpcId": "vpc-1",
|
||||
# "subnetId": "subnet-1",
|
||||
# "name": "subnet-1",
|
||||
# "zone": "us-east-1a"
|
||||
# }
|
||||
# ]
|
||||
# - openstack:
|
||||
# [
|
||||
# {
|
||||
# "cidr": "0.0.0.0/16",
|
||||
# "name": "private",
|
||||
# "id": "b14f8df9-ac27-48e2-8d65-f7ef78dc2654"
|
||||
# }
|
||||
# ]
|
||||
app.get "/networks/:provider" do
|
||||
check_headers :accept
|
||||
check_privileges("network", "r")
|
||||
check_provider(params[:provider])
|
||||
p = ::Provider::ProviderFactory.get params[:provider]
|
||||
json p.networks_detail
|
||||
end
|
||||
|
||||
puts "Network routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# Get list of networks for :provider
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* : array of strings
|
||||
# - ec2:
|
||||
# [
|
||||
# {
|
||||
# "cidr": "0.0.0.0/16",
|
||||
# "vpcId": "vpc-1",
|
||||
# "subnetId": "subnet-1",
|
||||
# "name": "subnet-1",
|
||||
# "zone": "us-east-1a"
|
||||
# }
|
||||
# ]
|
||||
# - openstack:
|
||||
# [
|
||||
# {
|
||||
# "cidr": "0.0.0.0/16",
|
||||
# "name": "private",
|
||||
# "id": "b14f8df9-ac27-48e2-8d65-f7ef78dc2654"
|
||||
# }
|
||||
# ]
|
||||
get "/networks/:provider" do
|
||||
check_headers :accept
|
||||
check_privileges("network", "r")
|
||||
check_provider(params[:provider])
|
||||
p = ::Provider::ProviderFactory.get params[:provider]
|
||||
json p.networks_detail
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,18 +1,14 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'sinatra/base'
|
||||
|
||||
require "json"
|
||||
require "routes/v2.0/base_routes"
|
||||
require "providers/provider_factory"
|
||||
|
||||
module Sinatra
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Core
|
||||
module ProviderRoutes
|
||||
|
||||
def self.registered(app)
|
||||
puts "Provider routes initialized"
|
||||
|
||||
# Get devops providers
|
||||
#
|
||||
@ -31,6 +27,8 @@ module Sinatra
|
||||
check_privileges("provider", "r")
|
||||
json ::Provider::ProviderFactory.providers
|
||||
end
|
||||
|
||||
puts "Provider routes initialized"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,181 +1,184 @@
|
||||
require "providers/provider_factory"
|
||||
require "routes/v2.0/base_routes"
|
||||
require "fileutils"
|
||||
require "commands/status"
|
||||
|
||||
module Version2_0
|
||||
class ScriptRoutes < BaseRoutes
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Core
|
||||
module ScriptRoutes
|
||||
|
||||
include StatusCommands
|
||||
extend StatusCommands
|
||||
|
||||
def initialize wrapper
|
||||
super wrapper
|
||||
puts "Script routes initialized"
|
||||
end
|
||||
|
||||
before "/script/:script_name" do
|
||||
check_headers :accept
|
||||
check_privileges("script", "w")
|
||||
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"))
|
||||
if request.put?
|
||||
halt_response("File '#{file_name}' already exist") if File.exists?(@file)
|
||||
elsif request.delete?
|
||||
halt_response("File '#{file_name}' does not exist", 404) unless File.exists?(@file)
|
||||
end
|
||||
end
|
||||
|
||||
after %r{\A/script/((command|run)/)?[\w]+\z} do
|
||||
statistic
|
||||
end
|
||||
|
||||
# Get scripts names
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# [
|
||||
# "script_1"
|
||||
# ]
|
||||
get "/scripts" do
|
||||
check_headers :accept
|
||||
check_privileges("script", "r")
|
||||
res = []
|
||||
Dir.foreach(DevopsService.config[:scripts_dir]) {|f| res.push(f) unless f.start_with?(".")}
|
||||
json res
|
||||
end
|
||||
|
||||
# Run command on node :node_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : POST
|
||||
# - body :
|
||||
# command to run
|
||||
#
|
||||
# * *Returns* : text stream
|
||||
post "/script/command/:node_name" do
|
||||
check_privileges("script", "x")
|
||||
user = request.env['REMOTE_USER']
|
||||
s = BaseRoutes.mongo.server_by_chef_node_name params[:node_name]
|
||||
BaseRoutes.mongo.check_project_auth s.project, s.deploy_env, user
|
||||
cert = BaseRoutes.mongo.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
|
||||
def self.registered(app)
|
||||
app.before "/script/:script_name" do
|
||||
check_headers :accept
|
||||
check_privileges("script", "w")
|
||||
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"))
|
||||
if request.put?
|
||||
halt_response("File '#{file_name}' already exist") if File.exists?(@file)
|
||||
elsif request.delete?
|
||||
halt_response("File '#{file_name}' does not exist", 404) unless File.exists?(@file)
|
||||
end
|
||||
end
|
||||
out << "\nDone"
|
||||
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
|
||||
post "/script/run/:script_name" do
|
||||
check_headers :content_type
|
||||
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 = BaseRoutes.mongo.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|
|
||||
BaseRoutes.mongo.check_project_auth s.project, s.deploy_env, user
|
||||
end
|
||||
stream() do |out|
|
||||
begin
|
||||
status = []
|
||||
servers.each do |s|
|
||||
cert = begin
|
||||
BaseRoutes.mongo.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"
|
||||
app.after %r{\A/script/((command|run)/)?[\w]+\z} do
|
||||
statistic
|
||||
end
|
||||
|
||||
begin
|
||||
IO.popen( (ssh_cmd % [@file]) + " 2>&1") do |so|
|
||||
while line = so.gets do
|
||||
out << line
|
||||
# Get scripts names
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# [
|
||||
# "script_1"
|
||||
# ]
|
||||
app.get "/scripts" do
|
||||
check_headers :accept
|
||||
check_privileges("script", "r")
|
||||
res = []
|
||||
Dir.foreach(DevopsService.config[:scripts_dir]) {|f| res.push(f) unless f.start_with?(".")}
|
||||
json res
|
||||
end
|
||||
|
||||
# Run command on node :node_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : POST
|
||||
# - body :
|
||||
# command to run
|
||||
#
|
||||
# * *Returns* : text stream
|
||||
app.post "/script/command/:node_name" do
|
||||
check_privileges("script", "x")
|
||||
user = request.env['REMOTE_USER']
|
||||
s = BaseRoutes.mongo.server_by_chef_node_name params[:node_name]
|
||||
BaseRoutes.mongo.check_project_auth s.project, s.deploy_env, user
|
||||
cert = BaseRoutes.mongo.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
|
||||
so.close
|
||||
status.push $?.to_i
|
||||
out << "\nDone"
|
||||
rescue IOError => e
|
||||
logger.error e.message
|
||||
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
|
||||
|
||||
# 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 "/script/run/:script_name" do
|
||||
check_headers :content_type
|
||||
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 = BaseRoutes.mongo.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|
|
||||
BaseRoutes.mongo.check_project_auth s.project, s.deploy_env, user
|
||||
end
|
||||
stream() do |out|
|
||||
begin
|
||||
status = []
|
||||
servers.each do |s|
|
||||
cert = begin
|
||||
BaseRoutes.mongo.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
|
||||
|
||||
# Create script :script_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : PUT
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - body : script content
|
||||
#
|
||||
# * *Returns* :
|
||||
# 201 - Created
|
||||
app.put "/script/:script_name" do
|
||||
File.open(@file, "w") {|f| f.write(request.body.read)}
|
||||
create_response("File '#{params[:script_name]}' created", nil, 201)
|
||||
end
|
||||
|
||||
# Delete script :script_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : Delete
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Deleted
|
||||
app.delete "/script/:script_name" do
|
||||
FileUtils.rm(@file)
|
||||
create_response("File '#{params[:script_name]}' deleted")
|
||||
end
|
||||
|
||||
puts "Script routes initialized"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# Create script :script_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : PUT
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - body : script content
|
||||
#
|
||||
# * *Returns* :
|
||||
# 201 - Created
|
||||
put "/script/:script_name" do
|
||||
File.open(@file, "w") {|f| f.write(request.body.read)}
|
||||
create_response("File '#{params[:script_name]}' created", nil, 201)
|
||||
end
|
||||
|
||||
# Delete script :script_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : Delete
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200 - Deleted
|
||||
delete "/script/:script_name" do
|
||||
FileUtils.rm(@file)
|
||||
create_response("File '#{params[:script_name]}' deleted")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,21 +1,24 @@
|
||||
require "json"
|
||||
require "routes/v2.0/base_routes"
|
||||
require "sidekiq"
|
||||
|
||||
module Version2_0
|
||||
class StatusRoutes < BaseRoutes
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Core
|
||||
module StatusRoutes
|
||||
|
||||
def initialize wrapper
|
||||
super wrapper
|
||||
puts "Status routes initialized"
|
||||
end
|
||||
def self.registered(app)
|
||||
app.get "/status/:id" do
|
||||
r = Sidekiq.redis do |connection|
|
||||
connection.hget("devops", params[:id])
|
||||
end
|
||||
return [404, "Job with id '#{params[:id]}' not found"] if r.nil?
|
||||
r
|
||||
end
|
||||
|
||||
puts "Status routes initialized"
|
||||
end
|
||||
|
||||
get "/status/:id" do
|
||||
r = Sidekiq.redis do |connection|
|
||||
connection.hget("devops", params[:id])
|
||||
end
|
||||
return [404, "Job with id '#{params[:id]}' not found"] if r.nil?
|
||||
r
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,87 +1,91 @@
|
||||
require "commands/knife_commands"
|
||||
|
||||
module Version2_0
|
||||
class TagRoutes < BaseRoutes
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Core
|
||||
module TagRoutes
|
||||
|
||||
def initialize wrapper
|
||||
super wrapper
|
||||
puts "Tag routes initialized"
|
||||
end
|
||||
def self.registered(app)
|
||||
app.before "/tags/:node_name" do
|
||||
if request.get?
|
||||
check_headers :accept
|
||||
check_privileges("server", "r")
|
||||
else
|
||||
check_headers :accept, :content_type
|
||||
check_privileges("server", "w")
|
||||
@tags = create_object_from_json_body(Array)
|
||||
check_array(@tags, "Request body should be a not empty array of strings")
|
||||
end
|
||||
server = BaseRoutes.mongo.server_by_chef_node_name(params[:node_name])
|
||||
halt_response("No servers found for name '#{params[:node_name]}'", 404) if server.nil?
|
||||
@chef_node_name = server.chef_node_name
|
||||
end
|
||||
|
||||
app.after "/tags/:node_name" do
|
||||
statistic
|
||||
end
|
||||
|
||||
# Get tags list for :node_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# [
|
||||
# "tag_1"
|
||||
# ]
|
||||
app.get "/tags/:node_name" do
|
||||
json(KnifeCommands.tags_list(@chef_node_name))
|
||||
end
|
||||
|
||||
# Set tags list to :node_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : POST
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# [
|
||||
# "tag_1"
|
||||
# ]
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200
|
||||
app.post "/tags/:node_name" do
|
||||
tagsStr = @tags.join(" ")
|
||||
cmd = KnifeCommands.tags_create(@chef_node_name, tagsStr)
|
||||
halt_response("Error: Cannot add tags #{tagsStr} to server #{@chef_node_name}", 500) unless cmd[1]
|
||||
create_response("Set tags for #{@chef_node_name}: #{tagsStr}")
|
||||
end
|
||||
|
||||
# Delete tags from :node_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : DELETE
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# [
|
||||
# "tag_1"
|
||||
# ]
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200
|
||||
app.delete "/tags/:node_name" do
|
||||
tagsStr = @tags.join(" ")
|
||||
cmd = KnifeCommands.tags_delete(@chef_node_name, tagsStr)
|
||||
halt_response("Cannot delete tags #{tagsStr} from server #{@chef_node_name}: #{cmd[0]}", 500) unless cmd[1]
|
||||
create_response("Deleted tags for #{@chef_node_name}: #{tagsStr}")
|
||||
end
|
||||
|
||||
puts "Tag routes initialized"
|
||||
end
|
||||
|
||||
before "/tags/:node_name" do
|
||||
if request.get?
|
||||
check_headers :accept
|
||||
check_privileges("server", "r")
|
||||
else
|
||||
check_headers :accept, :content_type
|
||||
check_privileges("server", "w")
|
||||
@tags = create_object_from_json_body(Array)
|
||||
check_array(@tags, "Request body should be a not empty array of strings")
|
||||
end
|
||||
server = BaseRoutes.mongo.server_by_chef_node_name(params[:node_name])
|
||||
halt_response("No servers found for name '#{params[:node_name]}'", 404) if server.nil?
|
||||
@chef_node_name = server.chef_node_name
|
||||
end
|
||||
|
||||
after "/tags/:node_name" do
|
||||
statistic
|
||||
end
|
||||
|
||||
# Get tags list for :node_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : GET
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
#
|
||||
# * *Returns* :
|
||||
# [
|
||||
# "tag_1"
|
||||
# ]
|
||||
get "/tags/:node_name" do
|
||||
json(KnifeCommands.tags_list(@chef_node_name))
|
||||
end
|
||||
|
||||
# Set tags list to :node_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : POST
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# [
|
||||
# "tag_1"
|
||||
# ]
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200
|
||||
post "/tags/:node_name" do
|
||||
tagsStr = @tags.join(" ")
|
||||
cmd = KnifeCommands.tags_create(@chef_node_name, tagsStr)
|
||||
halt_response("Error: Cannot add tags #{tagsStr} to server #{@chef_node_name}", 500) unless cmd[1]
|
||||
create_response("Set tags for #{@chef_node_name}: #{tagsStr}")
|
||||
end
|
||||
|
||||
# Delete tags from :node_name
|
||||
#
|
||||
# * *Request*
|
||||
# - method : DELETE
|
||||
# - headers :
|
||||
# - Accept: application/json
|
||||
# - Content-Type: application/json
|
||||
# - body :
|
||||
# [
|
||||
# "tag_1"
|
||||
# ]
|
||||
#
|
||||
# * *Returns* :
|
||||
# 200
|
||||
delete "/tags/:node_name" do
|
||||
tagsStr = @tags.join(" ")
|
||||
cmd = KnifeCommands.tags_delete(@chef_node_name, tagsStr)
|
||||
halt_response("Cannot delete tags #{tagsStr} from server #{@chef_node_name}: #{cmd[0]}", 500) unless cmd[1]
|
||||
create_response("Deleted tags for #{@chef_node_name}: #{tagsStr}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
require "db/exceptions/invalid_record"
|
||||
require "db/mongo/models/user"
|
||||
|
||||
module Sinatra
|
||||
module Devops
|
||||
module Version2_0
|
||||
module Core
|
||||
module UserRoutes
|
||||
|
||||
Loading…
Reference in New Issue
Block a user