require "db/mongo/models/deploy_env/deploy_env_factory" require "db/mongo/models/user" require "db/mongo/models/deploy_env/deploy_env_multi" require "db/mongo/models/mongo_model" require "json" require "hooks" require "lib/project/type/types_factory" require "db/validators/deploy_env/deploy_envs" module Devops module Model class Project < MongoModel include Hooks include Hooks::InstanceHooks define_hook :before_create define_hook :after_create define_hook :before_delete define_hook :after_delete #define_hook :after_add_deploy_env attr_accessor :id, :deploy_envs, :type, :archived, :description, :run_list MULTI_TYPE = "multi" set_field_validators :id, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::String, ::Validators::FieldValidator::NotEmpty] set_field_validators :deploy_envs, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::Array, ::Validators::FieldValidator::NotEmpty] set_field_validators :description, [::Validators::FieldValidator::Nil, ::Validators::FieldValidator::FieldType::String] set_field_validators :run_list, [::Validators::FieldValidator::NotNil, ::Validators::FieldValidator::FieldType::Array, ::Validators::FieldValidator::RunList] set_validators ::Validators::DeployEnv::RunList, ::Validators::DeployEnv::DeployEnvs def self.fields ["deploy_envs", "type", "description"] end def initialize p={} self.id = p["name"] #raise InvalidRecord.new "No deploy environments for project #{self.id}" if p["deploy_envs"].nil? or p["deploy_envs"].empty? self.type = p["type"] || Devops::GenericType.name self.description = p["description"] self.archived = p["archived"] || false self.run_list = p["run_list"] || [] @handler = Devops::TypesFactory.type self.type @handler.prepare(self) env_class = ( self.multi? ? DeployEnvMulti : DeployEnvFactory ) unless p["deploy_envs"].nil? self.deploy_envs = [] p["deploy_envs"].each do |e| env = env_class.create(e) self.deploy_envs.push env end end end def deploy_env env de = self.deploy_envs.detect {|e| e.identifier == env} raise RecordNotFound.new("Project '#{self.id}' does not have deploy environment '#{env}'") if de.nil? de end def add_deploy_env deploy_env res = deploy_env.create_role(self.id) Devops::Db.connector.add_deploy_env_to_project self.id, deploy_env Project.create_roles_response(res) end # user could be a String or an Array of strings. # if env is nil, add given user(s) to all project's envs, # otherwise only to specified one. def add_authorized_user user, env=nil return if user.nil? new_users = ( user.is_a?(Array) ? user : [ user ] ) environments = env.nil? ? self.deploy_envs : [ self.deploy_env(env) ] environments.each do |e| e.add_users new_users Devops::Db.connector.set_project_deploy_env_field(self.id, e.identifier, {users: e.users}) end end def remove_authorized_user user, env=nil return if user.nil? users = ( user.is_a?(Array) ? user : [ user ] ) environments = env.nil? ? self.deploy_envs : [ self.deploy_env(env) ] environments.each do |e| e.users = e.users - users Devops::Db.connector.set_project_deploy_env_field(self.id, e.identifier, {users: e.users}) end end def check_authorization user_id, env e = self.deploy_env(env) return true if user_id == User::ROOT_USER_NAME return true if is_sandbox? return e.users.include? user_id rescue RecordNotFound => e return false end def is_sandbox? id.start_with?('sandbox-') end =begin def validate! super check_name_value(self.id) true rescue InvalidRecord, ArgumentError => e raise InvalidRecord.new "Project '#{self.id}'. #{e.message}" end =end def delete_deploy_env env self.deploy_envs.delete_if {|e| e.identifier == env} Devops::Db.connector.remove_deploy_env_from_project self.id, env end =begin def add_env env raise InvalidRecord.new "Deploy environment '#{env.identifier}' for project '#{self.id}' already exist" unless self.deploy_env(env.identifier).nil? self.deploy_envs.push env end =end def to_hash h = self.to_hash_without_id h["name"] = self.id h end # TODO: why symbols here? def to_hash_list { name: self.id, description: self.description } end def deploy_info deploy_env, build_number=nil { "use_json_file" => true, # "run_list" => Set.new.merge(self.run_list).merge(deploy_env.run_list).to_a, "project" => self.id, "project_info" => { "project" => self.id, "deploy_env" => deploy_env.identifier, "deployers" => deploy_env.users } } end def to_hash_without_id h = {} h["deploy_envs"] = self.deploy_envs.map {|e| e.to_hash} unless self.deploy_envs.nil? h["archived"] = self.archived if self.archived h["description"] = self.description h["run_list"] = self.run_list if self.multi? h["type"] = MULTI_TYPE end h end def multi? self.type == MULTI_TYPE end def create res = {} res[:before] = self.run_hook :before_create Devops::Db.connector.project_insert self res[:after] = self.run_hook :after_create res end def delete res = {} res[:before] = self.run_hook :before_delete Devops::Db.connector.project_delete self.id res[:after] = self.run_hook :after_delete res end def extract_servers env, params @handler.extract_servers(self, env, params) end def self.build_from_bson p p["name"] = p["_id"] Project.new p end # maybe it worth to move components functionality to devops-nibr? #TODO: create validator def validate_components raise InvalidRecord.new "Components is not a hash" unless self.components.is_a?(Hash) self.components.each do |id, c| raise InvalidRecord.new "Component '#{id}' has no attribute 'filename'" unless c.key?("filename") end end def self.create_roles_response roles return "error in creating roles" unless roles if roles.is_a?(String) roles else info = "" info += " Project roles '#{roles[:new].join("', '")}' have been automaticaly created" unless roles[:new].nil? info += " Project roles '#{roles[:exist].join("', '")}' weren't created because they exist" unless roles[:exist].nil? info += " Project roles '#{roles[:error].join("', '")}' weren't created because of internal error" unless roles[:error].nil? info end end end end end