groups, filters, users, flavors

This commit is contained in:
amartynov 2015-07-16 17:18:55 +03:00
parent afbe4f691f
commit 31f1fd5e2b
58 changed files with 275 additions and 249 deletions

View File

@ -0,0 +1,26 @@
module Devops
module API2_0
module Handler
class Filter
def initialize provider
@provider = provider
end
def available_images
Devops::Db.connector.available_images(@provider)
end
def add_images images
Devops::Db.connector.add_available_images(images, @provider)
end
def delete_images images
Devops::Db.connector.delete_available_images(images, @provider)
end
end
end
end
end

View 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

View File

@ -0,0 +1,15 @@
require "providers/provider_factory"
module Devops
module API2_0
module Handler
class Provider
def providers
::Provider::ProviderFactory.providers
end
end
end
end
end

View 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

View File

@ -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)

View File

@ -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,12 @@ 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#, &Devops::API2_0::Handler::Filter.get_filters
check_privileges("filter", "r")
provider = params[:provider]
check_provider(provider)
json Devops::API2_0::Handler::Filter.new(provider).available_images
end
hash = {}
@ -50,7 +45,15 @@ 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 { #Devops::API2_0::Handler::Filter.add_filter
check_privileges("filter", "w")
provider = params[:provider]
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(provider).add_images(images)})
}
# Delete image ids from filter for :provider
#
@ -65,7 +68,15 @@ 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 {#Devops::API2_0::Handler::Filter.delete_filter
check_privileges("filter", "w")
provider = params[:provider]
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(provider).delete_images(images)})
}
app.multi_routes "/filter/:provider/image", {:headers => [:accept, :content_type]}, hash

View File

@ -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

View File

@ -1,5 +1,4 @@
require "json"
require "db/exceptions/invalid_record"
require "db/mongo/models/key"
require "fileutils"

View File

@ -4,7 +4,7 @@ require "json"
require "providers/provider_factory"
module Devops
module Version2_0
module API2_0
module Routes
module ProviderRoutes
@ -22,7 +22,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.providers
end
puts "Provider routes initialized"
end

View File

@ -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

View File

@ -1,25 +1,31 @@
require "sinatra/base"
require "sinatra/streaming"
require "helpers/version_2"
require "json"
require "fog"
require "auth/devops_auth"
require "db/exceptions/invalid_record"
require "db/exceptions/record_not_found"
require "exceptions/invalid_record"
require "exceptions/record_not_found"
require "exceptions/dependency_error"
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
@ -27,11 +33,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

View File

@ -2,13 +2,15 @@ module Devops
class DevopsApi2Application < Application
def prepare
require "routes/v2.0"
require "routes/v2.0/handlers/provider"
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"
=begin
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"
@ -16,12 +18,12 @@ module Devops
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_template_presets"
require "routes/v2.0/handlers/report"
require_relative "api2/routes/handlers/stack_template_preset"
=end
require 'lib/stubber'
end
@ -42,27 +44,26 @@ module Devops
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_template_preset"
require "routes/v2.0/report"
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/status"
require_relative "api2/routes/bootstrap_templates"
require_relative "api2/routes/stack"
require_relative "api2/routes/stack_template"
require_relative "api2/routes/report"
routes = Devops::Version2_0::Routes.constants.collect{|s| Devops::Version2_0::Routes.const_get(s)}.select {|const| const.class == Module}
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

View File

@ -1,4 +1,4 @@
require "app/sidekiq_web"
require "app/devops-client"
require "app/devops-version"
#require "app/devops-api2"
require "app/devops-api2"

View File

@ -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

View File

@ -1,6 +1,6 @@
require "commands/knife_commands"
require "commands/deploy"
require "db/exceptions/record_not_found"
require "exceptions/record_not_found"
module ServerCommands

View File

@ -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"

View File

@ -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 Devops::Model::User::PRIVILEGES.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)

View File

@ -1,7 +1,6 @@
require "db/exceptions/invalid_record"
require "db/mongo/models/mongo_model"
require "db/validators/image/bootstrap_template.rb"
require "db/validators/image/image_in_filter.rb"
require "db/validators/image/bootstrap_template"
require "db/validators/image/image_in_filter"
module Devops
module Model

View File

@ -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

View File

@ -1,5 +1,5 @@
require "providers/provider_factory"
require "db/exceptions/invalid_record"
require "exceptions/invalid_record"
require "json"
module Devops

View File

@ -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 = {}
[

View File

@ -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

View File

@ -1,32 +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 {
# f = FilterHandler.new(?) #request, params
# f.delete
# create_response("Deleted", {:images => f.delete})# settings.mongo.delete_available_images(@images, params[:provider])})
}
end
end
end
end
end

View File

@ -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

View File

@ -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

View File

@ -1,85 +0,0 @@
require "db/exceptions/invalid_record"
require "db/mongo/models/user"
module Devops
module Version2_0
module Handler
class User
def self.get_users
lambda {
check_privileges("user", "r")
users = Devops::Db.connector.users.map {|i| i.to_hash}
users.each {|u| u.delete("password")}
json users
}
end
def self.create_user
lambda {
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::Db.connector.user_insert Devops::Model::User.new(user)
create_response("Created", nil, 201)
}
end
def self.delete_user
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
r = Devops::Db.connector.user_delete params[:user]
create_response("User '#{params[:user]}' removed")
}
end
def self.change_user_privileges
lambda {
check_privileges("user", "w")
data = create_object_from_json_body
user = Devops::Db.connector.user params[:user]
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) || ""
user.grant(cmd, privileges)
Devops::Db.connector.user_update user
create_response("Updated")
}
end
def self.change_user_email_or_password
lambda {
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")
user = Devops::Db.connector.user u
user.send("#{action}=", p)
Devops::Db.connector.user_update user
create_response("Updated")
}
end
end
end
end
end