384 lines
10 KiB
Ruby
384 lines
10 KiB
Ruby
require "mongo"
|
|
|
|
require "db/exceptions/record_not_found"
|
|
require "db/exceptions/invalid_record"
|
|
require "exceptions/invalid_privileges"
|
|
|
|
require "db/mongo/models/project"
|
|
require "db/mongo/models/image"
|
|
require "db/mongo/models/project"
|
|
require "db/mongo/models/server"
|
|
require "db/mongo/models/user"
|
|
|
|
include Mongo
|
|
|
|
class MongoConnector
|
|
|
|
def initialize(db, host, port=27017, user=nil, password=nil)
|
|
@mongo_client = MongoClient.new(host, port)
|
|
@db = @mongo_client.db(db)
|
|
@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")
|
|
end
|
|
|
|
def images provider=nil
|
|
q = (provider.nil? ? {} : {"provider" => provider})
|
|
@images.find(q).to_a.map {|bi| Image.create_from_bson bi}
|
|
end
|
|
|
|
def image id
|
|
i = @images.find(create_query("_id" => id)).to_a[0]
|
|
raise RecordNotFound.new("Image '#{id}' does not exist") if i.nil?
|
|
Image.create_from_bson i
|
|
end
|
|
|
|
def image_insert image
|
|
image.validate!
|
|
@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
|
|
|
|
def image_update image
|
|
image.validate!
|
|
@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
|
|
|
|
def image_delete id
|
|
r = @images.remove(create_query("_id" => id))
|
|
raise RecordNotFound.new("Image '#{id}' not found") if r["n"] == 0
|
|
r
|
|
end
|
|
|
|
def available_images provider
|
|
f = @filters.find(create_query("type" => "image", "provider" => provider)).to_a[0]
|
|
return [] if f.nil?
|
|
f["images"]
|
|
end
|
|
|
|
def add_available_images images, provider
|
|
return unless images.is_a?(Array)
|
|
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
|
|
|
|
def delete_available_images images, provider
|
|
return unless images.is_a?(Array)
|
|
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
|
|
|
|
def is_project_exists? project
|
|
self.project project.id
|
|
return true
|
|
rescue RecordNotFound => e
|
|
return false
|
|
end
|
|
|
|
def project_insert project
|
|
project.validate!
|
|
@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
|
|
|
|
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
|