diff --git a/devops-service/app/api2/handlers/project.rb b/devops-service/app/api2/handlers/project.rb index fa47a59..e61536d 100644 --- a/devops-service/app/api2/handlers/project.rb +++ b/devops-service/app/api2/handlers/project.rb @@ -95,14 +95,19 @@ module Devops "Users '#{users.join("', '")}' have been removed from '#{id}' project's authorized users" end - # TODO: multi project + def set_project_run_list id + list = parser.run_list + project = Devops::Db.connector.project(id) + Devops::Db.connector.set_project_run_list id, list + "Updated project with run_list '#{list.inspect}'" + end + def set_project_env_run_list id, deploy_env list = parser.run_list project = Devops::Db.connector.project(id) env = project.deploy_env deploy_env - env.run_list = list - Devops::Db.connector.project_update project - "Updated environment '#{env.identifier}' with run_list '#{env.run_list.inspect}' in project '#{project.id}'" + Devops::Db.connector.set_project_env_run_list id, deploy_env, list + "Updated environment '#{env.identifier}' with run_list '#{list.inspect}' in project '#{project.id}'" end def delete_project id diff --git a/devops-service/app/api2/handlers/server.rb b/devops-service/app/api2/handlers/server.rb index ee4482a..cb2acdf 100644 --- a/devops-service/app/api2/handlers/server.rb +++ b/devops-service/app/api2/handlers/server.rb @@ -55,7 +55,7 @@ module Devops def create_server_stream out, body status = [] prepare_create_server(body).each do |s| - res = create_server_proc.call(out, s, provider, Devops::Db.connector) + res = create_server_proc.call(out, s, provider) status.push res end status @@ -253,6 +253,13 @@ module Devops yield s.id, provider end + def set_run_list node_name + s = get_server_by_key(node_name, parser.instance_key) + user = parser.current_user + Devops::Db.connector.check_project_auth s.project, s.deploy_env, user + Devops::Db.connector.set_server_run_list(s.id, parser.run_list) + end + def get_server_by_key id, key mongo = Devops::Db.connector key == "instance" ? mongo.server_by_instance_id(id) : mongo.server_by_chef_node_name(id) diff --git a/devops-service/app/api2/handlers/stack.rb b/devops-service/app/api2/handlers/stack.rb index 46c2bc0..bca4847 100644 --- a/devops-service/app/api2/handlers/stack.rb +++ b/devops-service/app/api2/handlers/stack.rb @@ -49,6 +49,10 @@ module Devops stack = Devops::Db.connector.stack(id) stack.resource(resource_id) end + + def set_run_list id + Devops::Db.connector.set_stack_run_list(id, parser.run_list) + end end end end diff --git a/devops-service/app/api2/parsers/project.rb b/devops-service/app/api2/parsers/project.rb index 98a6886..37c6f59 100644 --- a/devops-service/app/api2/parsers/project.rb +++ b/devops-service/app/api2/parsers/project.rb @@ -34,12 +34,14 @@ module Devops body = create_object_from_json_body check_string(body["name"], "Parameter 'name' must be a not empty string") check_array(body["deploy_envs"], "Parameter 'deploy_envs' must be a not empty array of objects", Hash) + check_array(body["run_list"], "Parameter 'run_list' must be a not empty array of string", String, false, true) Devops::Model::Project.new(body) end def update body = create_object_from_json_body check_array(body["deploy_envs"], "Parameter 'deploy_envs' must be a not empty array of objects", Hash) + check_array(body["run_list"], "Parameter 'run_list' must be a not empty array of string", String, false, true) Devops::Model::Project.new(body) end diff --git a/devops-service/app/api2/parsers/server.rb b/devops-service/app/api2/parsers/server.rb index ac70259..f1d6f65 100644 --- a/devops-service/app/api2/parsers/server.rb +++ b/devops-service/app/api2/parsers/server.rb @@ -35,6 +35,8 @@ module Devops raise InvalidRecord.new("Parameter 'force' should be a null or true") unless force.nil? or force == true groups = check_array(@body["groups"], "Parameter 'groups' should be null or not empty array of string", String, true) key_name = check_string(@body["key"], "Parameter 'key' should be null or not empty string", true) + rl = check_array(@body["run_list"], "Parameter 'run_list' should be a not empty array of string", String, true, true) + Validators::Helpers::RunList.new(rl).validate! unless rl.nil? @body end @@ -43,10 +45,7 @@ module Devops id = check_string(@body["instance_id"], "Parameter 'instance_id' must be a not empty string") name = check_string(@body["name"], "Parameter 'name' should be a not empty string", true) rl = check_array(@body["run_list"], "Parameter 'run_list' should be a not empty array of string", String, true) - unless rl.nil? - validator = Validators::Helpers::RunList.new(rl) - halt_response(validator.message) unless validator.valid? - end + Validators::Helpers::RunList.new(rl).validate! unless rl.nil? t = check_string(@body["bootstrap_template"], "Parameter 'bootstrap_template' should be a not empty string", true) @body end @@ -59,12 +58,21 @@ module Devops remote_user = check_string(@body["remote_user"], "Parameter 'remote_user' must be a not empty string") private_ip = check_string(@body["private_ip"], "Parameter 'private_ip' must be a not empty string") public_ip = check_string(@body["public_ip"], "Parameter 'public_ip' should be a not empty string", true) + rl = check_array(@body["run_list"], "Parameter 'run_list' should be a not empty array of string", String, true, true) + Validators::Helpers::RunList.new(rl).validate! unless rl.nil? @body end def tags @body ||= create_object_from_json_body - @body["tags"] + check_param(@body["tags"], Hash, "Parameter 'tags' should be a hash", false, true) + end + + def run_list + @body ||= create_object_from_json_body + rl = check_array(@body["run_list"], "Parameter 'run_list' should be a not empty array of string", String, false, true) + Validators::Helpers::RunList.new(rl).validate! + rl end end diff --git a/devops-service/app/api2/parsers/stack.rb b/devops-service/app/api2/parsers/stack.rb index 71094b9..ebb8f15 100644 --- a/devops-service/app/api2/parsers/stack.rb +++ b/devops-service/app/api2/parsers/stack.rb @@ -6,7 +6,16 @@ module Devops class StackParser < RequestParser def create - create_object_from_json_body + body = create_object_from_json_body + list = check_array(body["run_list"], "Body must contains not empty array of strings", String, true, true) + Validators::Helpers::RunList.new(list).validate! unless list.nil? + body + end + + def run_list + list = check_array(create_object_from_json_body(Array), "Body must contains not empty array of strings") + Validators::Helpers::RunList.new(list).validate! + list end end diff --git a/devops-service/app/api2/routes/project.rb b/devops-service/app/api2/routes/project.rb index b8aa929..ee4bee1 100644 --- a/devops-service/app/api2/routes/project.rb +++ b/devops-service/app/api2/routes/project.rb @@ -295,10 +295,10 @@ module Devops } app.multi_routes "/project/:id/user", {}, users_hash - # Set run_list to project environment + # Set run_list to project # # * *Request* - # - method : PUT + # - method : PATCH # - headers : # - Accept: application/json # - Content-Type: application/json @@ -310,7 +310,28 @@ module Devops # # * *Returns* : # 200 - Updated - app.put_with_headers "/project/:id/:env/run_list", :headers => [:accept, :content_type] do |project, deploy_env| + app.patch_with_headers "/project/:id/run_list", :headers => [:accept, :content_type] do |project| + check_privileges("project", "w") + info = Devops::API2_0::Handler::Project.new(request).set_project_run_list(project) + create_response(info) + end + + # Set run_list to project environment + # + # * *Request* + # - method : PATCH + # - headers : + # - Accept: application/json + # - Content-Type: application/json + # - body : + # [ + # "role[role_1]", + # "recipe[recipe_1]" + # ] + # + # * *Returns* : + # 200 - Updated + app.patch_with_headers "/project/:id/:env/run_list", :headers => [:accept, :content_type] do |project, deploy_env| check_privileges("project", "w") info = Devops::API2_0::Handler::Project.new(request).set_project_env_run_list(project, deploy_env) create_response(info) diff --git a/devops-service/app/api2/routes/server.rb b/devops-service/app/api2/routes/server.rb index 024dc24..f7c10af 100644 --- a/devops-service/app/api2/routes/server.rb +++ b/devops-service/app/api2/routes/server.rb @@ -322,7 +322,7 @@ module Devops hash["PUT"] = lambda {|id| check_privileges("server", "w") Devops::API2_0::Handler::Server.new(request).set_tags(id) - "Added" + create_response("Added") } # Delete devops server tags @@ -342,10 +342,34 @@ module Devops hash["DELETE"] = lambda {|id| check_privileges("server", "w") Devops::API2_0::Handler::Server.new(request).unset_tags(id) - "Deleted" + create_response("Deleted") } app.multi_routes "/server/:id/tags", {:headers => [:content_type]}, hash + # Set run_list to server + # + # * *Request* + # - method : PATCH + # - headers : + # - Accept: application/json + # - Content-Type: application/json + # - body : + # { + # "run_list": [ + # "role[role_1]", + # "recipe[recipe_1]" + # ], + # "key": "instance", -> search server by instance_id rather then chef_node_name + # } + # + # * *Returns* : + # 200 - Updated + app.patch_with_headers "/server/:id/run_list", :headers => [:accept, :content_type] do |node_name| + check_privileges("server", "w") + Devops::API2_0::Handler::Server.new(request).set_server_run_list(node_name) + create_response("Run list has been changed") + end + puts "Server routes initialized" end diff --git a/devops-service/app/api2/routes/stack.rb b/devops-service/app/api2/routes/stack.rb index 2a32d21..abfe3cb 100644 --- a/devops-service/app/api2/routes/stack.rb +++ b/devops-service/app/api2/routes/stack.rb @@ -51,6 +51,28 @@ module Devops json Devops::API2_0::Handler::Stack.new(request).resource(stack_id, resource_id) end + # Set run_list to stack + # + # * *Request* + # - method : PATCH + # - headers : + # - Accept: application/json + # - Content-Type: application/json + # - body : + # [ + # "role[role_1]", + # "recipe[recipe_1]" + # ] + # + # * *Returns* : + # 200 - Updated + app.patch_with_headers "/stack/:id/run_list", :headers => [:accept, :content_type] do |id| + check_privileges("stack", "w") + info = Devops::API2_0::Handler::Stack.new(request).set_run_list(id) + create_response(info) + end + + puts "Stack routes initialized" end diff --git a/devops-service/db/mongo/connectors/project.rb b/devops-service/db/mongo/connectors/project.rb index 9e46ef5..0c279da 100644 --- a/devops-service/db/mongo/connectors/project.rb +++ b/devops-service/db/mongo/connectors/project.rb @@ -93,6 +93,16 @@ module Connectors project end + def set_project_env_run_list(project_id, env, run_list) + Helpers::RunList.new(run_list).validate! + @collection.update({"_id" => project_id, "deploy_envs.identifier" => env}, {"$set" => {"deploy_envs.$.run_list" => run_list}}) + end + + def set_project_run_list(project_id, env, run_list) + Helpers::RunList.new(run_list).validate! + @collection.update({"_id" => project_id}, {"$set" => {run_list: run_list}}) + end + private def list(query={}, query_options={}) diff --git a/devops-service/db/mongo/connectors/server.rb b/devops-service/db/mongo/connectors/server.rb index 7c40322..afb0ede 100644 --- a/devops-service/db/mongo/connectors/server.rb +++ b/devops-service/db/mongo/connectors/server.rb @@ -67,6 +67,10 @@ module Connectors collection.remove('stack' => stack_id) end + def set_server_run_list(id, run_list) + @collection.update({"_id" => id}, {"$set" => {"run_list" => run_list}}) + end + private def model_from_bson(bson) diff --git a/devops-service/db/mongo/connectors/stack.rb b/devops-service/db/mongo/connectors/stack.rb index 3024821..241c5b8 100644 --- a/devops-service/db/mongo/connectors/stack.rb +++ b/devops-service/db/mongo/connectors/stack.rb @@ -14,6 +14,10 @@ module Connectors list(options) end + def set_stack_run_list id, run_list + collection.update({"_id" => id}, {"$set" => {"run_list" => run_list}}) + end + private def model_from_bson(bson) diff --git a/devops-service/db/mongo/models/deploy_env/deploy_env_base.rb b/devops-service/db/mongo/models/deploy_env/deploy_env_base.rb index 7a88483..41e36e1 100644 --- a/devops-service/db/mongo/models/deploy_env/deploy_env_base.rb +++ b/devops-service/db/mongo/models/deploy_env/deploy_env_base.rb @@ -1,14 +1,16 @@ require "db/mongo/models/mongo_model" require "providers/provider_factory" require "commands/deploy_env" +require "db/mongo/models/model_with_provider" module Devops module Model class DeployEnvBase < MongoModel include DeployEnvCommands + include ModelWithProvider - attr_accessor :identifier, :run_list, :expires, :provider, :users, :chef_env + attr_accessor :identifier, :run_list, :expires, :users, :chef_env def initialize d={} self.identifier = d["identifier"] @@ -30,15 +32,10 @@ module Devops } end - def provider_instance - @provider_instance ||= ::Provider::ProviderFactory.get(self.provider) - end - def build_error_message(message) "Deploy environment '#{self.identifier}'. " + message end - # class methods class << self diff --git a/devops-service/db/mongo/models/mongo_model.rb b/devops-service/db/mongo/models/mongo_model.rb index a880934..cf37bf3 100644 --- a/devops-service/db/mongo/models/mongo_model.rb +++ b/devops-service/db/mongo/models/mongo_model.rb @@ -119,7 +119,7 @@ module Devops end def self.validators - @validators || [] + @validators ||= [] end # all exceptions are handled in @validate! method diff --git a/devops-service/db/mongo/models/project.rb b/devops-service/db/mongo/models/project.rb index b92869b..e791f34 100644 --- a/devops-service/db/mongo/models/project.rb +++ b/devops-service/db/mongo/models/project.rb @@ -18,14 +18,17 @@ module Devops define_hook :before_delete define_hook :after_delete - attr_accessor :id, :deploy_envs, :type, :archived, :description + attr_accessor :id, :deploy_envs, :type, :archived, :description, :run_list types :id => {:type => String, :empty => false}, :deploy_envs => {:type => Array, :value_type => false, :empty => false}, - :description => {:type => String, :empty => true, :nil => true} + :description => {:type => String, :empty => true, :nil => true}, + :run_list => {:type => Array, :value_type => String, :empty => true, :nil => false} MULTI_TYPE = "multi" + set_validators ::Validators::DeployEnv::RunList + def self.fields ["deploy_envs", "type", "description"] end @@ -36,6 +39,7 @@ module Devops 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) unless handler.nil? diff --git a/devops-service/db/mongo/models/server.rb b/devops-service/db/mongo/models/server.rb index f589758..b7692da 100644 --- a/devops-service/db/mongo/models/server.rb +++ b/devops-service/db/mongo/models/server.rb @@ -1,10 +1,13 @@ require "db/mongo/models/mongo_model" require "hooks" +require "db/mongo/models/model_with_provider" + module Devops module Model class Server < MongoModel + include ModelWithProvider include Hooks #params: # out - container for output data @@ -20,8 +23,8 @@ module Devops define_hook :before_bootstrap define_hook :after_bootstrap - attr_accessor :provider, :chef_node_name, :id, :remote_user, :project, :deploy_env, :private_ip, :public_ip, :created_at, :without_bootstrap, :created_by, :reserved_by, :stack - attr_accessor :options, :static, :key + attr_accessor :chef_node_name, :id, :remote_user, :project, :deploy_env, :private_ip, :public_ip, :created_at, :without_bootstrap, :created_by, :reserved_by, :stack, :run_list + attr_accessor :options, :key types :id => {:type => String, :empty => false}, :provider => {:type => String, :empty => false}, @@ -34,10 +37,13 @@ module Devops :created_by => {:type => String, :empty => false}, :chef_node_name => {:type => String, :empty => true}, :reserved_by => {:type => String, :empty => true}, - :stack => {:type => String, :nil => true} + :stack => {:type => String, :nil => true}, + :run_list => {:type => Array, :value_type => String, :empty => true, :nil => false} + + set_validators ::Validators::DeployEnv::RunList def self.fields - ["chef_node_name", "project", "deploy_env", "provider", "remote_user", "private_ip", "public_ip", "created_at", "created_by", "static", "key", "reserved_by"] + ["chef_node_name", "project", "deploy_env", "provider", "remote_user", "private_ip", "public_ip", "created_at", "created_by", "key", "reserved_by"] end def initialize s={} @@ -51,10 +57,10 @@ module Devops self.private_ip = s["private_ip"] self.created_at = s["created_at"] self.created_by = s["created_by"] - self.static = s["static"] self.key = s["key"] self.reserved_by = s["reserved_by"] self.stack = s["stack"] + self.run_list = p["run_list"] || [] end def create @@ -81,10 +87,10 @@ module Devops "public_ip" => self.public_ip, "created_at" => self.created_at, "created_by" => self.created_by, - "static" => self.static, "key" => self.key, "reserved_by" => self.reserved_by, - "stack" => stack + "stack" => stack, + "run_list" => self.run_list }.delete_if{|k,v| v.nil?} end @@ -111,7 +117,7 @@ module Devops end def static? - self.static || false + (self.provider == Provider::Static::PROVIDER) || false end end diff --git a/devops-service/db/mongo/models/stack/stack_base.rb b/devops-service/db/mongo/models/stack/stack_base.rb index d95c435..f411ace 100644 --- a/devops-service/db/mongo/models/stack/stack_base.rb +++ b/devops-service/db/mongo/models/stack/stack_base.rb @@ -1,9 +1,12 @@ +require "db/mongo/models/model_with_provider" module Devops module Model class StackBase < MongoModel + include ModelWithProvider + attr_accessor :id, :project, :deploy_env, :stack_template, - :cloud_stack_id, :provider, :parameters, :details, :owner + :cloud_stack_id, :parameters, :details, :owner types id: {type: String, empty: false}, provider: {type: String, empty: false}, @@ -11,7 +14,8 @@ module Devops deploy_env: {type: String}, stack_template: {type: String, empty: false}, cloud_stack_id: {type: String, nil: true}, - owner: {type: String} + owner: {type: String}, + :run_list => {:type => Array, :value_type => String, :empty => true, :nil => false} # details: {type: Hash, nil: true} # Hash type isn't supported yet def initialize attrs={} @@ -44,27 +48,27 @@ module Devops def create_stack_in_cloud! begin - self.cloud_stack_id = provider_class.create_stack(self) + self.cloud_stack_id = provider_instance.create_stack(self) rescue ProviderErrors::NameConflict raise InvalidRecord.new "Duplicate key error: stack with name '#{id}' already exists in cloud" end end def delete_stack_in_cloud! - provider_class.delete_stack(self) + provider_instance.delete_stack(self) end def sync_details! - self.details = provider_class.stack_details(self).attributes + self.details = provider_instance.stack_details(self).attributes end def resources - provider_class.stack_resources(self) + provider_instance.stack_resources(self) end # resource_id is logical def resource(resource_id) - provider_class.stack_resource(self, resource_id) + provider_instance.stack_resource(self, resource_id) end def stack_status @@ -84,7 +88,6 @@ module Devops end class << self - attr_accessor :provider # attrs should include: # - id (String) @@ -103,12 +106,6 @@ module Devops end end - private - - def provider_class - Provider::ProviderFactory.get(provider) - end - end end end diff --git a/devops-service/db/mongo/mongo_connector.rb b/devops-service/db/mongo/mongo_connector.rb index 4dbfd7f..dd153f8 100644 --- a/devops-service/db/mongo/mongo_connector.rb +++ b/devops-service/db/mongo/mongo_connector.rb @@ -13,16 +13,16 @@ class MongoConnector delegate( [:images, :image, :image_insert, :image_delete, :image_update] => :images_connector, [:stack_templates, :stack_template, :stack_template_insert, :stack_template_delete, :stack_template_update] => :stack_templates_connector, - [:stacks, :stack, :stack_insert, :stack_delete, :stack_update] => :stacks_connector, + [:stacks, :stack, :stack_insert, :stack_delete, :stack_update, :set_stack_run_list] => :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, + :project_delete, :is_project_exists?, :check_project_auth, :set_project_run_list, :set_project_env_run_list] => :projects_connector, [:project_templates, :project_template_insert, :project_template_update, :project_template_delete] => :projects_templates_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, :stack_servers_delete] => :servers_connector, + :server_delete, :server_update, :server_set_chef_node_name, :stack_servers_delete, :set_server_run_list] => :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, diff --git a/devops-service/sinatra/methods_with_headers.rb b/devops-service/sinatra/methods_with_headers.rb index 45ce393..2bce5f1 100644 --- a/devops-service/sinatra/methods_with_headers.rb +++ b/devops-service/sinatra/methods_with_headers.rb @@ -47,6 +47,20 @@ module Sinatra end end + def patch_with_headers path, opt={}, &block + headers = opt.delete(:headers) || [] + before path do + check_headers *headers + protect! + end + + patch path, opt, &block + + after path do + statistic + end + end + def delete_with_headers path, opt={}, &block headers = opt.delete(:headers) || [] before path do