merged with achuchkalov
This commit is contained in:
parent
a0dd907afc
commit
fa3450e03e
19
devops-service/db/mongo/connectors/base.rb
Normal file
19
devops-service/db/mongo/connectors/base.rb
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
require "db/exceptions/record_not_found"
|
||||||
|
require "db/exceptions/invalid_record"
|
||||||
|
require "exceptions/invalid_command"
|
||||||
|
require "exceptions/invalid_privileges"
|
||||||
|
|
||||||
|
module Connectors
|
||||||
|
class Base
|
||||||
|
# Yes, we can implement connectors without attr_accessor, storing collection directly
|
||||||
|
# in instance variable like
|
||||||
|
# @collection = db.collection('users')
|
||||||
|
#
|
||||||
|
# But with latter approach included modules should know about instance variables of
|
||||||
|
# base classes.
|
||||||
|
# Also, debugging "No method error" is simplier than seeking missing instance var.
|
||||||
|
private
|
||||||
|
|
||||||
|
attr_accessor :collection
|
||||||
|
end
|
||||||
|
end
|
||||||
38
devops-service/db/mongo/connectors/filter.rb
Normal file
38
devops-service/db/mongo/connectors/filter.rb
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
module Connectors
|
||||||
|
class Filter < Base
|
||||||
|
|
||||||
|
def initialize(db)
|
||||||
|
self.collection = db.collection('filters')
|
||||||
|
end
|
||||||
|
|
||||||
|
def available_images provider
|
||||||
|
f = collection.find('type' => 'image', 'provider' => provider).to_a.first
|
||||||
|
return [] if f.nil?
|
||||||
|
f['images']
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_available_images images, provider
|
||||||
|
return unless images.is_a?(Array)
|
||||||
|
f = collection.find('type' => 'image', 'provider' => provider).to_a.first
|
||||||
|
if f.nil?
|
||||||
|
collection.insert('type' => 'image', 'provider' => provider, 'images' => images)
|
||||||
|
return images
|
||||||
|
else
|
||||||
|
f['images'] |= images
|
||||||
|
collection.update({'_id' => f['_id']}, f)
|
||||||
|
return f['images']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_available_images images, provider
|
||||||
|
return unless images.is_a?(Array)
|
||||||
|
f = collection.find('type' => 'image', 'provider' => provider).to_a.first
|
||||||
|
unless f.nil?
|
||||||
|
f['images'] -= images
|
||||||
|
collection.update({'_id' => f['_id']}, f)
|
||||||
|
return f['images']
|
||||||
|
end
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
26
devops-service/db/mongo/connectors/helpers/delete_command.rb
Normal file
26
devops-service/db/mongo/connectors/helpers/delete_command.rb
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
require 'lib/string_helper'
|
||||||
|
|
||||||
|
module Connectors
|
||||||
|
module Helpers
|
||||||
|
module DeleteCommand
|
||||||
|
|
||||||
|
# when included, this module adds method #delete and alias for it.
|
||||||
|
# Alias name depends on base class name.
|
||||||
|
# We need this alias to forward methods from MongoConnector to resources connectors.
|
||||||
|
|
||||||
|
def self.included(base)
|
||||||
|
resource_name = StringHelper.underscore_class(base)
|
||||||
|
method_name = "#{resource_name}_delete".to_sym
|
||||||
|
alias_method method_name, :delete
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete(id, options={})
|
||||||
|
delete_query = {'_id' => id}.merge(options)
|
||||||
|
r = collection.remove(delete_query)
|
||||||
|
raise RecordNotFound.new("'#{id}' not found") if r['n'] == 0
|
||||||
|
r
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
31
devops-service/db/mongo/connectors/helpers/insert_command.rb
Normal file
31
devops-service/db/mongo/connectors/helpers/insert_command.rb
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
require 'lib/string_helper'
|
||||||
|
|
||||||
|
module Connectors
|
||||||
|
module Helpers
|
||||||
|
module InsertCommand
|
||||||
|
|
||||||
|
# when included, this module adds method #insert and alias for it.
|
||||||
|
# Alias name depends on base class name.
|
||||||
|
# We need this alias to forward methods from MongoConnector to resources connectors.
|
||||||
|
|
||||||
|
def self.included(base)
|
||||||
|
resource_name = StringHelper.underscore_class(base)
|
||||||
|
method_name = "#{resource_name}_insert".to_sym
|
||||||
|
alias_method method_name, :insert
|
||||||
|
end
|
||||||
|
|
||||||
|
def insert(record)
|
||||||
|
begin
|
||||||
|
record.validate!
|
||||||
|
collection.insert(record.to_mongo_hash)
|
||||||
|
rescue Mongo::OperationFailure => e
|
||||||
|
if e.message =~ /^11000/
|
||||||
|
resource_name = StringHelper.underscore_class(record.class)
|
||||||
|
raise InvalidRecord.new("Duplicate key error: #{resource_name} with id '#{record.id}'")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
24
devops-service/db/mongo/connectors/helpers/list_command.rb
Normal file
24
devops-service/db/mongo/connectors/helpers/list_command.rb
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
require 'lib/string_helper'
|
||||||
|
|
||||||
|
module Connectors
|
||||||
|
module Helpers
|
||||||
|
module ListCommand
|
||||||
|
|
||||||
|
# when included, this module adds method #list and alias for it.
|
||||||
|
# Alias name depends on base class name.
|
||||||
|
# We need this alias to forward methods from MongoConnector to resources connectors.
|
||||||
|
|
||||||
|
def self.included(base)
|
||||||
|
resource_name = StringHelper.underscore_class(base).to_sym
|
||||||
|
method_name = StringHelper.pluralize(resource_name)
|
||||||
|
alias_method method_name, :list
|
||||||
|
end
|
||||||
|
|
||||||
|
# query options is needed, for example, for fields limiting
|
||||||
|
def list(query={}, query_options={})
|
||||||
|
collection.find(query, query_options).to_a.map {|bson| model_from_bson(bson)}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
25
devops-service/db/mongo/connectors/helpers/show_command.rb
Normal file
25
devops-service/db/mongo/connectors/helpers/show_command.rb
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
require 'lib/string_helper'
|
||||||
|
|
||||||
|
module Connectors
|
||||||
|
module Helpers
|
||||||
|
module ShowCommand
|
||||||
|
|
||||||
|
# when included, this module adds method #show and alias for it.
|
||||||
|
# Alias name depends on base class name.
|
||||||
|
# We need this alias to forward methods from MongoConnector to resources connectors.
|
||||||
|
|
||||||
|
def self.included(base)
|
||||||
|
method_name = StringHelper.underscore_class(base).to_sym
|
||||||
|
alias_method method_name, :show
|
||||||
|
end
|
||||||
|
|
||||||
|
def show(id, options={})
|
||||||
|
query = {'_id' => id}.merge(options)
|
||||||
|
bson = collection.find(query).to_a.first
|
||||||
|
raise RecordNotFound.new("'#{id}' not found") unless bson
|
||||||
|
model_from_bson(bson)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
29
devops-service/db/mongo/connectors/helpers/update_command.rb
Normal file
29
devops-service/db/mongo/connectors/helpers/update_command.rb
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
require 'lib/string_helper'
|
||||||
|
|
||||||
|
module Connectors
|
||||||
|
module Helpers
|
||||||
|
module UpdateCommand
|
||||||
|
|
||||||
|
# when included, this module adds method #update and alias for it.
|
||||||
|
# Alias name depends on base class name.
|
||||||
|
# We need this alias to forward methods from MongoConnector to resources connectors.
|
||||||
|
|
||||||
|
def self.included(base)
|
||||||
|
resource_name = StringHelper.underscore_class(base)
|
||||||
|
method_name = "#{resource_name}_update".to_sym
|
||||||
|
alias_method method_name, :update
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(record)
|
||||||
|
record.validate!
|
||||||
|
collection.update({"_id" => record.id}, record.to_mongo_hash)
|
||||||
|
rescue Mongo::OperationFailure => e
|
||||||
|
if e.message =~ /^11000/
|
||||||
|
resource_name = StringHelper.underscore_class(record.class)
|
||||||
|
raise InvalidRecord.new("Duplicate key error: #{resource_name} with id '#{record.id}'")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
25
devops-service/db/mongo/connectors/image.rb
Normal file
25
devops-service/db/mongo/connectors/image.rb
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
module Connectors
|
||||||
|
class Image < Base
|
||||||
|
include Helpers::InsertCommand,
|
||||||
|
Helpers::ShowCommand,
|
||||||
|
Helpers::ListCommand,
|
||||||
|
Helpers::DeleteCommand,
|
||||||
|
Helpers::UpdateCommand
|
||||||
|
|
||||||
|
def initialize(db)
|
||||||
|
self.collection = db.collection('images')
|
||||||
|
end
|
||||||
|
|
||||||
|
def images(provider=nil)
|
||||||
|
query = (provider.nil? ? {} : {'provider' => provider})
|
||||||
|
list(query)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def model_from_bson(bson)
|
||||||
|
::Image.create_from_bson(bson)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
28
devops-service/db/mongo/connectors/key.rb
Normal file
28
devops-service/db/mongo/connectors/key.rb
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
module Connectors
|
||||||
|
class Key < Base
|
||||||
|
include Helpers::InsertCommand,
|
||||||
|
Helpers::ShowCommand,
|
||||||
|
Helpers::ListCommand,
|
||||||
|
Helpers::DeleteCommand
|
||||||
|
|
||||||
|
def initialize(db)
|
||||||
|
self.collection = db.collection('keys')
|
||||||
|
end
|
||||||
|
|
||||||
|
def key(id, scope=nil)
|
||||||
|
options = scope ? {'scope' => scope} : {}
|
||||||
|
show(id, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def key_delete id
|
||||||
|
delete(id, 'scope' => ::Key::USER)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def model_from_bson(bson)
|
||||||
|
::Key.create_from_bson(bson)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
90
devops-service/db/mongo/connectors/project.rb
Normal file
90
devops-service/db/mongo/connectors/project.rb
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
module Connectors
|
||||||
|
class Project < Base
|
||||||
|
include Helpers::InsertCommand,
|
||||||
|
Helpers::ShowCommand,
|
||||||
|
Helpers::ListCommand,
|
||||||
|
Helpers::DeleteCommand,
|
||||||
|
Helpers::UpdateCommand
|
||||||
|
|
||||||
|
|
||||||
|
def initialize(db)
|
||||||
|
@collection = db.collection('projects')
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_project_exists?(project)
|
||||||
|
self.project(project.id)
|
||||||
|
return true
|
||||||
|
rescue RecordNotFound => e
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
def projects_all
|
||||||
|
list
|
||||||
|
end
|
||||||
|
|
||||||
|
def projects ids=nil, type=nil, fields=[]
|
||||||
|
query = {}
|
||||||
|
query['_id'] = {'$in' => ids} if ids
|
||||||
|
query['type'] = 'multi' if type == :multi
|
||||||
|
list(query, fields: fields)
|
||||||
|
end
|
||||||
|
|
||||||
|
# names - array of project names
|
||||||
|
def project_names_with_envs(names=nil)
|
||||||
|
# db.projects.aggregate({$unwind:"$deploy_envs"}, {$project:{"deploy_envs.identifier":1}}, {$group:{_id:"$_id", envs: {$addToSet: "$deploy_envs.identifier"}}})
|
||||||
|
q = []
|
||||||
|
unless names.nil?
|
||||||
|
q.push({
|
||||||
|
'$match' => {
|
||||||
|
'_id' => {
|
||||||
|
'$in' => names
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
q.push({
|
||||||
|
'$unwind' => '$deploy_envs'
|
||||||
|
})
|
||||||
|
q.push({
|
||||||
|
'$project' => {
|
||||||
|
'deploy_envs.identifier' => 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
q.push({
|
||||||
|
'$group' => {
|
||||||
|
'_id' => '$_id',
|
||||||
|
'envs' => {
|
||||||
|
'$addToSet' => '$deploy_envs.identifier'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
res = @collection.aggregate(q)
|
||||||
|
r = {}
|
||||||
|
res.each do |ar|
|
||||||
|
r[ar['_id']] = ar['envs']
|
||||||
|
end
|
||||||
|
return r
|
||||||
|
end
|
||||||
|
|
||||||
|
def projects_by_image(image)
|
||||||
|
list('deploy_envs.image' => image)
|
||||||
|
end
|
||||||
|
|
||||||
|
def projects_by_user(user)
|
||||||
|
list('deploy_envs.users' => user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_project_auth(project_id, env, user_id)
|
||||||
|
project = show(project_id)
|
||||||
|
raise InvalidPrivileges.new("User '#{user_id}' unauthorized to work with project '#{project_id}'") unless project.check_authorization(user_id, env)
|
||||||
|
project
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def model_from_bson(bson)
|
||||||
|
::Project.create_from_bson(bson)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
48
devops-service/db/mongo/connectors/report.rb
Normal file
48
devops-service/db/mongo/connectors/report.rb
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
require "date"
|
||||||
|
|
||||||
|
module Connectors
|
||||||
|
class Report < Base
|
||||||
|
include Helpers::ShowCommand,
|
||||||
|
Helpers::ListCommand
|
||||||
|
|
||||||
|
def initialize(db)
|
||||||
|
self.collection = db.collection('reports')
|
||||||
|
end
|
||||||
|
|
||||||
|
def save_report r
|
||||||
|
r.created_at = Time.new
|
||||||
|
collection.insert(r.to_mongo_hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
def reports options={}
|
||||||
|
date = {}
|
||||||
|
if options.has_key?("date_from") or options.has_key?("date_to")
|
||||||
|
if options.has_key?("date_from")
|
||||||
|
begin
|
||||||
|
d = Date.parse(options["date_from"])
|
||||||
|
date["$gte"] = d.to_time
|
||||||
|
rescue ArgumentError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if options.has_key?("date_to")
|
||||||
|
begin
|
||||||
|
d = Date.parse(options["date_to"])
|
||||||
|
date["$lt"] = d.to_time
|
||||||
|
rescue ArgumentError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
options.delete("date_from")
|
||||||
|
options.delete("date_to")
|
||||||
|
options["created_at"] = date unless date.empty?
|
||||||
|
end
|
||||||
|
list(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def model_from_bson(bson)
|
||||||
|
::Report.new(bson)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
88
devops-service/db/mongo/connectors/server.rb
Normal file
88
devops-service/db/mongo/connectors/server.rb
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
module Connectors
|
||||||
|
class Server < Base
|
||||||
|
include Helpers::DeleteCommand,
|
||||||
|
Helpers::ListCommand
|
||||||
|
|
||||||
|
|
||||||
|
def initialize(db)
|
||||||
|
self.collection = db.collection('servers')
|
||||||
|
end
|
||||||
|
|
||||||
|
def servers_find(query, fields)
|
||||||
|
query_options = fields.nil? ? {} : {fields: fields}
|
||||||
|
list(query, query_options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def servers(p=nil, env=nil, names=nil, reserved=nil, fields=:all)
|
||||||
|
q = {}
|
||||||
|
q['project'] = p unless p.nil? or p.empty?
|
||||||
|
q['deploy_env'] = env unless env.nil? or env.empty?
|
||||||
|
q['chef_node_name'] = {'$in' => names} unless names.nil? or names.class != Array
|
||||||
|
q['reserved_by'] = {'$ne' => nil} unless reserved.nil?
|
||||||
|
f = nil
|
||||||
|
unless fields == :all
|
||||||
|
f = fields
|
||||||
|
['_id', 'chef_node_name'].each do |k|
|
||||||
|
f.push(k) unless f.include?(k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
servers_find(q, f)
|
||||||
|
end
|
||||||
|
|
||||||
|
def servers_by_names(names)
|
||||||
|
query = {}
|
||||||
|
query['chef_node_name'] = {'$in' => names} unless names.nil? or names.class != Array
|
||||||
|
list(query)
|
||||||
|
end
|
||||||
|
|
||||||
|
def server_by_instance_id(id)
|
||||||
|
find_server('_id' => id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def server_by_chef_node_name(name)
|
||||||
|
find_server('chef_node_name' => name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def servers_by_key(key_name)
|
||||||
|
collection.find('key' => key_name).to_a.map { |bson| model_from_bson(bson) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def server_insert(server)
|
||||||
|
#server.validate!
|
||||||
|
server.created_at = Time.now
|
||||||
|
collection.insert(server.to_mongo_hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
# somewhy servers are not validated in previous version of code. I leave this until I know, why.
|
||||||
|
def server_update(server)
|
||||||
|
collection.update({'_id' => server.id}, server.to_hash_without_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
# somewhy servers are not validated in previous version of code. I leave this until I know, why.
|
||||||
|
def server_set_chef_node_name(server)
|
||||||
|
collection.update({'_id' => server.id}, {'$set' => {'chef_node_name' => server.chef_node_name}})
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def model_from_bson(bson)
|
||||||
|
::Server.create_from_bson(bson)
|
||||||
|
end
|
||||||
|
|
||||||
|
# couldn't be replaced with ShowCommand (_id doesn't neccesary appear in params)
|
||||||
|
def find_server(params)
|
||||||
|
bson = collection.find(params).to_a.first
|
||||||
|
if bson.nil?
|
||||||
|
if params.has_key? "_id"
|
||||||
|
raise RecordNotFound.new("No server by instance id '#{params["_id"]}' found")
|
||||||
|
elsif params.has_key? "chef_node_name"
|
||||||
|
raise RecordNotFound.new("No server by node name '#{params["chef_node_name"]}' found")
|
||||||
|
else
|
||||||
|
raise RecordNotFound.new('Invalid params')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
model_from_bson(bson)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
24
devops-service/db/mongo/connectors/stack.rb
Normal file
24
devops-service/db/mongo/connectors/stack.rb
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
module Connectors
|
||||||
|
class Stack < Base
|
||||||
|
include Helpers::InsertCommand,
|
||||||
|
Helpers::ShowCommand,
|
||||||
|
Helpers::ListCommand,
|
||||||
|
Helpers::DeleteCommand
|
||||||
|
|
||||||
|
def initialize(db)
|
||||||
|
self.collection = db.collection('stacks')
|
||||||
|
end
|
||||||
|
|
||||||
|
def stacks(provider=nil)
|
||||||
|
query = (provider.nil? ? {} : {'provider' => provider})
|
||||||
|
list(query)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def model_from_bson(bson)
|
||||||
|
provider = bson['provider']
|
||||||
|
::StackFactory.get_class(provider).create_from_bson(bson)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
25
devops-service/db/mongo/connectors/stack_template.rb
Normal file
25
devops-service/db/mongo/connectors/stack_template.rb
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
module Connectors
|
||||||
|
class StackTemplate < Base
|
||||||
|
include Helpers::InsertCommand,
|
||||||
|
Helpers::ShowCommand,
|
||||||
|
Helpers::ListCommand,
|
||||||
|
Helpers::DeleteCommand
|
||||||
|
|
||||||
|
def initialize(db)
|
||||||
|
self.collection = db.collection('stack_templates')
|
||||||
|
end
|
||||||
|
|
||||||
|
def stack_templates(provider=nil)
|
||||||
|
query = (provider.nil? ? {} : {'provider' => provider})
|
||||||
|
list(query)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def model_from_bson(bson)
|
||||||
|
provider = bson['provider']
|
||||||
|
::StackTemplateFactory.get_class(provider).create_from_bson(bson)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
14
devops-service/db/mongo/connectors/statictic.rb
Normal file
14
devops-service/db/mongo/connectors/statictic.rb
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
module Connectors
|
||||||
|
class Statistic < Base
|
||||||
|
|
||||||
|
def initialize(db)
|
||||||
|
self.collection = db.collection('statistic')
|
||||||
|
end
|
||||||
|
|
||||||
|
def statistic(user, path, method, body, response_code)
|
||||||
|
collection.insert(user: user, path: path, method: method, body: body, response_code: response_code, date: Time.now)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
57
devops-service/db/mongo/connectors/user.rb
Normal file
57
devops-service/db/mongo/connectors/user.rb
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
module Connectors
|
||||||
|
class User < Base
|
||||||
|
include Helpers::InsertCommand,
|
||||||
|
Helpers::ShowCommand,
|
||||||
|
Helpers::ListCommand,
|
||||||
|
Helpers::DeleteCommand,
|
||||||
|
Helpers::UpdateCommand
|
||||||
|
|
||||||
|
|
||||||
|
def initialize(db)
|
||||||
|
self.collection = db.collection('users')
|
||||||
|
end
|
||||||
|
|
||||||
|
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?
|
||||||
|
end
|
||||||
|
|
||||||
|
def users(ids=nil)
|
||||||
|
query = {}
|
||||||
|
query['_id'] = {'$in' => ids} if ids.is_a?(Array)
|
||||||
|
list(query)
|
||||||
|
end
|
||||||
|
|
||||||
|
def users_names(ids=nil)
|
||||||
|
users = self.users(ids)
|
||||||
|
users.map(&:id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_root_user
|
||||||
|
u = user('root')
|
||||||
|
rescue RecordNotFound => e
|
||||||
|
root = ::User.create_root
|
||||||
|
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)
|
||||||
|
::User.create_from_bson(bson)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@ -1,5 +1,6 @@
|
|||||||
require "db/mongo/models/mongo_model"
|
require "db/mongo/models/mongo_model"
|
||||||
require "db/exceptions/invalid_record"
|
require "db/exceptions/invalid_record"
|
||||||
|
require "providers/provider_factory"
|
||||||
require "commands/deploy_env"
|
require "commands/deploy_env"
|
||||||
|
|
||||||
class DeployEnvBase < MongoModel
|
class DeployEnvBase < MongoModel
|
||||||
@ -18,18 +19,6 @@ class DeployEnvBase < MongoModel
|
|||||||
self.users = (b.is_a?(Array) ? b.uniq : b)
|
self.users = (b.is_a?(Array) ? b.uniq : b)
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate!
|
|
||||||
super
|
|
||||||
begin
|
|
||||||
self.class.validators.each do |validator|
|
|
||||||
validator.new(self).validate!
|
|
||||||
end
|
|
||||||
true
|
|
||||||
rescue InvalidRecord => e
|
|
||||||
raise InvalidRecord.new "Deploy environment '#{self.identifier}'. " + e.message
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_hash
|
def to_hash
|
||||||
{
|
{
|
||||||
"identifier" => self.identifier,
|
"identifier" => self.identifier,
|
||||||
@ -44,6 +33,10 @@ class DeployEnvBase < MongoModel
|
|||||||
@provider_instance ||= ::Provider::ProviderFactory.get(self.provider)
|
@provider_instance ||= ::Provider::ProviderFactory.get(self.provider)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_error_message(message)
|
||||||
|
"Deploy environment '#{self.identifier}'. " + message
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# class methods
|
# class methods
|
||||||
class << self
|
class << self
|
||||||
@ -52,7 +45,7 @@ class DeployEnvBase < MongoModel
|
|||||||
@validators
|
@validators
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_validators(*validators)
|
def set_validators(*validators)
|
||||||
@validators = validators
|
@validators = validators
|
||||||
63
devops-service/db/mongo/models/deploy_env/deploy_env_ec2.rb
Normal file
63
devops-service/db/mongo/models/deploy_env/deploy_env_ec2.rb
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
require "db/mongo/models/deploy_env/deploy_env_base"
|
||||||
|
|
||||||
|
class DeployEnvEc2 < DeployEnvBase
|
||||||
|
|
||||||
|
attr_accessor :flavor, :image, :subnets, :groups
|
||||||
|
|
||||||
|
types :identifier => {:type => String, :empty => false},
|
||||||
|
:image => {:type => String, :empty => false},
|
||||||
|
:flavor => {:type => String, :empty => false},
|
||||||
|
:provider => {:type => String, :empty => false},
|
||||||
|
:expires => {:type => String, :empty => false, :nil => true},
|
||||||
|
:run_list => {:type => Array, :empty => true},
|
||||||
|
:users => {:type => Array, :empty => true},
|
||||||
|
:subnets => {:type => Array, :empty => true},
|
||||||
|
:groups => {:type => Array, :empty => false}
|
||||||
|
|
||||||
|
set_validators ::Validators::DeployEnv::RunList,
|
||||||
|
::Validators::DeployEnv::Expiration,
|
||||||
|
::Validators::DeployEnv::Users,
|
||||||
|
::Validators::DeployEnv::Flavor,
|
||||||
|
::Validators::DeployEnv::Image,
|
||||||
|
::Validators::DeployEnv::SubnetBelongsToProvider,
|
||||||
|
::Validators::DeployEnv::Groups
|
||||||
|
|
||||||
|
def initialize d={}
|
||||||
|
super(d)
|
||||||
|
self.flavor = d["flavor"]
|
||||||
|
self.image = d["image"]
|
||||||
|
b = d["subnets"] || []
|
||||||
|
self.subnets = if b.is_a?(Array)
|
||||||
|
(b.size > 1 ? [ b[0] ] : b)
|
||||||
|
else
|
||||||
|
b
|
||||||
|
end
|
||||||
|
b = d["groups"] || ["default"]
|
||||||
|
self.groups = (b.is_a?(Array) ? b.uniq : b)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_hash
|
||||||
|
h = super
|
||||||
|
h.merge!({
|
||||||
|
"flavor" => self.flavor,
|
||||||
|
"image" => self.image,
|
||||||
|
"subnets" => self.subnets,
|
||||||
|
"groups" => self.groups
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create hash
|
||||||
|
DeployEnvEc2.new(hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def subnets_filter
|
||||||
|
networks = provider_instance.networks
|
||||||
|
|
||||||
|
unless self.subnets.empty?
|
||||||
|
{"vpc-id" => networks.detect{|n| n["name"] == self.subnets[0]}["vpcId"] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@ -1,12 +1,8 @@
|
|||||||
require "db/exceptions/invalid_record"
|
require_relative "deploy_env_static"
|
||||||
require "db/mongo/models/deploy_env_static"
|
require_relative "deploy_env_openstack"
|
||||||
require "db/mongo/models/deploy_env_openstack"
|
require_relative "deploy_env_ec2"
|
||||||
require "db/mongo/models/deploy_env_ec2"
|
|
||||||
require "providers/static"
|
|
||||||
require "providers/openstack"
|
|
||||||
require "providers/ec2"
|
|
||||||
|
|
||||||
class DeployEnv
|
class DeployEnvFactory
|
||||||
|
|
||||||
def self.create hash
|
def self.create hash
|
||||||
c = case(hash["provider"])
|
c = case(hash["provider"])
|
||||||
@ -1,64 +0,0 @@
|
|||||||
require "db/mongo/models/deploy_env_base"
|
|
||||||
require "providers/provider_factory"
|
|
||||||
|
|
||||||
class DeployEnvEc2 < DeployEnvBase
|
|
||||||
|
|
||||||
attr_accessor :flavor, :image, :subnets, :groups
|
|
||||||
|
|
||||||
types :identifier => {:type => String, :empty => false},
|
|
||||||
:image => {:type => String, :empty => false},
|
|
||||||
:flavor => {:type => String, :empty => false},
|
|
||||||
:provider => {:type => String, :empty => false},
|
|
||||||
:expires => {:type => String, :empty => false, :nil => true},
|
|
||||||
:run_list => {:type => Array, :empty => true},
|
|
||||||
:users => {:type => Array, :empty => true},
|
|
||||||
:subnets => {:type => Array, :empty => true},
|
|
||||||
:groups => {:type => Array, :empty => false}
|
|
||||||
|
|
||||||
set_validators ::Validators::DeployEnv::RunList,
|
|
||||||
::Validators::DeployEnv::Expiration,
|
|
||||||
::Validators::DeployEnv::Users,
|
|
||||||
::Validators::DeployEnv::Flavor,
|
|
||||||
::Validators::DeployEnv::Image,
|
|
||||||
::Validators::DeployEnv::SubnetBelongsToProvider,
|
|
||||||
::Validators::DeployEnv::Groups
|
|
||||||
|
|
||||||
def initialize d={}
|
|
||||||
super(d)
|
|
||||||
self.flavor = d["flavor"]
|
|
||||||
self.image = d["image"]
|
|
||||||
b = d["subnets"] || []
|
|
||||||
self.subnets = if b.is_a?(Array)
|
|
||||||
(b.size > 1 ? [ b[0] ] : b)
|
|
||||||
else
|
|
||||||
b
|
|
||||||
end
|
|
||||||
b = d["groups"] || ["default"]
|
|
||||||
self.groups = (b.is_a?(Array) ? b.uniq : b)
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_hash
|
|
||||||
h = super
|
|
||||||
h.merge!({
|
|
||||||
"flavor" => self.flavor,
|
|
||||||
"image" => self.image,
|
|
||||||
"subnets" => self.subnets,
|
|
||||||
"groups" => self.groups
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.create hash
|
|
||||||
DeployEnvEc2.new(hash)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def subnets_filter
|
|
||||||
networks = provider_instance.networks
|
|
||||||
|
|
||||||
unless self.subnets.empty?
|
|
||||||
{"vpc-id" => networks.detect{|n| n["name"] == self.subnets[0]}["vpcId"] }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
@ -1,30 +1,16 @@
|
|||||||
require "db/exceptions/invalid_record"
|
require "db/exceptions/invalid_record"
|
||||||
require "db/mongo/models/mongo_model"
|
require "db/mongo/models/mongo_model"
|
||||||
require "commands/image"
|
|
||||||
require "commands/bootstrap_templates"
|
|
||||||
|
|
||||||
class Image < MongoModel
|
class Image < MongoModel
|
||||||
|
|
||||||
include ImageCommands
|
|
||||||
include BootstrapTemplatesCommands
|
|
||||||
|
|
||||||
attr_accessor :id, :provider, :remote_user, :name, :bootstrap_template
|
attr_accessor :id, :provider, :remote_user, :name, :bootstrap_template
|
||||||
types :id => {:type => String, :empty => false},
|
types :id => {:type => String, :empty => false},
|
||||||
:provider => {:type => String, :empty => false},
|
:provider => {:type => String, :empty => false},
|
||||||
:remote_user => {:type => String, :empty => false},
|
:remote_user => {:type => String, :empty => false},
|
||||||
:name => {:type => String, :empty => true},
|
:name => {:type => String, :empty => true},
|
||||||
:bootstrap_template => {:type => String, :empty => false, :nil => true}
|
:bootstrap_template => {:type => String, :empty => false, :nil => true}
|
||||||
|
set_validators ::Validators::Image::ImageInFilter,
|
||||||
def validate!
|
::Validators::Image::BootstrapTemplate
|
||||||
super
|
|
||||||
images = get_images(DevopsService.mongo, self.provider)
|
|
||||||
raise InvalidRecord.new "Invalid image id '#{self.id}' for provider '#{self.provider}', please check image filters" unless images.map{|i| i["id"]}.include?(self.id)
|
|
||||||
|
|
||||||
if self.bootstrap_template
|
|
||||||
templates = get_templates
|
|
||||||
raise InvalidRecord.new "Invalid bootstrap template '#{self.bootstrap_template}' for image '#{self.id}'" unless templates.include?(self.bootstrap_template)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize p={}
|
def initialize p={}
|
||||||
self.id = p["id"]
|
self.id = p["id"]
|
||||||
|
|||||||
@ -12,6 +12,9 @@ class Key < MongoModel
|
|||||||
:path => {:type => String, :empty => false},
|
:path => {:type => String, :empty => false},
|
||||||
:scope => {:type => String, :empty => false}
|
:scope => {:type => String, :empty => false}
|
||||||
|
|
||||||
|
set_validators ::Validators::Key::FileExistence,
|
||||||
|
::Validators::Key::Scope
|
||||||
|
|
||||||
def initialize p={}
|
def initialize p={}
|
||||||
self.id = p["id"]
|
self.id = p["id"]
|
||||||
self.path = p["path"]
|
self.path = p["path"]
|
||||||
@ -40,11 +43,4 @@ class Key < MongoModel
|
|||||||
o
|
o
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate!
|
|
||||||
super
|
|
||||||
raise InvalidRecord.new "File does not exist" unless File.exist?(self.path)
|
|
||||||
raise InvalidRecord.new "Key parameter 'scope' is invalid" unless [SYSTEM, USER].include?(self.scope)
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -48,6 +48,22 @@ class MongoModel
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def validate!
|
||||||
|
begin
|
||||||
|
self.validate_fields_types
|
||||||
|
self.class.validate_model(self)
|
||||||
|
true
|
||||||
|
rescue InvalidRecord => e
|
||||||
|
error_message = self.build_error_message(e.message)
|
||||||
|
raise InvalidRecord.new(error_message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_error_message(message)
|
||||||
|
# overrided in descendants
|
||||||
|
message
|
||||||
|
end
|
||||||
|
|
||||||
# types - Hash
|
# types - Hash
|
||||||
# key - param name
|
# key - param name
|
||||||
# value - Hash
|
# value - Hash
|
||||||
@ -56,7 +72,7 @@ class MongoModel
|
|||||||
# :nil - can param be nil? (false)
|
# :nil - can param be nil? (false)
|
||||||
# :value_type - type of array element (String)
|
# :value_type - type of array element (String)
|
||||||
def self.types types
|
def self.types types
|
||||||
define_method :validate do
|
define_method :validate_fields_types do
|
||||||
t = types.keys
|
t = types.keys
|
||||||
e = types.keys
|
e = types.keys
|
||||||
n = types.keys
|
n = types.keys
|
||||||
@ -98,8 +114,32 @@ class MongoModel
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate!
|
def self.validators
|
||||||
self.validate
|
@validators || []
|
||||||
|
end
|
||||||
|
|
||||||
|
# all exceptions are handled in @validate! method
|
||||||
|
def self.validate_model(model)
|
||||||
|
validators.each do |validator|
|
||||||
|
validator.new(model).validate!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# private class methods
|
||||||
|
class << self
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_validators(*validators_to_add)
|
||||||
|
@validators ||= []
|
||||||
|
@validators += validators_to_add
|
||||||
|
end
|
||||||
|
|
||||||
|
def unset_validators(*validators_to_remove)
|
||||||
|
@validators ||= []
|
||||||
|
self.validators -= validators_to_remove
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
require "db/exceptions/invalid_record"
|
require "db/exceptions/invalid_record"
|
||||||
require "db/exceptions/record_not_found"
|
require "db/exceptions/record_not_found"
|
||||||
require "db/mongo/models/deploy_env"
|
require "db/mongo/models/deploy_env/deploy_env_factory"
|
||||||
require "db/mongo/models/user"
|
require "db/mongo/models/user"
|
||||||
require "db/mongo/models/deploy_env_multi"
|
require "db/mongo/models/deploy_env/deploy_env_multi"
|
||||||
require "db/mongo/models/mongo_model"
|
require "db/mongo/models/mongo_model"
|
||||||
require "json"
|
require "json"
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ class Project < MongoModel
|
|||||||
self.id = p["name"]
|
self.id = p["name"]
|
||||||
#raise InvalidRecord.new "No deploy envirenments for project #{self.id}" if p["deploy_envs"].nil? or p["deploy_envs"].empty?
|
#raise InvalidRecord.new "No deploy envirenments for project #{self.id}" if p["deploy_envs"].nil? or p["deploy_envs"].empty?
|
||||||
self.type = p["type"]
|
self.type = p["type"]
|
||||||
env_class = ( self.multi? ? DeployEnvMulti : DeployEnv )
|
env_class = ( self.multi? ? DeployEnvMulti : DeployEnvFactory )
|
||||||
unless p["deploy_envs"].nil?
|
unless p["deploy_envs"].nil?
|
||||||
self.deploy_envs = []
|
self.deploy_envs = []
|
||||||
p["deploy_envs"].each do |e|
|
p["deploy_envs"].each do |e|
|
||||||
|
|||||||
52
devops-service/db/mongo/models/stack/stack_base.rb
Normal file
52
devops-service/db/mongo/models/stack/stack_base.rb
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
class StackBase < MongoModel
|
||||||
|
|
||||||
|
attr_accessor :id, :project, :deploy_env, :stack_template, :cloud_stack_id, :provider
|
||||||
|
|
||||||
|
types id: {type: String, empty: false},
|
||||||
|
provider: {type: String, empty: false},
|
||||||
|
project: {type: String, empty: false},
|
||||||
|
deploy_env: {type: String, empty: false},
|
||||||
|
stack_template: {type: String, empty: false},
|
||||||
|
cloud_stack_id: {type: String, empty: false}
|
||||||
|
|
||||||
|
def initialize attrs={}
|
||||||
|
self.id = attrs['id']
|
||||||
|
self.provider = attrs['provider']
|
||||||
|
self.project = attrs['project']
|
||||||
|
self.deploy_env = attrs['deploy_env']
|
||||||
|
self.stack_template = attrs['stack_template']
|
||||||
|
self.cloud_stack_id = attrs['cloud_stack_id']
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_hash_without_id
|
||||||
|
{
|
||||||
|
provider: provider,
|
||||||
|
project: self.project,
|
||||||
|
deploy_env: self.deploy_env,
|
||||||
|
stack_template: self.stack_template,
|
||||||
|
cloud_stack_id: self.cloud_stack_id
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# attrs should include:
|
||||||
|
# - id (String)
|
||||||
|
# - provider (String)
|
||||||
|
# - deploy_env (String)
|
||||||
|
# - stack_template (String)
|
||||||
|
def self.create(attrs)
|
||||||
|
model = new(attrs)
|
||||||
|
model.create_stack_in_cloud!
|
||||||
|
model
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create_from_bson(attrs)
|
||||||
|
attrs['id'] = attrs["_id"]
|
||||||
|
self.new(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_stack_in_cloud!
|
||||||
|
raise 'override me'
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
8
devops-service/db/mongo/models/stack/stack_ec2.rb
Normal file
8
devops-service/db/mongo/models/stack/stack_ec2.rb
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
class StackEc2 < StackBase
|
||||||
|
|
||||||
|
def create_stack_in_cloud!
|
||||||
|
# create stack in AWS
|
||||||
|
self.cloud_stack_id = 'arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83'
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
26
devops-service/db/mongo/models/stack/stack_factory.rb
Normal file
26
devops-service/db/mongo/models/stack/stack_factory.rb
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
require_relative "stack_base"
|
||||||
|
require_relative "stack_openstack"
|
||||||
|
require_relative "stack_ec2"
|
||||||
|
|
||||||
|
class StackFactory
|
||||||
|
|
||||||
|
def self.create(provider, attrs)
|
||||||
|
get_class(provider).create(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create_from_bson(provider, attrs)
|
||||||
|
get_class(provider).create_from_bson(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_class(provider)
|
||||||
|
case provider
|
||||||
|
when ::Provider::Openstack::PROVIDER
|
||||||
|
StackOpenstack
|
||||||
|
when ::Provider::Ec2::PROVIDER
|
||||||
|
StackEc2
|
||||||
|
else
|
||||||
|
raise InvalidRecord.new "Invalid provider: '#{provider}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
10
devops-service/db/mongo/models/stack/stack_openstack.rb
Normal file
10
devops-service/db/mongo/models/stack/stack_openstack.rb
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
class StackOpenstack < StackBase
|
||||||
|
|
||||||
|
def create_stack_in_cloud!
|
||||||
|
provider = ::Provider::ProviderFactory.get('openstack')
|
||||||
|
provider.create_stack(self)
|
||||||
|
# # create stack in Openstack
|
||||||
|
# self.cloud_stack_id = '4c712026-dcd5-4664-90b8-0915494c1332'
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
require 'tempfile'
|
||||||
|
require 'securerandom'
|
||||||
|
|
||||||
|
class StackTemplateBase < MongoModel
|
||||||
|
|
||||||
|
attr_accessor :id, :template_url, :template_json, :provider
|
||||||
|
|
||||||
|
# Few words about template_url:
|
||||||
|
# In Amazon Cloudformation the template file must be stored on an Amazon S3 bucket,
|
||||||
|
# but for Openstack stacks it isn't neccessary (your may use local file).
|
||||||
|
# I decided to enforce template_url strategy using in openstack to reach more common
|
||||||
|
# interface between different providers' stack templates.
|
||||||
|
|
||||||
|
types id: {type: String, empty: false},
|
||||||
|
provider: {type: String, empty: false},
|
||||||
|
template_json: {type: String, empty: false},
|
||||||
|
template_url: {type: String, empty: false}
|
||||||
|
|
||||||
|
def initialize(attrs)
|
||||||
|
self.id = attrs['id']
|
||||||
|
self.template_json = attrs['template_json'].to_s
|
||||||
|
self.template_url = attrs['template_url']
|
||||||
|
self.provider = attrs['provider']
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_hash_without_id
|
||||||
|
{
|
||||||
|
provider: provider,
|
||||||
|
template_json: template_json,
|
||||||
|
template_url: template_url
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# do not forget to destroy template files on template destroying
|
||||||
|
def delete_template_file_from_storage
|
||||||
|
raise 'Override me'
|
||||||
|
end
|
||||||
|
|
||||||
|
# attrs should include:
|
||||||
|
# - id (String)
|
||||||
|
# - provider (String)
|
||||||
|
# - template_json (String)
|
||||||
|
def self.create(attrs)
|
||||||
|
json = attrs['template_json']
|
||||||
|
attrs['template_url'] = generate_template_file_and_upload_to_storage(attrs['id'], json)
|
||||||
|
new(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create_from_bson(attrs)
|
||||||
|
attrs['id'] = attrs["_id"]
|
||||||
|
self.new(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
class << self
|
||||||
|
private
|
||||||
|
|
||||||
|
def generate_template_file_and_upload_to_storage(id, json)
|
||||||
|
tempfile = Tempfile.new('foo')
|
||||||
|
tempfile.write(json)
|
||||||
|
secure_filename = "#{id}-#{SecureRandom.hex}.template"
|
||||||
|
upload_file_to_storage(secure_filename, tempfile.path)
|
||||||
|
ensure
|
||||||
|
tempfile.close
|
||||||
|
tempfile.unlink
|
||||||
|
end
|
||||||
|
|
||||||
|
def upload_file_to_storage(filename, file_path)
|
||||||
|
raise 'Override me'
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
class StackTemplateEc2 < StackTemplateBase
|
||||||
|
|
||||||
|
def delete_template_file_from_storage
|
||||||
|
raise 'Implement me'
|
||||||
|
end
|
||||||
|
|
||||||
|
class << self
|
||||||
|
private
|
||||||
|
|
||||||
|
def upload_file_to_storage(filename, path)
|
||||||
|
"https://s3.amazonaws.com/#{filename}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
require_relative "stack_template_base"
|
||||||
|
require_relative "stack_template_openstack"
|
||||||
|
require_relative "stack_template_ec2"
|
||||||
|
|
||||||
|
class StackTemplateFactory
|
||||||
|
|
||||||
|
def self.create(provider, attrs)
|
||||||
|
get_class(provider).create(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create_from_bson(provider, attrs)
|
||||||
|
get_class(provider).create_from_bson(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_class(provider)
|
||||||
|
case provider
|
||||||
|
when ::Provider::Openstack::PROVIDER
|
||||||
|
StackTemplateOpenstack
|
||||||
|
when ::Provider::Ec2::PROVIDER
|
||||||
|
StackTemplateEc2
|
||||||
|
else
|
||||||
|
raise InvalidRecord.new "Invalid provider: '#{provider}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
class StackTemplateOpenstack < StackTemplateBase
|
||||||
|
|
||||||
|
def delete_template_file_from_storage
|
||||||
|
raise 'Implement me'
|
||||||
|
end
|
||||||
|
|
||||||
|
class << self
|
||||||
|
private
|
||||||
|
|
||||||
|
def upload_file_to_storage(filename, path)
|
||||||
|
"https://openstack_host/v1/my_account/#{filename}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@ -2,8 +2,6 @@ require "db/exceptions/invalid_record"
|
|||||||
require "exceptions/invalid_command"
|
require "exceptions/invalid_command"
|
||||||
require "db/mongo/models/mongo_model"
|
require "db/mongo/models/mongo_model"
|
||||||
|
|
||||||
#require "common/fog"
|
|
||||||
|
|
||||||
class User < MongoModel
|
class User < MongoModel
|
||||||
|
|
||||||
ROOT_USER_NAME = 'root'
|
ROOT_USER_NAME = 'root'
|
||||||
@ -70,28 +68,17 @@ class User < MongoModel
|
|||||||
o
|
o
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def can?(command, privilege)
|
||||||
|
p = self.privileges[command] || []
|
||||||
|
p.include?(privilege)
|
||||||
|
end
|
||||||
|
|
||||||
def check_privilege cmd, priv
|
def check_privilege cmd, priv
|
||||||
p = self.privileges[cmd]
|
p = self.privileges[cmd]
|
||||||
return false if p.nil?
|
return false if p.nil?
|
||||||
return p.include?(priv)
|
return p.include?(priv)
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
|
||||||
def check_privilege_read cmd
|
|
||||||
check_privilege_r_w cmd, "r"
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_privilege_write cmd
|
|
||||||
check_privilege_r_w cmd, "w"
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_privilege_r_w cmd, flag
|
|
||||||
p = self.privileges[cmd]
|
|
||||||
return false if p.nil?
|
|
||||||
return p == flag || p == 'rw'
|
|
||||||
end
|
|
||||||
=end
|
|
||||||
|
|
||||||
def self.create_root
|
def self.create_root
|
||||||
root = User.new({'username' => ROOT_USER_NAME, 'password' => ROOT_PASSWORD})
|
root = User.new({'username' => ROOT_USER_NAME, 'password' => ROOT_PASSWORD})
|
||||||
root.privileges = root.all_privileges
|
root.privileges = root.all_privileges
|
||||||
@ -101,20 +88,25 @@ class User < MongoModel
|
|||||||
|
|
||||||
private
|
private
|
||||||
def privileges_with_value v, options={}
|
def privileges_with_value v, options={}
|
||||||
{
|
privileges = {}
|
||||||
"flavor" => v,
|
[
|
||||||
"group" => v,
|
'flavor',
|
||||||
"image" => v,
|
'group',
|
||||||
"project" => v,
|
'image',
|
||||||
"server" => v,
|
'project',
|
||||||
"key" => v,
|
'server',
|
||||||
"user" => v,
|
'key',
|
||||||
"filter" => v,
|
'user',
|
||||||
"network" => v,
|
'filter',
|
||||||
"provider" => v,
|
'network',
|
||||||
"script" => v,
|
'provider',
|
||||||
"templates" => v
|
'script',
|
||||||
}.merge(options)
|
'templates',
|
||||||
|
'stack_template',
|
||||||
|
'stack'
|
||||||
|
].each { |t| privileges.store(t, value) }
|
||||||
|
|
||||||
|
privileges.merge(options)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,438 +1,77 @@
|
|||||||
require "mongo"
|
require "mongo"
|
||||||
require "date"
|
require "forwardable"
|
||||||
|
|
||||||
require "db/exceptions/record_not_found"
|
require "db/mongo/connectors/base"
|
||||||
require "db/exceptions/invalid_record"
|
Dir["db/mongo/connectors/helpers/*.rb"].each {|file| require file }
|
||||||
require "exceptions/invalid_privileges"
|
Dir["db/mongo/connectors/*.rb"].each {|file| require file }
|
||||||
|
|
||||||
require "db/mongo/models/project"
|
|
||||||
require "db/mongo/models/image"
|
|
||||||
require "db/mongo/models/report"
|
|
||||||
require "db/mongo/models/key"
|
|
||||||
require "db/mongo/models/project"
|
|
||||||
require "db/mongo/models/server"
|
|
||||||
require "db/mongo/models/user"
|
|
||||||
|
|
||||||
include Mongo
|
include Mongo
|
||||||
|
|
||||||
class MongoConnector
|
class MongoConnector
|
||||||
|
extend Forwardable
|
||||||
|
|
||||||
|
delegate(
|
||||||
|
[:images, :image, :image_insert, :image_delete, :image_update] => :images_connector,
|
||||||
|
[:stack_templates, :stack_template, :stack_template_insert, :stack_template_delete] => :stack_templates_connector,
|
||||||
|
[:stacks, :stack, :stack_insert, :stack_delete] => :stacks_connector,
|
||||||
|
[:available_images, :add_available_images, :delete_available_images] => :filters_connector,
|
||||||
|
[:project, :projects_all, :projects, :project_names_with_envs,
|
||||||
|
:projects_by_image, :projects_by_user, :project_insert, :project_update,
|
||||||
|
:project_delete, :is_project_exists?, :check_project_auth] => :projects_connector,
|
||||||
|
[:servers_find, :servers, :servers_by_names, :server_by_instance_id,
|
||||||
|
:server_by_chef_node_name, :servers_by_key, :server_insert,
|
||||||
|
:server_delete, :server_update, :server_set_chef_node_name] => :servers_connector,
|
||||||
|
[:user_auth, :user, :users, :users_names, :user_insert, :user_delete,
|
||||||
|
:user_update, :create_root_user, :check_user_privileges] => :users_connector,
|
||||||
|
[:keys, :key, :key_insert, :key_delete] => :keys_connector,
|
||||||
|
[:save_report, :report, :reports] => :reports_connector,
|
||||||
|
[:statistic] => :statistics_connector
|
||||||
|
)
|
||||||
|
|
||||||
def initialize(db, host, port=27017, user=nil, password=nil)
|
def initialize(db, host, port=27017, user=nil, password=nil)
|
||||||
@mongo_client = MongoClient.new(host, port)
|
@db = MongoClient.new(host, port).db(db)
|
||||||
@db = @mongo_client.db(db)
|
|
||||||
@db.authenticate(user, password) unless user.nil? or password.nil?
|
@db.authenticate(user, password) unless user.nil? or password.nil?
|
||||||
@projects = @db.collection("projects")
|
|
||||||
@images = @db.collection("images")
|
|
||||||
@servers = @db.collection("servers")
|
|
||||||
@filters = @db.collection("filters")
|
|
||||||
@keys = @db.collection("keys")
|
|
||||||
@users = @db.collection("users")
|
|
||||||
@statistic = @db.collection("statistic")
|
|
||||||
@reports = @db.collection("reports")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def images provider=nil
|
private
|
||||||
q = (provider.nil? ? {} : {"provider" => provider})
|
|
||||||
@images.find(q).to_a.map {|bi| Image.create_from_bson bi}
|
def images_connector
|
||||||
|
@image_connector ||= Connectors::Image.new(@db)
|
||||||
end
|
end
|
||||||
|
|
||||||
def image id
|
def stack_templates_connector
|
||||||
i = @images.find(create_query("_id" => id)).to_a[0]
|
@stack_templates_connector ||= Connectors::StackTemplate.new(@db)
|
||||||
raise RecordNotFound.new("Image '#{id}' does not exist") if i.nil?
|
|
||||||
Image.create_from_bson i
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def image_insert image
|
def stacks_connector
|
||||||
image.validate!
|
@stack_connector ||= Connectors::Stack.new(@db)
|
||||||
@images.insert(image.to_mongo_hash)
|
|
||||||
rescue Mongo::OperationFailure => e
|
|
||||||
if e.message =~ /^11000/
|
|
||||||
raise InvalidRecord.new("Duplicate key error: image with id '#{image.id}'")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def image_update image
|
def filters_connector
|
||||||
image.validate!
|
@filter_connector ||= Connectors::Filter.new(@db)
|
||||||
@images.update(create_query({"_id" => image.id}), create_query(image.to_mongo_hash))
|
|
||||||
rescue Mongo::OperationFailure => e
|
|
||||||
if e.message =~ /^11000/
|
|
||||||
raise InvalidRecord.new("Duplicate key error: image with id '#{image.id}'")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def image_delete id
|
def projects_connector
|
||||||
r = @images.remove(create_query("_id" => id))
|
@projects_connector ||= Connectors::Project.new(@db)
|
||||||
raise RecordNotFound.new("Image '#{id}' not found") if r["n"] == 0
|
|
||||||
r
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def available_images provider
|
def servers_connector
|
||||||
f = @filters.find(create_query("type" => "image", "provider" => provider)).to_a[0]
|
@servers_connector ||= Connectors::Server.new(@db)
|
||||||
return [] if f.nil?
|
|
||||||
f["images"]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_available_images images, provider
|
def users_connector
|
||||||
return unless images.is_a?(Array)
|
@users_connector ||= Connectors::User.new(@db)
|
||||||
f = @filters.find(create_query("type" => "image", "provider" => provider)).to_a[0]
|
|
||||||
if f.nil?
|
|
||||||
@filters.insert(create_query({"type" => "image", "provider" => provider, "images" => images}))
|
|
||||||
return images
|
|
||||||
else
|
|
||||||
f["images"] |= images
|
|
||||||
@filters.update({"_id" => f["_id"]}, f)
|
|
||||||
return f["images"]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_available_images images, provider
|
def keys_connector
|
||||||
return unless images.is_a?(Array)
|
@keys_connector ||= Connectors::Key.new(@db)
|
||||||
f = @filters.find(create_query("type" => "image", "provider" => provider)).to_a[0]
|
|
||||||
unless f.nil?
|
|
||||||
f["images"] -= images
|
|
||||||
@filters.update({"_id" => f["_id"]}, f)
|
|
||||||
return f["images"]
|
|
||||||
end
|
|
||||||
[]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_project_exists? project
|
def reports_connector
|
||||||
self.project project.id
|
@reports_connector ||= Connectors::Report.new(@db)
|
||||||
return true
|
|
||||||
rescue RecordNotFound => e
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def project_insert project
|
def statistics_connector
|
||||||
project.validate!
|
@statistics_connector ||= Connectors::Statistic.new(@db)
|
||||||
@projects.insert(create_query(project.to_mongo_hash))
|
|
||||||
rescue Mongo::OperationFailure => e
|
|
||||||
if e.message =~ /^11000/
|
|
||||||
raise InvalidRecord.new("Duplicate key error: project with id '#{project.id}'")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def project name
|
|
||||||
p = @projects.find(create_query("_id" => name)).to_a[0]
|
|
||||||
raise RecordNotFound.new("Project '#{name}' does not exist") if p.nil?
|
|
||||||
Project.create_from_bson p
|
|
||||||
end
|
|
||||||
|
|
||||||
def projects_all
|
|
||||||
p = @projects.find()
|
|
||||||
p.to_a.map {|bp| Project.create_from_bson bp}
|
|
||||||
end
|
|
||||||
|
|
||||||
def projects list=nil, type=nil, fields=[]
|
|
||||||
q = (list.nil? ? {} : {"_id" => {"$in" => list}})
|
|
||||||
case type
|
|
||||||
when :multi
|
|
||||||
q["type"] = "multi"
|
|
||||||
#else
|
|
||||||
# q["type"] = {"$exists" => false}
|
|
||||||
end
|
|
||||||
res = @projects.find(create_query(q), :fields => fields)
|
|
||||||
a = res.to_a
|
|
||||||
a.map {|bp| Project.create_from_bson bp}
|
|
||||||
end
|
|
||||||
|
|
||||||
# names - array of project names
|
|
||||||
def project_names_with_envs names=nil
|
|
||||||
# db.projects.aggregate({$unwind:"$deploy_envs"}, {$project:{"deploy_envs.identifier":1}}, {$group:{_id:"$_id", envs: {$addToSet: "$deploy_envs.identifier"}}})
|
|
||||||
q = []
|
|
||||||
unless names.nil?
|
|
||||||
q.push({
|
|
||||||
"$match" => {
|
|
||||||
"_id" => {
|
|
||||||
"$in" => names
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
end
|
|
||||||
q.push({
|
|
||||||
"$unwind" => "$deploy_envs"
|
|
||||||
})
|
|
||||||
q.push({
|
|
||||||
"$project" => {
|
|
||||||
"deploy_envs.identifier" => 1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
q.push({
|
|
||||||
"$group" => {
|
|
||||||
"_id" => "$_id",
|
|
||||||
"envs" => {
|
|
||||||
"$addToSet" => "$deploy_envs.identifier"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
res = @projects.aggregate(q)
|
|
||||||
r = {}
|
|
||||||
res.each do |ar|
|
|
||||||
r[ar["_id"]] = ar["envs"]
|
|
||||||
end
|
|
||||||
return r
|
|
||||||
end
|
|
||||||
|
|
||||||
def projects_by_image image
|
|
||||||
@projects.find(create_query("deploy_envs.image" => image)).to_a.map {|bp| Project.create_from_bson bp}
|
|
||||||
end
|
|
||||||
|
|
||||||
def projects_by_user user
|
|
||||||
@projects.find(create_query("deploy_envs.users" => user)).to_a.map {|bp| Project.create_from_bson bp}
|
|
||||||
end
|
|
||||||
|
|
||||||
def project_delete name
|
|
||||||
r = @projects.remove(create_query("_id" => name))
|
|
||||||
raise RecordNotFound.new("Project '#{name}' not found") if r["n"] == 0
|
|
||||||
end
|
|
||||||
|
|
||||||
def project_update project
|
|
||||||
project.validate!
|
|
||||||
@projects.update(create_query({"_id" => project.id}), project.to_mongo_hash)
|
|
||||||
rescue Mongo::OperationFailure => e
|
|
||||||
if e.message =~ /^11000/
|
|
||||||
raise InvalidRecord.new("Duplicate key error: project with id '#{project.id}'")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def servers_find q, fields
|
|
||||||
s = if fields.nil?
|
|
||||||
@servers.find(create_query(q))
|
|
||||||
else
|
|
||||||
@servers.find(create_query(q), :fields => fields)
|
|
||||||
end
|
|
||||||
s.to_a.map{|bs| Server.create_from_bson bs}
|
|
||||||
end
|
|
||||||
|
|
||||||
def servers p=nil, env=nil, names=nil, reserved=nil, fields=:all
|
|
||||||
q = {}
|
|
||||||
q["project"] = p unless p.nil? or p.empty?
|
|
||||||
q["deploy_env"] = env unless env.nil? or env.empty?
|
|
||||||
q["chef_node_name"] = {"$in" => names} unless names.nil? or names.class != Array
|
|
||||||
q["reserved_by"] = {"$ne" => nil} unless reserved.nil?
|
|
||||||
f = nil
|
|
||||||
unless fields == :all
|
|
||||||
f = fields
|
|
||||||
["_id", "chef_node_name"].each do |k|
|
|
||||||
f.push(k) unless f.include?(k)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
servers_find(q, f)
|
|
||||||
end
|
|
||||||
|
|
||||||
def servers_by_names names
|
|
||||||
q = {}
|
|
||||||
q["chef_node_name"] = {"$in" => names} unless names.nil? or names.class != Array
|
|
||||||
@servers.find(create_query(q)).to_a.map{|bs| Server.create_from_bson bs}
|
|
||||||
end
|
|
||||||
|
|
||||||
def server_by_instance_id id
|
|
||||||
find_server "_id" => id
|
|
||||||
end
|
|
||||||
|
|
||||||
def server_by_chef_node_name name
|
|
||||||
find_server "chef_node_name" => name
|
|
||||||
end
|
|
||||||
|
|
||||||
def servers_by_key key_name
|
|
||||||
@servers.find(create_query("key" => key_name)).to_a.map {|bs| Server.create_from_bson bs}
|
|
||||||
end
|
|
||||||
|
|
||||||
def server_insert s
|
|
||||||
#s.validate!
|
|
||||||
s.created_at = Time.now
|
|
||||||
@servers.insert(create_query(s.to_mongo_hash))
|
|
||||||
end
|
|
||||||
|
|
||||||
def server_delete id
|
|
||||||
@servers.remove(create_query("_id" => id))
|
|
||||||
end
|
|
||||||
|
|
||||||
def server_update server
|
|
||||||
@servers.update({"_id" => server.id}, server.to_hash_without_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def server_set_chef_node_name server
|
|
||||||
@servers.update({"_id" => server.id}, {"$set" => {"chef_node_name" => server.chef_node_name}})
|
|
||||||
end
|
|
||||||
|
|
||||||
def keys
|
|
||||||
@keys.find(create_query).to_a.map {|bi| Key.create_from_bson bi}
|
|
||||||
end
|
|
||||||
|
|
||||||
def key id, scope=nil
|
|
||||||
q = {
|
|
||||||
"_id" => id
|
|
||||||
}
|
|
||||||
q["scope"] = scope unless scope.nil?
|
|
||||||
k = @keys.find(create_query(q)).to_a[0]
|
|
||||||
raise RecordNotFound.new("Key '#{id}' does not exist") if k.nil?
|
|
||||||
Key.create_from_bson k
|
|
||||||
end
|
|
||||||
|
|
||||||
def key_insert key
|
|
||||||
key.validate!
|
|
||||||
@keys.insert(create_query(key.to_mongo_hash))
|
|
||||||
rescue Mongo::OperationFailure => e
|
|
||||||
if e.message =~ /^11000/
|
|
||||||
raise InvalidRecord.new("Duplicate key error: key with id '#{key.id}'")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def key_delete id
|
|
||||||
r = @keys.remove(create_query("_id" => id, "scope" => Key::USER))
|
|
||||||
raise RecordNotFound.new("Key '#{id}' not found") if r["n"] == 0
|
|
||||||
r
|
|
||||||
end
|
|
||||||
|
|
||||||
def user_auth user, password
|
|
||||||
u = @users.find("_id" => user, "password" => password).to_a[0]
|
|
||||||
raise RecordNotFound.new("Invalid username or password") if u.nil?
|
|
||||||
end
|
|
||||||
|
|
||||||
def user id
|
|
||||||
u = @users.find("_id" => id).to_a[0]
|
|
||||||
raise RecordNotFound.new("User '#{id}' does not exist") if u.nil?
|
|
||||||
User.create_from_bson u
|
|
||||||
end
|
|
||||||
|
|
||||||
def users array=nil
|
|
||||||
q = {}
|
|
||||||
q["_id"] = {"$in" => array} if array.is_a?(Array)
|
|
||||||
@users.find(q).to_a.map {|bi| User.create_from_bson bi}
|
|
||||||
end
|
|
||||||
|
|
||||||
def users_names array=nil
|
|
||||||
q = {}
|
|
||||||
q["_id"] = {"$in" => array} if array.is_a?(Array)
|
|
||||||
@users.find({}, :fields => ["_id"]).to_a.map{|u| u["_id"]}
|
|
||||||
end
|
|
||||||
|
|
||||||
def user_insert user
|
|
||||||
user.validate!
|
|
||||||
@users.insert(user.to_mongo_hash)
|
|
||||||
rescue Mongo::OperationFailure => e
|
|
||||||
if e.message =~ /^11000/
|
|
||||||
raise InvalidRecord.new("Duplicate key error: user with id '#{user.id}'")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def user_delete id
|
|
||||||
r = @users.remove("_id" => id)
|
|
||||||
raise RecordNotFound.new("User '#{id}' not found") if r["n"] == 0
|
|
||||||
r
|
|
||||||
end
|
|
||||||
|
|
||||||
def user_update user
|
|
||||||
user.validate!
|
|
||||||
@users.update({"_id" => user.id}, user.to_mongo_hash)
|
|
||||||
rescue Mongo::OperationFailure => e
|
|
||||||
if e.message =~ /^11000/
|
|
||||||
raise InvalidRecord.new("Duplicate key error: user with id '#{user.id}'")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_root_user
|
|
||||||
begin
|
|
||||||
u = user("root")
|
|
||||||
rescue RecordNotFound => e
|
|
||||||
root = User.create_root
|
|
||||||
@users.insert(root.to_mongo_hash)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_user_privileges id, cmd, priv
|
|
||||||
user = self.user(id)
|
|
||||||
case priv
|
|
||||||
when "r", "w", "x"
|
|
||||||
raise InvalidPrivileges.new("Access denied for '#{user.id}'") unless user.check_privilege cmd, priv
|
|
||||||
else
|
|
||||||
raise InvalidPrivileges.new("Access internal problem with privilege '#{priv}'")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_project_auth project_id, env, user_id
|
|
||||||
p = @projects.find(create_query("_id" => project_id)).to_a[0]
|
|
||||||
raise RecordNotFound.new("Project '#{project_id}' does not exist") if p.nil?
|
|
||||||
project = Project.create_from_bson p
|
|
||||||
raise InvalidPrivileges.new("User '#{user_id}' unauthorized to work with project '#{project_id}'") unless project.check_authorization(user_id, env)
|
|
||||||
project
|
|
||||||
end
|
|
||||||
|
|
||||||
def statistic user, path, method, body, response_code
|
|
||||||
@statistic.insert({:user => user, :path => path, :method => method, :body => body, :response_code => response_code, :date => Time.now})
|
|
||||||
end
|
|
||||||
|
|
||||||
def save_report r
|
|
||||||
r.created_at = Time.new
|
|
||||||
@reports.insert(r.to_mongo_hash)
|
|
||||||
end
|
|
||||||
|
|
||||||
def reports options={}
|
|
||||||
date = {}
|
|
||||||
if options.has_key?("date_from") or options.has_key?("date_to")
|
|
||||||
if options.has_key?("date_from")
|
|
||||||
begin
|
|
||||||
d = Date.parse(options["date_from"])
|
|
||||||
date["$gte"] = d.to_time
|
|
||||||
rescue ArgumentError
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if options.has_key?("date_to")
|
|
||||||
begin
|
|
||||||
d = Date.parse(options["date_to"])
|
|
||||||
date["$lt"] = d.to_time
|
|
||||||
rescue ArgumentError
|
|
||||||
end
|
|
||||||
end
|
|
||||||
options.delete("date_from")
|
|
||||||
options.delete("date_to")
|
|
||||||
options["created_at"] = date unless date.empty?
|
|
||||||
end
|
|
||||||
if options.has_key?("type")
|
|
||||||
begin
|
|
||||||
options["type"] = Integer(options["type"])
|
|
||||||
rescue ArgumentError
|
|
||||||
options.delete("type")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sort = -1
|
|
||||||
if options.has_key?("sort")
|
|
||||||
sort = 1 if options["sort"] == "asc"
|
|
||||||
options.delete("sort")
|
|
||||||
end
|
|
||||||
@reports.find(options).to_a.map{|e| Report.new(e)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def report id
|
|
||||||
r = @reports.find({"_id" => id}).to_a[0]
|
|
||||||
raise RecordNotFound.new("Report '#{id}' does not exist") if r.nil?
|
|
||||||
Report.new(r)
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_report_status id, status
|
|
||||||
@reports.update({"_id" => id}, {"$set" => {"status" => status, "updated_at" => Time.new}})
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def find_server params
|
|
||||||
s = @servers.find(create_query(params)).to_a[0]
|
|
||||||
if s.nil?
|
|
||||||
if params.has_key? "_id"
|
|
||||||
raise RecordNotFound.new("No server by instance id '#{params["_id"]}' found")
|
|
||||||
elsif params.has_key? "chef_node_name"
|
|
||||||
raise RecordNotFound.new("No server by node name '#{params["chef_node_name"]}' found")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Server.create_from_bson s
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_query q={}
|
|
||||||
q
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_query_with_provider provider, q={}
|
|
||||||
q["provider"] = provider
|
|
||||||
q
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,8 +1,16 @@
|
|||||||
module Validators
|
module Validators
|
||||||
class Helpers; end
|
class Helpers; end
|
||||||
class DeployEnv; end
|
class DeployEnv; end
|
||||||
|
class Key; end
|
||||||
|
class Image; end
|
||||||
end
|
end
|
||||||
|
|
||||||
require "db/validators/base"
|
require "db/validators/base"
|
||||||
Dir["db/validators/helpers/*.rb"].each {|file| require file }
|
[
|
||||||
Dir["db/validators/deploy_env/*.rb"].each {|file| require file }
|
'db/validators/helpers/*.rb',
|
||||||
|
'db/validators/deploy_env/*.rb',
|
||||||
|
'db/validators/key/*.rb',
|
||||||
|
'db/validators/image/*.rb'
|
||||||
|
].each do |files_regexp|
|
||||||
|
Dir[files_regexp].each {|file| require file }
|
||||||
|
end
|
||||||
|
|||||||
@ -16,4 +16,25 @@ class Validators::Base
|
|||||||
def message
|
def message
|
||||||
raise 'override me'
|
raise 'override me'
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
class << self
|
||||||
|
private
|
||||||
|
|
||||||
|
# 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 :valid? do
|
||||||
|
self.helper_validator.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
define_method :message do
|
||||||
|
self.helper_validator.message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|||||||
@ -4,17 +4,6 @@
|
|||||||
module Validators
|
module Validators
|
||||||
class DeployEnv::RunList < Base
|
class DeployEnv::RunList < Base
|
||||||
|
|
||||||
def initialize(model)
|
delegate_to_helper_validator { Helpers::RunList.new(@model.run_list) }
|
||||||
super(model)
|
|
||||||
@helper_validator = Helpers::RunList.new(@model.run_list)
|
|
||||||
end
|
|
||||||
|
|
||||||
def valid?
|
|
||||||
@helper_validator.valid?
|
|
||||||
end
|
|
||||||
|
|
||||||
def message
|
|
||||||
@helper_validator.message
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
12
devops-service/db/validators/helpers/file_existence.rb
Normal file
12
devops-service/db/validators/helpers/file_existence.rb
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
module Validators
|
||||||
|
class Helpers::FileExistence < Base
|
||||||
|
|
||||||
|
def valid?
|
||||||
|
File.exist?(@model)
|
||||||
|
end
|
||||||
|
|
||||||
|
def message
|
||||||
|
"File does not exist: '#{@model}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
20
devops-service/db/validators/image/bootstrap_template.rb
Normal file
20
devops-service/db/validators/image/bootstrap_template.rb
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
require "commands/bootstrap_templates"
|
||||||
|
module Validators
|
||||||
|
class Image::BootstrapTemplate < Base
|
||||||
|
|
||||||
|
include BootstrapTemplatesCommands
|
||||||
|
|
||||||
|
def valid?
|
||||||
|
if @model.bootstrap_template
|
||||||
|
templates = get_templates
|
||||||
|
templates.include?(@model.bootstrap_template)
|
||||||
|
else
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def message
|
||||||
|
"Invalid bootstrap template '#{@model.bootstrap_template}' for image '#{@model.id}'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
16
devops-service/db/validators/image/image_in_filter.rb
Normal file
16
devops-service/db/validators/image/image_in_filter.rb
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
require "commands/image"
|
||||||
|
module Validators
|
||||||
|
class Image::ImageInFilter < Base
|
||||||
|
|
||||||
|
include ImageCommands
|
||||||
|
|
||||||
|
def valid?
|
||||||
|
images = get_images(DevopsService.mongo, @model.provider)
|
||||||
|
images.map{|i| i["id"]}.include?(@model.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def message
|
||||||
|
"Invalid image id '#{@model.id}' for provider '#{@model.provider}', please check image filters"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
7
devops-service/db/validators/key/file_existence.rb
Normal file
7
devops-service/db/validators/key/file_existence.rb
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module Validators
|
||||||
|
class Key::FileExistence < Base
|
||||||
|
|
||||||
|
delegate_to_helper_validator { Helpers::FileExistence.new(@model.path) }
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
12
devops-service/db/validators/key/scope.rb
Normal file
12
devops-service/db/validators/key/scope.rb
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
module Validators
|
||||||
|
class Key::Scope < Base
|
||||||
|
|
||||||
|
def valid?
|
||||||
|
[::Key::SYSTEM, ::Key::USER].include?(@model.scope)
|
||||||
|
end
|
||||||
|
|
||||||
|
def message
|
||||||
|
"Key parameter 'scope' is invalid"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
35
devops-service/lib/string_helper.rb
Normal file
35
devops-service/lib/string_helper.rb
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
module StringHelper
|
||||||
|
extend self
|
||||||
|
|
||||||
|
# from Rails' ActiveSupport
|
||||||
|
def underscore(string)
|
||||||
|
string.gsub(/::/, '/').
|
||||||
|
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
||||||
|
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
||||||
|
tr("-", "_").
|
||||||
|
downcase
|
||||||
|
end
|
||||||
|
|
||||||
|
def underscore_class(klass, without_ancestors=true)
|
||||||
|
class_name = if without_ancestors
|
||||||
|
klass.to_s.split('::').last
|
||||||
|
else
|
||||||
|
klass.to_s
|
||||||
|
end
|
||||||
|
StringHelper.underscore(class_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
# from Rails' ActiveSupport
|
||||||
|
def camelize(term)
|
||||||
|
string = term.to_s
|
||||||
|
string = string.sub(/^[a-z\d]*/) { $&.capitalize }
|
||||||
|
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
|
||||||
|
string.gsub!(/\//, '::')
|
||||||
|
string
|
||||||
|
end
|
||||||
|
|
||||||
|
# rough simplification
|
||||||
|
def pluralize(string)
|
||||||
|
"#{string}s"
|
||||||
|
end
|
||||||
|
end
|
||||||
13
devops-service/providers/all.rb
Normal file
13
devops-service/providers/all.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
["ec2", "openstack", "static"].each do |provider|
|
||||||
|
begin
|
||||||
|
require_relative provider
|
||||||
|
|
||||||
|
provider_stub_path = File.expand_path("../#{provider}_stub.rb", __FILE__)
|
||||||
|
|
||||||
|
if DevopsService.debug? && File.exists?(provider_stub_path)
|
||||||
|
require provider_stub_path
|
||||||
|
end
|
||||||
|
rescue LoadError => e
|
||||||
|
puts "Can not load provider '#{provider}': " + e.message
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -190,6 +190,11 @@ module Provider
|
|||||||
def network
|
def network
|
||||||
connection_network(self.connection_options)
|
connection_network(self.connection_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_stack(stack)
|
||||||
|
byebug
|
||||||
|
result = orchestration.create_stack(stack.id, {template_url: stack.template_url})
|
||||||
|
end
|
||||||
private
|
private
|
||||||
def convert_groups list
|
def convert_groups list
|
||||||
res = {}
|
res = {}
|
||||||
@ -211,5 +216,9 @@ module Provider
|
|||||||
res
|
res
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def orchestration
|
||||||
|
@connection ||= Fog::Orchestration::OpenStack.new(connection_options)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -20,14 +20,12 @@ module Provider
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.init conf
|
def self.init conf
|
||||||
|
|
||||||
|
# require providers here to get access to debug properties
|
||||||
|
require 'providers/all'
|
||||||
|
|
||||||
["ec2", "openstack", "static"].each do |p|
|
["ec2", "openstack", "static"].each do |p|
|
||||||
begin
|
begin
|
||||||
require "providers/#{p}"
|
|
||||||
|
|
||||||
if File.exist?("providers/#{p}_stub.rb")
|
|
||||||
require "providers/#{p}_stub"
|
|
||||||
end
|
|
||||||
|
|
||||||
o = Provider.const_get(p.capitalize).new(conf)
|
o = Provider.const_get(p.capitalize).new(conf)
|
||||||
if o.configured?
|
if o.configured?
|
||||||
@@providers[p] = o
|
@@providers[p] = o
|
||||||
@ -36,9 +34,6 @@ module Provider
|
|||||||
rescue => e
|
rescue => e
|
||||||
puts "Error while loading provider '#{p}': " + e.message
|
puts "Error while loading provider '#{p}': " + e.message
|
||||||
next
|
next
|
||||||
rescue LoadError => e
|
|
||||||
puts "Can not load provider '#{p}': " + e.message
|
|
||||||
next
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user