diff --git a/devops-service/app/api2/handlers/project.rb b/devops-service/app/api2/handlers/project.rb index 80f4b01..ee45024 100644 --- a/devops-service/app/api2/handlers/project.rb +++ b/devops-service/app/api2/handlers/project.rb @@ -94,12 +94,29 @@ module Devops end end - def add_or_update_deploy_env id, deploy_env + def update_deploy_env_field id, deploy_env, field project = Devops::Db.connector.project(id) - env = parser.add_or_update_deploy_env + db_env = project.deploy_env(deploy_env) + value = parser.update_deploy_env_field + if db_env.respond_to?(field + "=") + if field == "identifier" + db_env.rename id, value + "Environment '#{deploy_env}' has been renamed to '#{value}'" + else + db_env.update_field(id, field, value) + "Environment's field '#{field}' has been updated" + end + else + raise RecordNotFound.new("Field '#{field}' does not exist") + end + end + + def update_deploy_env id, deploy_env + project = Devops::Db.connector.project(id) + db_env = project.deploy_env(deploy_env) + env = parser.update_deploy_env env.identifier = deploy_env if env.identifier.nil? begin - db_env = project.deploy_env(deploy_env) unless env.identifier == deploy_env servers = Devops::Db.connector.servers_by_project_and_deploy_env(id, deploy_env) raise InvalidRecord.new("Can not update environment '#{deploy_env}', there are #{servers.size} servers on it") unless servers.empty? @@ -279,49 +296,6 @@ module Devops return [uri] end -=begin - def create_roles project_id, envs - all_roles = KnifeFactory.instance.roles - return " Can't get roles list" if all_roles.nil? - roles = {:new => [], :error => [], :exist => []} - envs.each do |e| - role_name = KnifeCommands.role_name(project_id, e.identifier) - begin - if all_roles.include? role_name - roles[:exist].push role_name - else - KnifeCommands.create_role role_name, project_id, e.identifier - roles[:new].push role_name - DevopsLogger.logger.info "Role '#{role_name}' created" - end - rescue => er - roles[:error].push role_name - DevopsLogger.logger.error "Role '#{role_name}' can not be created: #{er.message}" - end - end - roles - end - - def create_new_roles old_project, new_project - old_project.deploy_envs.each do |e| - new_project.deploy_envs.delete_if {|env| e.identifier == env.identifier} - end - create_roles new_project.id, new_project.deploy_envs - end - - def create_roles_response roles - if roles.is_a?(String) - roles - else - info = "" - info += " Project roles '#{roles[:new].join("', '")}' have been automaticaly created" unless roles[:new].empty? - info += " Project roles '#{roles[:exist].join("', '")}' weren't created because they exist" unless roles[:exist].empty? - info += " Project roles '#{roles[:error].join("', '")}' weren't created because of internal error" unless roles[:error].empty? - info - end - end -=end - end end end diff --git a/devops-service/app/api2/parsers/image.rb b/devops-service/app/api2/parsers/image.rb index f801250..4e5c348 100644 --- a/devops-service/app/api2/parsers/image.rb +++ b/devops-service/app/api2/parsers/image.rb @@ -6,7 +6,8 @@ module Devops class ImageParser < RequestParser def images - provider = @params[:provider] + provider = @params["provider"] + puts "Provider: #{provider}" check_provider(provider) if provider provider end diff --git a/devops-service/app/api2/parsers/key.rb b/devops-service/app/api2/parsers/key.rb index 3610438..fcf1db2 100644 --- a/devops-service/app/api2/parsers/key.rb +++ b/devops-service/app/api2/parsers/key.rb @@ -7,7 +7,7 @@ module Devops def create key = create_object_from_json_body - fname = check_filename(key["file_name"], "Parameter 'file_name' must be a not empty string") + fname = check_filename(key["file_name"], "Parameter 'file_name' should be a not empty string") kname = check_string(key["key_name"], "Parameter 'key_name' should be a not empty string") content = check_string(key["content"], "Parameter 'content' should be a not empty string") key diff --git a/devops-service/app/api2/parsers/project.rb b/devops-service/app/api2/parsers/project.rb index e300977..dc2a8e9 100644 --- a/devops-service/app/api2/parsers/project.rb +++ b/devops-service/app/api2/parsers/project.rb @@ -50,10 +50,16 @@ module Devops Devops::Model::DeployEnvFactory.create(body) end - def add_or_update_deploy_env + def update_deploy_env_field body = create_object_from_json_body - rl = check_array(body["run_list"], "Parameter 'run_list' should be an array of string", String, false, true) - Validators::Helpers::RunList.new(rl).validate! + raise InvalidRecord.new("'value' key not found") if body["value"].nil? + body["value"] + end + + def update_deploy_env + body = create_object_from_json_body +# rl = check_array(body["run_list"], "Parameter 'run_list' should be an array of string", String, false, true) +# Validators::Helpers::RunList.new(rl).validate! Devops::Model::DeployEnvFactory.create(body) end diff --git a/devops-service/app/api2/parsers/user.rb b/devops-service/app/api2/parsers/user.rb index 33266fb..ac7858a 100644 --- a/devops-service/app/api2/parsers/user.rb +++ b/devops-service/app/api2/parsers/user.rb @@ -16,18 +16,16 @@ module Devops def user_privileges data = create_object_from_json_body cmd = check_string(data["cmd"], "Parameter 'cmd' should be a not empty string", true) - privileges = check_string(data["privileges"], "Parameter 'privileges' should be a not empty string", true) + privileges = check_string(data["privileges"], "Parameter 'privileges' should be a string", true, true) return cmd, privileges end def change_password - raise InvalidPrivileges.new("Access denied for '#{current_user}'") if user == Devops::Model::User::ROOT_USER_NAME and current_user != Devops::Model::User::ROOT_USER_NAME body = create_object_from_json_body check_string(body["password"], "Parameter 'password' must be a not empty string") end def change_email - raise InvalidPrivileges.new("Access denied for '#{current_user}'") if user == Devops::Model::User::ROOT_USER_NAME and current_user != Devops::Model::User::ROOT_USER_NAME body = create_object_from_json_body check_string(body["email"], "Parameter 'email' must be a not empty string") end diff --git a/devops-service/app/api2/routes/key.rb b/devops-service/app/api2/routes/key.rb index 09a0449..a10e816 100644 --- a/devops-service/app/api2/routes/key.rb +++ b/devops-service/app/api2/routes/key.rb @@ -22,7 +22,7 @@ module Devops # ] app.get_with_headers "/keys", :headers => [:accept] do check_privileges("key", "r") - json Devops::API2_0::Handler::Key.new(request).keys.map(&:to_hash) + json Devops::API2_0::Handler::Key.new(request).keys.map{|k| h = k.to_hash; h.delete("path"); h} end # Create ssh key on devops server diff --git a/devops-service/app/api2/routes/project.rb b/devops-service/app/api2/routes/project.rb index 973bbc4c..e88b0b5 100644 --- a/devops-service/app/api2/routes/project.rb +++ b/devops-service/app/api2/routes/project.rb @@ -217,6 +217,27 @@ module Devops # - method : POST # - headers : # - Accept: application/json + # - body : + # { + # "identifier": "prod", + # "provider": "openstack", + # "flavor": "m1.small", + # "image": "image id", + # "subnets": [ + # "private" + # ], + # "groups": [ + # "default" + # ], + # "users": [ + # "user" + # ], + # "run_list": [ ], + # "expires": null + # } + # + # * *Returns* : + # 200 - Added app.post_with_headers "/project/:project/deploy_env", :headers => [:accept, :content_type] do |project| check_privileges("project", "w") res, env = Devops::API2_0::Handler::Project.new(request).add_deploy_env(project) @@ -235,7 +256,7 @@ module Devops json Devops::API2_0::Handler::Project.new(request).project_deploy_env(project, env) } - # Add or update deploy_env + # Update deploy_env, you can send few fields in the body # # * *Request* # - method : PUT @@ -266,7 +287,7 @@ module Devops deploy_env_hash["PUT"] = lambda{|id, deploy_env| check_privileges("project", "w") begin - res = Devops::API2_0::Handler::Project.new(request).add_or_update_deploy_env(id, deploy_env) + res = Devops::API2_0::Handler::Project.new(request).update_deploy_env(id, deploy_env) create_response(res, nil, 200) rescue InvalidRecord => e halt_response(e.message) @@ -293,6 +314,12 @@ module Devops } app.multi_routes "/project/:id/deploy_envs/:deploy_env", {}, deploy_env_hash + app.put_with_headers "/project/:id/deploy_env/:deploy_env/:field", :headers => [:accept, :content_type] do |project_id, deploy_env, field| + check_privileges("project", "w") + res = Devops::API2_0::Handler::Project.new(request).update_deploy_env_field(project_id, deploy_env, field) + create_response(res, nil, 200) + end + # Create project # # * *Request* diff --git a/devops-service/app/api2/routes/user.rb b/devops-service/app/api2/routes/user.rb index e9ec0eb..2ac0dbb 100644 --- a/devops-service/app/api2/routes/user.rb +++ b/devops-service/app/api2/routes/user.rb @@ -113,7 +113,9 @@ module Devops # * *Returns* : # 200 - Updated app.put_with_headers %r{\A/user/#{DevopsConfig::OBJECT_NAME}/email\z}, :headers => [:accept, :content_type] do |user| - check_privileges("user", "w") unless request.env['REMOTE_USER'] == user + current_user = request.env['REMOTE_USER'] + check_privileges("user", "w") unless current_user == user + raise InvalidPrivileges.new("Access denied for '#{current_user}'") if user == Devops::Model::User::ROOT_USER_NAME and current_user != Devops::Model::User::ROOT_USER_NAME Devops::API2_0::Handler::User.new(request).change_email(user) create_response("Updated") end @@ -133,7 +135,9 @@ module Devops # * *Returns* : # 200 - Updated app.put_with_headers %r{\A/user/#{DevopsConfig::OBJECT_NAME}/password\z}, :headers => [:accept, :content_type] do |user| - check_privileges("user", "w") unless request.env['REMOTE_USER'] == user + current_user = request.env['REMOTE_USER'] + check_privileges("user", "w") unless current_user == user + raise InvalidPrivileges.new("Access denied for '#{current_user}'") if user == Devops::Model::User::ROOT_USER_NAME and current_user != Devops::Model::User::ROOT_USER_NAME Devops::API2_0::Handler::User.new(request).change_password(user) create_response("Updated") end diff --git a/devops-service/core/devops-config.rb b/devops-service/core/devops-config.rb index 395b3ba..495a326 100644 --- a/devops-service/core/devops-config.rb +++ b/devops-service/core/devops-config.rb @@ -2,7 +2,7 @@ require "socket" class DevopsConfig - OBJECT_NAME = /[\w\-]+/ + OBJECT_NAME = /([\w\-]+)/ @@config = nil diff --git a/devops-service/db/mongo/connectors/project.rb b/devops-service/db/mongo/connectors/project.rb index 2e41b04..ce2ce58 100644 --- a/devops-service/db/mongo/connectors/project.rb +++ b/devops-service/db/mongo/connectors/project.rb @@ -104,13 +104,17 @@ module Connectors list( {'deploy_envs' => {'$elemMatch' => q}}, {:fields => {'deploy_envs' => {'$elemMatch' => q}}} ) end - def set_project_deploy_env_field(project_id, env, field, value) - @collection.update({"_id" => project_id, "deploy_envs.identifier" => env}, {"$set" => {"deploy_envs.$.#{field}" => value}}) + def set_project_deploy_env_field(project_id, env, field_value_hash) + set = {} + field_value_hash.each do |field, value| + set["deploy_envs.$.#{field}"] = value + end + @collection.update({"_id" => project_id, "deploy_envs.identifier" => env}, {"$set" => set}) end def set_project_env_run_list(project_id, env, run_list) Helpers::RunList.new(run_list).validate! - set_project_deploy_env_field(project_id, env, "run_list", run_list) + set_project_deploy_env_field(project_id, env, {"run_list" => run_list}) end def set_project_run_list(project_id, env, run_list) diff --git a/devops-service/db/mongo/models/deploy_env/cloud_deploy_env.rb b/devops-service/db/mongo/models/deploy_env/cloud_deploy_env.rb index 49eff30..f608421 100644 --- a/devops-service/db/mongo/models/deploy_env/cloud_deploy_env.rb +++ b/devops-service/db/mongo/models/deploy_env/cloud_deploy_env.rb @@ -12,7 +12,8 @@ module Devops class CloudDeployEnv < DeployEnvBase attr_accessor :flavor, :image, :subnets, :groups, :stack_template - +=begin +@Deprecated types :identifier => {:type => String, :empty => false}, :image => {:type => String, :empty => false}, :flavor => {:type => String, :empty => false}, @@ -23,6 +24,7 @@ module Devops :subnets => {:type => Array, :empty => true}, :groups => {:type => Array, :empty => false}, :stack_template => {:type => String, :empty => false, :nil => true} +=end set_validators ::Validators::DeployEnv::Flavor, ::Validators::DeployEnv::Image, @@ -31,6 +33,22 @@ module Devops ::Validators::DeployEnv::Groups, ::Validators::DeployEnv::StackTemplate # set_validators ::Validators::DeployEnv::CloudParameters + set_field_validators :flavor, ::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::Flavor + set_field_validators :image, ::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::Image + set_field_validators :subnets, ::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::Array +# ::Validators::FieldValidator::Subnets.new + set_field_validators :groups, ::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::Array +# ::Validators::FieldValidator::Groups.new + set_field_validators :stack_template, ::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty, +# ::Validators::FieldValidator::StackTemplate.new def initialize d={} super(d) 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 4d8eb29..d69caff 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,9 +1,6 @@ require "db/mongo/models/mongo_model" require "providers/provider_factory" require "db/mongo/models/model_with_provider" -require "db/validators/deploy_env/run_list" -require "db/validators/deploy_env/expiration" -require "db/validators/deploy_env/users" module Devops module Model @@ -17,6 +14,22 @@ module Devops ::Validators::DeployEnv::Expiration, ::Validators::DeployEnv::Users + set_field_validators :identifier, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty, + ::Validators::FieldValidator::Name + + set_field_validators :run_list, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::Array, + ::Validators::FieldValidator::RunList + + set_field_validators :users, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::Array + + set_field_validators :expires, ::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::Expires + def initialize d={} self.identifier = d["identifier"] b = d["run_list"] || [] @@ -41,12 +54,40 @@ module Devops self.users = (self.users + users).uniq end + def rename project_id, new_name + old_name = self.identifier + self.identifier = new_name + self.validate_identifier! + begin + project = Devops::Db.connector.project(project_id) + project.deploy_env(self.identifier) + raise InvalidRecord.new("Environment with identifier '#{new_name}' already exist in project '#{project_id}'") + rescue RecordNotFound => e + res = create_role(project_id) + knife = knife_instance + old_role_name = knife.role_name(project_id, old_name) + self.run_list.delete("role[#{old_role_name}]") + role = res[:new] || res[:exist] + self.run_list << "role[#{role[0]}]" unless role.nil? + Devops::Db.connector.set_project_deploy_env_field(project_id, old_name, {"identifier" => new_name, "run_list" => self.run_list}) + msg = "Project '#{project_id}': environment '#{old_name}' has been renamed to '#{new_name}'." + Project.create_roles_response(res) + DevopsLogger.logger.info(msg) + msg + end + end + + def update_field project_id, field, value + self.send(field + "=", value) + self.send("validate_" + field + "!") + Devops::Db.connector.set_project_deploy_env_field(project_id, self.identifier, {field => value}) + end + def build_error_message(message) "Deploy environment '#{self.identifier}'. " + message end def create_role project_id - knife = KnifeFactory.instance + knife = knife_instance if knife.nil? DevopsLogger.logger.error "Can not get knife instance" return nil @@ -56,25 +97,29 @@ module Devops if all_roles.nil? msg = "Can't get roles list from chef" DevopsLogger.logger.error msg - return {error: msg} + return {error: [msg]} end role_name = knife.role_name(project_id, self.identifier) begin if all_roles.include? role_name - info[:exist] = role_name + info[:exist] = [role_name] else knife.create_role role_name, project_id, self.identifier - info[:new] = role_name + info[:new] = [role_name] DevopsLogger.logger.info "Role '#{role_name}' created" end self.run_list << "role[#{role_name}]" rescue => er - info[:error] = role_name + info[:error] = [role_name] DevopsLogger.logger.error "Role '#{role_name}' can not be created: #{er.message}" end info end + def knife_instance + KnifeFactory.instance + end + end end end diff --git a/devops-service/db/mongo/models/deploy_env/deploy_env_ec2.rb b/devops-service/db/mongo/models/deploy_env/deploy_env_ec2.rb index 43f5a61..39a455a 100644 --- a/devops-service/db/mongo/models/deploy_env/deploy_env_ec2.rb +++ b/devops-service/db/mongo/models/deploy_env/deploy_env_ec2.rb @@ -4,6 +4,8 @@ module Devops module Model class DeployEnvEc2 < CloudDeployEnv +=begin +@Deprecated types :identifier => {:type => String, :empty => false}, :image => {:type => String, :empty => false}, :flavor => {:type => String, :empty => false}, @@ -14,6 +16,7 @@ module Devops :subnets => {:type => Array, :empty => true}, :groups => {:type => Array, :empty => false}, :stack_template => {:type => String, :empty => false, :nil => true} +=end =begin set_validators ::Validators::DeployEnv::RunList, diff --git a/devops-service/db/mongo/models/image.rb b/devops-service/db/mongo/models/image.rb index 5f3364c..728a66a 100644 --- a/devops-service/db/mongo/models/image.rb +++ b/devops-service/db/mongo/models/image.rb @@ -1,19 +1,54 @@ require "db/mongo/models/mongo_model" require "db/validators/image/bootstrap_template" require "db/validators/image/image_in_filter" +require "db/mongo/models/model_with_provider" module Devops module Model class Image < MongoModel + include ModelWithProvider - attr_accessor :id, :provider, :remote_user, :name, :bootstrap_template + attr_accessor :id, :remote_user, :name, :bootstrap_template +=begin types :id => {:type => String, :empty => false}, :provider => {:type => String, :empty => false}, :remote_user => {:type => String, :empty => false}, :name => {:type => String, :empty => true}, :bootstrap_template => {:type => String, :empty => false, :nil => true} - set_validators ::Validators::Image::ImageInFilter, - ::Validators::Image::BootstrapTemplate +=end + +# set_validators ::Validators::Image::ImageInFilter, +# ::Validators::Image::BootstrapTemplate + + set_field_validators :id, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty, + ::Validators::FieldValidator::ImageName, + ::Validators::Image::ImageInFilter + + set_field_validators :remote_user, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty, + ::Validators::FieldValidator::Name + + set_field_validators :name, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty, + ::Validators::FieldValidator::ImageName + + set_field_validators :bootstrap_template, ::Validators::FieldValidator::Nil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty, + ::Validators::FieldValidator::Name, + ::Validators::Image::BootstrapTemplate + + def validate! + validate_id! + validate_provider! + validate_remote_user! + validate_name! + validate_bootstrap_template! + end def initialize p={} self.id = p["id"] diff --git a/devops-service/db/mongo/models/model_with_provider.rb b/devops-service/db/mongo/models/model_with_provider.rb index 41fe401..5314bae 100644 --- a/devops-service/db/mongo/models/model_with_provider.rb +++ b/devops-service/db/mongo/models/model_with_provider.rb @@ -6,6 +6,14 @@ module Devops attr_accessor :provider + def ModelWithProvider.included(mod) + + mod.set_field_validators :provider, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::NotEmpty, + ::Validators::FieldValidator::Provider + end + def provider_instance @provider_instance ||= Provider::ProviderFactory.get(self.provider) end diff --git a/devops-service/db/mongo/models/mongo_model.rb b/devops-service/db/mongo/models/mongo_model.rb index 7f64b05..7be13e7 100644 --- a/devops-service/db/mongo/models/mongo_model.rb +++ b/devops-service/db/mongo/models/mongo_model.rb @@ -55,7 +55,7 @@ module Devops def validate! begin # TODO: we should validate type in request parser - self.validate_fields_types +# self.validate_fields_types self.class.validate_model(self) true rescue InvalidRecord => e @@ -120,13 +120,17 @@ module Devops end @validators = [] +# @field_validators = [] class << self attr_accessor :validators +# attr_accessor :field_validators def inherited(subclass) subclass.validators = [] subclass.validators += self.validators +# subclass.field_validators = [] +# subclass.field_validators += self.field_validators end # all exceptions are handled in @validate! method @@ -136,6 +140,16 @@ module Devops end end + # validate field value + # if method validate! returns false, then stop validation without error + def set_field_validators field, *validators + define_method("validate_" + field.to_s + "!") do + validators.each do |validator| + break unless validator.new(self, send(field)).validate! + end + end + end + # private class methods private diff --git a/devops-service/db/mongo/models/project.rb b/devops-service/db/mongo/models/project.rb index 48f99b6..6e9e674 100644 --- a/devops-service/db/mongo/models/project.rb +++ b/devops-service/db/mongo/models/project.rb @@ -67,7 +67,7 @@ module Devops 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 - create_roles_response(res) + Project.create_roles_response(res) end def add_authorized_user user, env=nil @@ -210,7 +210,7 @@ module Devops end end - def create_roles_response roles + def self.create_roles_response roles if roles.is_a?(String) roles else diff --git a/devops-service/db/mongo/models/user.rb b/devops-service/db/mongo/models/user.rb index b4ded68..b16e032 100644 --- a/devops-service/db/mongo/models/user.rb +++ b/devops-service/db/mongo/models/user.rb @@ -17,6 +17,15 @@ module Devops :email => {:type => String, :empty => false}, :password => {:type => String, :empty => true} + set_field_validators :id, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String, + ::Validators::FieldValidator::Name + set_field_validators :password, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String + set_field_validators :email, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::String + set_field_validators :privileges, ::Validators::FieldValidator::NotNil, + ::Validators::FieldValidator::FieldType::Hash def initialize p={} self.id = p['username'] self.email = p['email'] @@ -24,6 +33,13 @@ module Devops self.privileges = p["privileges"] || self.default_privileges end + def validate! + validate_id! + validate_password! + validate_email! + validate_privileges! + end + def all_privileges privileges_with_value("rwx") end @@ -33,6 +49,8 @@ module Devops end def grant cmd, priv='' + priv='' if priv.nil? + cmd='' if cmd.nil? if !priv.empty? and PRIVILEGES_REGEX.match(priv).to_s.empty? raise InvalidCommand.new "Invalid privileges '#{priv}'. Available values are '#{PRIVILEGES.join("', '")}'" end @@ -46,7 +64,7 @@ module Devops when "" self.privileges = self.default_privileges else - raise InvalidCommand.new "Unsupported command #{cmd}" unless self.all_privileges.include?(cmd) + raise InvalidCommand.new "Unsupported command '#{cmd}'" unless self.all_privileges.include?(cmd) self.privileges[cmd] = priv end end diff --git a/devops-service/db/validators/all.rb b/devops-service/db/validators/all.rb index 37f2e28..03257dd 100644 --- a/devops-service/db/validators/all.rb +++ b/devops-service/db/validators/all.rb @@ -3,6 +3,8 @@ module Validators module DeployEnv; end module Key; end module Image; end + + module FieldValidator; end end require "db/validators/base" @@ -10,7 +12,8 @@ require "db/validators/base" 'db/validators/helpers/*.rb', 'db/validators/deploy_env/*.rb', 'db/validators/key/*.rb', - 'db/validators/image/*.rb' + 'db/validators/image/*.rb', + 'db/validators/field_validators/*.rb' ].each do |files_regexp| Dir[files_regexp].each {|file| require file } end diff --git a/devops-service/db/validators/field_validators/base.rb b/devops-service/db/validators/field_validators/base.rb new file mode 100644 index 0000000..8c60d57 --- /dev/null +++ b/devops-service/db/validators/field_validators/base.rb @@ -0,0 +1,25 @@ +module Validators + module FieldValidator + class Base + + def initialize model, value + @model = model + @value = value + end + + def validate! + raise InvalidRecord.new(self.message) unless self.valid? + true + end + + def valid? + raise 'override me' + end + + def message + raise 'override me' + end + end + end +end + diff --git a/devops-service/db/validators/field_validators/expires.rb b/devops-service/db/validators/field_validators/expires.rb new file mode 100644 index 0000000..101cc5a --- /dev/null +++ b/devops-service/db/validators/field_validators/expires.rb @@ -0,0 +1,19 @@ +require_relative "base" + +module Validators + module FieldValidator + class Expires < Base + + EXPIRES_REGEXP = /^[0-9]+[smhdw]$/ + + def valid? + !@value.match(EXPIRES_REGEXP).nil? + end + + def message + "Invalid value, it should contains symbols '0-9smhdw'" + end + end + end +end + diff --git a/devops-service/db/validators/field_validators/field_type.rb b/devops-service/db/validators/field_validators/field_type.rb new file mode 100644 index 0000000..f90d191 --- /dev/null +++ b/devops-service/db/validators/field_validators/field_type.rb @@ -0,0 +1,62 @@ +require_relative "base" + +module Validators + module FieldValidator + class FieldType < Base + + def valid? + @value.is_a?(type) + #TODO: strip string + #value.strip! if value.is_a?(String) + end + + def message + "Invalid value, it should be a #{type_name}" + end + + class String < FieldType + + def type + ::String + end + + def type_name + "string" + end + end + + class Array < FieldType + + def type + ::Array + end + + def type_name + "array" + end + + def message + "Invalid value, it should be an #{type_name}" + end + + end + + class Hash < FieldType + + def type + ::Hash + end + + def type_name + "object" + end + + def message + "Invalid value, it should be an #{type_name}" + end + end + + end + end +end + diff --git a/devops-service/db/validators/field_validators/flavor.rb b/devops-service/db/validators/field_validators/flavor.rb new file mode 100644 index 0000000..a06d104 --- /dev/null +++ b/devops-service/db/validators/field_validators/flavor.rb @@ -0,0 +1,18 @@ +require_relative "base" +module Validators + module FieldValidator + class Flavor < Base + + def valid? + @model.provider_instance.flavors.detect do |flavor| + flavor['id'] == @value + end + end + + def message + "Invalid flavor '#{@value}'." + end + end + end +end + diff --git a/devops-service/db/validators/field_validators/image.rb b/devops-service/db/validators/field_validators/image.rb new file mode 100644 index 0000000..275f1b8 --- /dev/null +++ b/devops-service/db/validators/field_validators/image.rb @@ -0,0 +1,22 @@ +require "commands/image" +require_relative "base" + +module Validators + module FieldValidator + class Image < Base + include ::ImageCommands + + def valid? + images = get_available_provider_images(::Devops::Db.connector, @model.provider) + images.detect do |image| + image["id"] == @value + end + end + + def message + "Invalid image '#{@value}'." + end + end + end +end + diff --git a/devops-service/db/validators/field_validators/image_name.rb b/devops-service/db/validators/field_validators/image_name.rb new file mode 100644 index 0000000..e886a53 --- /dev/null +++ b/devops-service/db/validators/field_validators/image_name.rb @@ -0,0 +1,18 @@ +require_relative "base" +module Validators + module FieldValidator + class ImageName < Base + + MAX_NAME_LEN = 100 + NAME_REGEX = /\A[\w\-\.]{1,#{MAX_NAME_LEN}}\z/ + + def valid? + !NAME_REGEX.match(@value).nil? + end + + def message + "Invalid value '#{@value}': it should contains symbols 'a-zA-Z0-9_-.' and length should be more then 1 and less or equals then #{MAX_NAME_LEN}" + end + end + end +end diff --git a/devops-service/db/validators/field_validators/name.rb b/devops-service/db/validators/field_validators/name.rb new file mode 100644 index 0000000..1319d85 --- /dev/null +++ b/devops-service/db/validators/field_validators/name.rb @@ -0,0 +1,18 @@ +require_relative "base" +module Validators + module FieldValidator + class Name < Base + + MAX_NAME_LEN = 200 + NAME_REGEX = /\A\w{1,#{MAX_NAME_LEN}}\z/ + + def valid? + !NAME_REGEX.match(@value).nil? + end + + def message + "Invalid value '#{@value}': it should contains symbols 'a-zA-Z0-9_' and length should be more then 1 and less or equals then #{MAX_NAME_LEN}" + end + end + end +end diff --git a/devops-service/db/validators/field_validators/nil.rb b/devops-service/db/validators/field_validators/nil.rb new file mode 100644 index 0000000..3a58dc1 --- /dev/null +++ b/devops-service/db/validators/field_validators/nil.rb @@ -0,0 +1,14 @@ +require_relative "base" + +module Validators + module FieldValidator + class Nil < Base + + def validate! + !@value.nil? + end + + end + end +end + diff --git a/devops-service/db/validators/field_validators/not_empty.rb b/devops-service/db/validators/field_validators/not_empty.rb new file mode 100644 index 0000000..2e9c550 --- /dev/null +++ b/devops-service/db/validators/field_validators/not_empty.rb @@ -0,0 +1,18 @@ +require_relative "base" + +module Validators + module FieldValidator + class NotEmpty < Base + + def valid? + !@value.empty? + end + + def message + "Value can not be empty" + end + + end + end +end + diff --git a/devops-service/db/validators/field_validators/not_nil.rb b/devops-service/db/validators/field_validators/not_nil.rb new file mode 100644 index 0000000..ef9f78e --- /dev/null +++ b/devops-service/db/validators/field_validators/not_nil.rb @@ -0,0 +1,18 @@ +require_relative "base" + +module Validators + module FieldValidator + class NotNil < Base + + def valid? + !@value.nil? + end + + def message + "Value can not be undefined" + end + + end + end +end + diff --git a/devops-service/db/validators/field_validators/provider.rb b/devops-service/db/validators/field_validators/provider.rb new file mode 100644 index 0000000..0a9a7dc --- /dev/null +++ b/devops-service/db/validators/field_validators/provider.rb @@ -0,0 +1,18 @@ +require_relative "base" + +module Validators + module FieldValidator + class Provider < Base + + def valid? + @providers = ::Provider::ProviderFactory.providers + @providers.include?(@value) + end + + def message + "Invalid value, available values: '#{@providers.join("', '")}'" + end + end + end +end + diff --git a/devops-service/db/validators/field_validators/run_list.rb b/devops-service/db/validators/field_validators/run_list.rb new file mode 100644 index 0000000..35e9ecd --- /dev/null +++ b/devops-service/db/validators/field_validators/run_list.rb @@ -0,0 +1,13 @@ +require_relative "base" + +module Validators + module FieldValidator + class RunList < Base + + def validate! + Validators::Helpers::RunList.new(@value).validate! + end + + end + end +end diff --git a/devops-service/tests/features/step_definitions/http_queries_steps.rb b/devops-service/tests/features/step_definitions/http_queries_steps.rb index 5cfa911..d802ed9 100644 --- a/devops-service/tests/features/step_definitions/http_queries_steps.rb +++ b/devops-service/tests/features/step_definitions/http_queries_steps.rb @@ -6,6 +6,11 @@ When(/^I send GET '(.*)' query$/) do |path| get(path, {}, DEFAULT_HEADERS) end +When(/^I send GET '(.*)' query with header 'Accept' value '(.*)'$/) do |path, hv| + headers = {"Accept" => hv} + get(path, {}, headers) +end + When(/^I send GET '(.*)' query with user without privileges$/) do |path| get_without_privileges(path, {}, DEFAULT_HEADERS) end @@ -31,9 +36,16 @@ When(/^I send POST '(.*)' query with JSON body$/) do |path, body| res = post_body(path, body, DEFAULT_HEADERS) end -When(/^I send POST '(.*)' query with body with header 'Accept' value '(.*)'$/) do |path, hv, body| +When(/^I send POST '(.*)' query with JSON body with header '(.*)' value '(.*)'$/) do |path, header, hv, body| + JSON.parse(body) unless body.strip.empty? headers = DEFAULT_HEADERS.clone - headers["Accept"] = hv + headers[header] = hv + res = post_body(path, body, headers) +end + +When(/^I send POST '(.*)' query with body with header '(.*)' value '(.*)'$/) do |path, header, hv, body| + headers = DEFAULT_HEADERS.clone + headers[header] = hv res = post_body(path, body, headers) end @@ -57,13 +69,19 @@ When(/^I send DELETE '(.*)' query$/) do |path| delete(path, {}, DEFAULT_HEADERS) end -When(/^I send DELETE '(.*)' query with JSON body with header 'Accept' value '(.*)'$/) do |path, hv, body| +When(/^I send DELETE '(.*)' query with JSON body with header '(.*)' value '(.*)'$/) do |path, header, hv, body| JSON.parse(body) unless body.strip.empty? headers = DEFAULT_HEADERS.clone - headers["Accept"] = hv + headers[header] = hv res = delete_body(path, body, headers) end +When(/^I send DELETE '(.*)' query with header '(.*)' value '(.*)'$/) do |path, header, hv| + headers = DEFAULT_HEADERS.clone + headers[header] = hv + res = delete_body(path, nil, headers) +end + When(/^I send DELETE '(.*)' query with JSON body$/) do |path, body| JSON.parse(body) unless body.strip.empty? res = delete_body(path, body, DEFAULT_HEADERS) @@ -99,10 +117,10 @@ When(/^I send PUT '(.*)' query with user without privileges$/) do |path| put_without_privileges(path, {}, DEFAULT_HEADERS) end -When(/^I send PUT '(.*)' query with JSON body with header 'Accept' value '(.*)'$/) do |path, hv, body| +When(/^I send PUT '(.*)' query with JSON body with header '(.*)' value '(.*)'$/) do |path, header, hv, body| JSON.parse(body) unless body.strip.empty? headers = DEFAULT_HEADERS.clone - headers["Accept"] = hv + headers[header] = hv res = put_body(path, body, headers) end diff --git a/devops-service/tests/features/step_definitions/json_steps.rb b/devops-service/tests/features/step_definitions/json_steps.rb index ce6956f..42cbe45 100644 --- a/devops-service/tests/features/step_definitions/json_steps.rb +++ b/devops-service/tests/features/step_definitions/json_steps.rb @@ -1,5 +1,5 @@ Then(/^response array should contains elements like:$/) do |string| - src = JSON.parse(string).first + src = JSON.parse(string) array = JSON.parse(last_response.body) array.each do |e| src.each do |key, value| @@ -44,15 +44,14 @@ Then(/^response should be JSON object like:$/) do |string| end Then(/^the array should contains strings '(.*)'$/) do |string| - buf = string.split(",") + buf = string.split(",").map(&:strip) array = JSON.parse(last_response.body) - buf.each do |v| - assert array.include?(v), "Array should contains '#{v}'" - end + res = buf - array + assert res.empty?, "Response has no strings '#{res.join("', '")}'" end Then(/^the array should not contains strings '(.*)'$/) do |string| - buf = string.split(",") + buf = string.split(",").map(&:strip) array = JSON.parse(last_response.body) buf.each do |v| assert !array.include?(v), "Array should not contains '#{v}'" diff --git a/devops-service/tests/generate_tests.rb b/devops-service/tests/generate_tests.rb index 2d097d9..b797fd3 100755 --- a/devops-service/tests/generate_tests.rb +++ b/devops-service/tests/generate_tests.rb @@ -5,6 +5,7 @@ require "yaml" require "ostruct" require "fileutils" require "./templates/fixtures/fixture_formatter" +require "./templates/generators/path_scenarios_generator.rb" class Generator < OpenStruct @@ -15,7 +16,8 @@ class Generator < OpenStruct config_file = ENV["DEVOPS_FEATURES_GENERATOR_CONFIG"] || ENV["CONFIG"] || CONFIG @config = YAML.load_file(File.new(config_file)) load_fixtures() - super(:config => @config, :formatter => @formatter, :fixtures => @fixtures) + @generator = PathScenariosGenerator.new + super(:config => @config, :formatter => @formatter, :fixtures => @fixtures, :generator => @generator) end def configure! @@ -31,14 +33,18 @@ class Generator < OpenStruct templates.each do |input, output| puts "Input: #{input}" if File.exists?(input) - file_data = File.read(input) - if file_data.nil? - puts "Data of file '#{input}' is nil" - else - data = render(file_data) - dir = File.dirname(output) - FileUtils.mkdir_p(dir) unless File.exists?(dir) - File.open(output, "w") {|f| f.write(data)} + begin + file_data = File.read(input) + if file_data.nil? + puts "Data of file '#{input}' is nil" + else + data = render(file_data) + dir = File.dirname(output) + FileUtils.mkdir_p(dir) unless File.exists?(dir) + File.open(output, "w") {|f| f.write(data)} + end + rescue => e + puts "\tError: #{e.message}" end else puts "WARN: file '#{input}' does not exist" @@ -46,14 +52,22 @@ class Generator < OpenStruct end end - def clean!(feature_files) + def self.clean! + dir = "features/api_v2/" + if File.exists?(dir) + puts "Removing directory '#{dir}'" + FileUtils.rm_r(dir) + end + +=begin feature_files.each do |feature_file| if File.exists?(feature_file) - FileUtils.rm(feature_file) + FileUtils.rm_f(feature_file) else puts "WARN: file '#{feature_file}' does not exist" end end +=end end private @@ -63,10 +77,13 @@ class Generator < OpenStruct end def load_fixtures + puts "Load fixures:" @fixtures = {} Dir["templates/fixtures/*.yml"].each do |fixture_path| fixture_name = File.basename(fixture_path, '.yml') + print "\t#{fixture_path}..." @fixtures[fixture_name] = YAML.load_file(fixture_path) + puts " ok" end @formatter = FixtureFormatter.new(@fixtures) @@ -78,7 +95,14 @@ templates = { #list "templates/api_v2/00_list/flavor.feature.erb" => "features/api_v2/00_list/flavor.feature", "templates/api_v2/00_list/stack_preset.feature.erb" => "features/api_v2/00_list/stack_preset.feature", + "templates/api_v2/00_list/00_network.feature.erb" => "features/api_v2/00_list/00_network.feature", "templates/api_v2/00_list/10_user.feature.erb" => "features/api_v2/00_list/10_user.feature", + "templates/api_v2/00_list/10_group.feature.erb" => "features/api_v2/00_list/10_group.feature", + "templates/api_v2/00_list/10_bootstrap_template.feature.erb" => "features/api_v2/00_list/10_bootstrap_template.feature", + "templates/api_v2/00_list/10_filter.feature.erb" => "features/api_v2/00_list/10_filter.feature", + "templates/api_v2/00_list/20_image.feature.erb" => "features/api_v2/00_list/20_image.feature", + "templates/api_v2/00_list/20_key.feature.erb" => "features/api_v2/00_list/20_key.feature", + "templates/api_v2/00_list/30_project.feature.erb" => "features/api_v2/00_list/30_project.feature", #create "templates/api_v2/10_create/00_filter.feature.erb" => "features/api_v2/10_create/00_filter.feature", @@ -87,6 +111,7 @@ templates = { "templates/api_v2/10_create/10_image.feature.erb" => "features/api_v2/10_create/10_image.feature", "templates/api_v2/10_create/50_stack.feature.erb" => "features/api_v2/10_create/50_stack.feature", "templates/api_v2/10_create/20_project.feature.erb" => "features/api_v2/10_create/20_project.feature", + "templates/api_v2/10_create/21_deploy_env.feature.erb" => "features/api_v2/10_create/21_deploy_env.feature", "templates/api_v2/10_create/30_script.feature.erb" => "features/api_v2/10_create/30_script.feature", "templates/api_v2/10_create/40_deploy_env.feature.erb" => "features/api_v2/10_create/40_deploy_env.feature", "templates/api_v2/10_create/00_user.feature.erb" => "features/api_v2/10_create/00_user.feature", @@ -108,11 +133,10 @@ templates = { } -generator = Generator.new.configure! if ARGV.first != 'clean' + generator = Generator.new.configure! generator.generate!(templates) else - generator.clean!(templates.values) + Generator.clean! end - diff --git a/devops-service/tests/params.yml b/devops-service/tests/params.yml index e544e6e..40f0cef 100644 --- a/devops-service/tests/params.yml +++ b/devops-service/tests/params.yml @@ -7,30 +7,3 @@ path_prefix: "" username_without_privileges: "user_for_testing_" password_without_privileges: "test" -openstack: - flavor: "as_long_as_image" - image: "08093b30-8393-42c3-8fb3-c4df56deb967" - subnet: "subnet" - project: - name: "test_openstack" - env: "test" - -ec2: - flavor: "m1.small" - image: "ami-63071b0a" - subnet: "subnet" - project: - name: "test_ec2" - env: "test" - -static: - project: - name: "test_static" - env: "test" - -script: - name: "cucumber_test_script" - -user: - name: "cucumber_test" - diff --git a/devops-service/tests/templates/api_v2/00_list/00_network.feature.erb b/devops-service/tests/templates/api_v2/00_list/00_network.feature.erb new file mode 100644 index 0000000..41a3069 --- /dev/null +++ b/devops-service/tests/templates/api_v2/00_list/00_network.feature.erb @@ -0,0 +1,42 @@ +@network @list +Feature: Networks + + <% @formatter.get_fixture('providers/without_static').each do |provider| %> + @<%= provider %> + Scenario: Get list of <%= provider %> networks + When I send GET '/v2.0/networks/<%= provider %>' query + Then response should be '200' + And the Content-Type header should include 'application/json' + And the JSON response should be an array + And response array should contains elements like: + """ + [ + <%= @formatter.json(provider + '/network', spaces: 6) %> + ] + """ + + @<%= provider %> + Scenario: Get list of <%= provider %> networks with header 'Accept' value is not 'application/json' + When I send GET '/v2.0/networks/<%= provider %>' query with header 'Accept' value 'application/xml' + Then response should be '406' + + <% end %> + + @static + Scenario: Get list of static networks + When I send GET '/v2.0/networks/static' query + Then response should be '200' + And the Content-Type header should include 'application/json' + And the JSON response should be an array + And response array should be empty + + <% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %> + <%= providers.join(" ") %> + Scenario: Get networks list of unknown provider + When I send GET '/v2.0/networks/foo' query + Then response should be '404' + + <%= providers.join(" ") %> + Scenario: Get networks list of unknown provider without privileges + When I send GET '/v2.0/networks/foo' query with user without privileges + Then response should be '401' diff --git a/devops-service/tests/templates/api_v2/00_list/10_bootstrap_template.feature.erb b/devops-service/tests/templates/api_v2/00_list/10_bootstrap_template.feature.erb new file mode 100644 index 0000000..94b74fa --- /dev/null +++ b/devops-service/tests/templates/api_v2/00_list/10_bootstrap_template.feature.erb @@ -0,0 +1,18 @@ +<% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %> +@list @bootstrap_template <%= providers.join(" ") %> +Feature: Bootstrap templates + + Scenario: Get list bootstrap templates + When I send GET '/v2.0/templates' query + Then response should be '200' + And the Content-Type header should include 'application/json' + And the JSON response should be an array + And the array elements should be strings + + Scenario: Get bootstrap templates list with header 'Accept' value is not 'application/json' + When I send GET '/v2.0/templates' query with header 'Accept' value 'application/xml' + Then response should be '406' + + Scenario: Get bootstrap template list without privileges + When I send GET '/v2.0/templates' query with user without privileges + Then response should be '401' diff --git a/devops-service/tests/templates/api_v2/00_list/10_filter.feature.erb b/devops-service/tests/templates/api_v2/00_list/10_filter.feature.erb new file mode 100644 index 0000000..37ea244 --- /dev/null +++ b/devops-service/tests/templates/api_v2/00_list/10_filter.feature.erb @@ -0,0 +1,32 @@ +@filter @list +Feature: Filters + + <% @formatter.get_fixture('providers/without_static').each do |provider| %> + @<%= provider %> + Scenario: Get list of <%= provider %> filters + When I send GET '/v2.0/filter/<%= provider %>/images' query + Then response should be '200' + And the Content-Type header should include 'application/json' + And the JSON response should be an array + + @<%= provider %> + Scenario: Get list of <%= provider %> filters with header 'Accept' value is not 'application/json' + When I send GET '/v2.0/filter/<%= provider %>/images' query with header 'Accept' value 'application/xml' + Then response should be '406' + + @<%= provider %> + Scenario: Get filter list for <%= provider %> provider without privileges + When I send GET '/v2.0/filter/<%= provider %>/images' query with user without privileges + Then response should be '401' + <% end %> + + @openstack @ec2 @static + Scenario: Get filter list of unknown provider + When I send GET '/v2.0/filter/foo/images' query + Then response should be '404' + + @openstack @ec2 @static + Scenario: Get filter list of unknown provider without privileges + When I send GET '/v2.0/filter/foo/images' query with user without privileges + Then response should be '401' + diff --git a/devops-service/tests/templates/api_v2/00_list/10_group.feature.erb b/devops-service/tests/templates/api_v2/00_list/10_group.feature.erb new file mode 100644 index 0000000..6f88caf --- /dev/null +++ b/devops-service/tests/templates/api_v2/00_list/10_group.feature.erb @@ -0,0 +1,32 @@ +@group @list +Feature: Groups + + <% @formatter.get_fixture('providers/without_static').each do |provider| %> + @<%= provider %> + Scenario: Get list of <%= provider %> groups + When I send GET '/v2.0/groups/<%= provider %>' query + Then response should be '200' + And the Content-Type header should include 'application/json' + And the JSON response should be an object + + @<%= provider %> + Scenario: Get list of <%= provider %> groups with header 'Accept' value is not 'application/json' + When I send GET '/v2.0/groups/<%= provider %>' query with header 'Accept' value 'application/xml' + Then response should be '406' + + @<%= provider %> + Scenario: Get groups list for <%= provider %> provider without privileges + When I send GET '/v2.0/groups/<%= provider %>' query with user without privileges + Then response should be '401' + <% end %> + + <% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %> + <%= providers.join(" ") %> + Scenario: Get groups list of unknown provider + When I send GET '/v2.0/groups/foo' query + Then response should be '404' + + <%= providers.join(" ") %> + Scenario: Get groups list of unknown provider without privileges + When I send GET '/v2.0/groups/foo' query with user without privileges + Then response should be '401' diff --git a/devops-service/tests/templates/api_v2/00_list/10_user.feature.erb b/devops-service/tests/templates/api_v2/00_list/10_user.feature.erb index 159e380..e8f5dc2 100644 --- a/devops-service/tests/templates/api_v2/00_list/10_user.feature.erb +++ b/devops-service/tests/templates/api_v2/00_list/10_user.feature.erb @@ -1,4 +1,5 @@ -@user +<% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %> +@list @user <%= providers.join(" ") %> Feature: list user Scenario: Get list of all users @@ -9,27 +10,14 @@ Feature: list user And response array should contains elements like: """ [ - { - "email": "test@test.test", - "privileges": { - "flavor": "rwx", - "group": "rwx", - "image": "rwx", - "project": "rwx", - "server": "rwx", - "key": "rwx", - "user": "rwx", - "filter": "rwx", - "network": "rwx", - "provider": "rwx", - "script": "rwx", - "templates": "rwx" - }, - "id": "test" - } + <%= @formatter.json('user/show', spaces: 6) %> ] """ + Scenario: Get list of all users + When I send GET '/v2.0/users' query with header 'Accept' value 'application/xml' + Then response should be '406' + Scenario: Get list of all users without privileges When I send GET '/v2.0/users' query with user without privileges Then response should be '401' diff --git a/devops-service/tests/templates/api_v2/00_list/20_image.feature.erb b/devops-service/tests/templates/api_v2/00_list/20_image.feature.erb new file mode 100644 index 0000000..a982da2 --- /dev/null +++ b/devops-service/tests/templates/api_v2/00_list/20_image.feature.erb @@ -0,0 +1,106 @@ +@image @list +Feature: List images + + <% @formatter.get_fixture('providers/without_static').each do |provider| %> + @<%= provider %> + Scenario: Get list mages with provider <%= provider %> + When I send GET '/v2.0/images?provider=<%= provider %>' query + Then response should be '200' + And the Content-Type header should include 'application/json' + And the JSON response should be an array + And response array should contains elements like: + """ + <%= @formatter.json(provider + '/image') %> + """ + + @<%= provider %> + Scenario: Get list of <%= provider %> images with header 'Accept' value is not 'application/json' + When I send GET '/v2.0/images?provider=<%= provider %>' query with header 'Accept' value 'application/xml' + Then response should be '406' + + @<%= provider %> + Scenario: Get images list for <%= provider %> provider without privileges + When I send GET '/v2.0/images?provider=<%= provider %>' query with user without privileges + Then response should be '401' + + @<%= provider %> + Scenario: Get images list of <%= provider %> provider + When I send GET '/v2.0/images/provider/<%= provider %>' query + Then response should be '200' + And the Content-Type header should include 'application/json' + And the JSON response should be an array + And response array should contains elements like: + """ + <%= @formatter.json(provider + '/provider_image') %> + """ + + @<%= provider %> + Scenario: Get list of <%= provider %> images with header 'Accept' value is not 'application/json' + When I send GET '/v2.0/images/provider/<%= provider %>' query with header 'Accept' value 'application/xml' + Then response should be '406' + + @<%= provider %> + Scenario: Get images list for <%= provider %> provider without privileges + When I send GET '/v2.0/images/provider/<%= provider %>' query with user without privileges + Then response should be '401' + + <% end %> + + @static + Scenario: Get list of static provider images + When I send GET '/v2.0/images?provider=static' query + Then response should be '200' + And the Content-Type header should include 'application/json' + And the JSON response should be an array + And response array should be empty + + @static + Scenario: Get list of static images with header 'Accept' value is not 'application/json' + When I send GET '/v2.0/images?provider=static' query with header 'Accept' value 'application/xml' + Then response should be '406' + + @static + Scenario: Get images list for static provider without privileges + When I send GET '/v2.0/images?provider=static' query with user without privileges + Then response should be '401' + + <% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %> + <%= providers.join(" ") %> + Scenario: Get images list of unknown provider + When I send GET '/v2.0/images?provider=foo' query + Then response should be '400' + + <%= providers.join(" ") %> + Scenario: Get images list without privileges + When I send GET '/v2.0/images' query with user without privileges + Then response should be '401' + + <%= providers.join(" ") %> + Scenario: Get groups list of unknown provider without privileges + When I send GET '/v2.0/images?provider=foo' query with user without privileges + Then response should be '401' + + <%= providers.join(" ") %> + Scenario: Get list of all images - invalid path + When I send GET '/v2.0/images/foo' query + Then response should be '404' + + <%= providers.join(" ") %> + Scenario: Get list of images of unknown provider + When I send GET '/v2.0/images/provider/foo' query + Then response should be '404' + + <%= providers.join(" ") %> + Scenario: Get unknown image + When I send GET '/v2.0/image/foo' query + Then response should be '404' + + <%= providers.join(" ") %> + Scenario: Get unknown image without privileges + When I send GET '/v2.0/image/foo' query with user without privileges + Then response should be '401' + + <%= providers.join(" ") %> + Scenario: Get image path + When I send GET '/v2.0/image' query + Then response should be '404' diff --git a/devops-service/tests/templates/api_v2/00_list/20_key.feature.erb b/devops-service/tests/templates/api_v2/00_list/20_key.feature.erb new file mode 100644 index 0000000..ba20fb4 --- /dev/null +++ b/devops-service/tests/templates/api_v2/00_list/20_key.feature.erb @@ -0,0 +1,21 @@ +<% providers = @formatter.get_fixture('providers/all').map{|p| "@#{p}"} %> +@key @list <%= providers.join(" ") %> +Feature: List keys + + Scenario: Get keys + When I send GET '/v2.0/keys' query + Then response should be '200' + And the Content-Type header should include 'application/json' + And the JSON response should be an array + And response array should contains elements like: + """ + <%= @formatter.json('key/list_element') %> + """ + + Scenario: Get keys list with header 'Accept' value is not 'application/json' + When I send GET '/v2.0/keys' query with header 'Accept' value 'application/xml' + Then response should be '406' + + Scenario: Get keys list without privileges + When I send GET '/v2.0/keys' query with user without privileges + Then response should be '401' diff --git a/devops-service/tests/templates/api_v2/00_list/30_project.feature.erb b/devops-service/tests/templates/api_v2/00_list/30_project.feature.erb new file mode 100644 index 0000000..792482e --- /dev/null +++ b/devops-service/tests/templates/api_v2/00_list/30_project.feature.erb @@ -0,0 +1,6 @@ +<% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %> +@project @list <%= providers.join(" ") %> +Feature: List projects + + <%= @generator.generate_get_path_scenarios("Show project types", "/v2.0/project_types") {%Q(And the JSON response should be an array\n And the array elements should be strings)} %> + diff --git a/devops-service/tests/templates/api_v2/00_list/flavor.feature.erb b/devops-service/tests/templates/api_v2/00_list/flavor.feature.erb index c61d20f..a3aa947 100644 --- a/devops-service/tests/templates/api_v2/00_list/flavor.feature.erb +++ b/devops-service/tests/templates/api_v2/00_list/flavor.feature.erb @@ -1,42 +1,26 @@ -@flavor +@flavor @list Feature: Flavors - @openstack - Scenario: Get list of openstack flavors - When I send GET '/v2.0/flavors/openstack' query + <% @formatter.get_fixture('providers/without_static').each do |provider| %> + @<%= provider %> + Scenario: Get list of <%= provider %> flavors + When I send GET '/v2.0/flavors/<%= provider %>' query Then response should be '200' And the Content-Type header should include 'application/json' And the JSON response should be an array And response array should contains elements like: """ [ - { - "id": "flavor_id", - "v_cpus": "v_cpus", - "ram": "ram", - "disk": "disk" - } + <%= @formatter.json(provider + '/flavor', spaces: 6) %> ] """ - @ec2 - Scenario: Get list of ec2 flavors - When I send GET '/v2.0/flavors/ec2' query - Then response should be '200' - And the Content-Type header should include 'application/json' - And the JSON response should be an array - And response array should contains elements like: - """ - [ - { - "id": "t1.micro", - "cores": 2, - "disk": 0, - "name": "Micro Instance", - "ram": 613 - } - ] - """ + @<%= provider %> + Scenario: Get list of <%= provider %> flavors with header 'Accept' value is not 'application/json' + When I send GET '/v2.0/flavors/<%= provider %>' query with header 'Accept' value 'application/xml' + Then response should be '406' + + <% end %> @static Scenario: Get list of static flavors @@ -46,10 +30,13 @@ Feature: Flavors And the JSON response should be an array And response array should be empty + <% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %> + <%= providers.join(" ") %> Scenario: Get flavors list of unknown provider When I send GET '/v2.0/flavors/foo' query Then response should be '404' + <%= providers.join(" ") %> Scenario: Get flavors list of unknown provider without privileges When I send GET '/v2.0/flavors/foo' query with user without privileges Then response should be '401' diff --git a/devops-service/tests/templates/api_v2/00_list/stack_preset.feature.erb b/devops-service/tests/templates/api_v2/00_list/stack_preset.feature.erb index 973279d..f2c2311 100644 --- a/devops-service/tests/templates/api_v2/00_list/stack_preset.feature.erb +++ b/devops-service/tests/templates/api_v2/00_list/stack_preset.feature.erb @@ -1,4 +1,4 @@ -@stack_preset +@stack_preset @list Feature: stack template preset list Scenario: Get list of all stack template presets diff --git a/devops-service/tests/templates/api_v2/10_create/00_filter.feature.erb b/devops-service/tests/templates/api_v2/10_create/00_filter.feature.erb index 19ac70b..4885b8a 100644 --- a/devops-service/tests/templates/api_v2/10_create/00_filter.feature.erb +++ b/devops-service/tests/templates/api_v2/10_create/00_filter.feature.erb @@ -1,192 +1,74 @@ @filter @image @project Feature: Filters - @openstack - Scenario: Add openstack image filter with user without privileges - When I send PUT '/v2.0/filter/openstack/image' query with user without privileges + <% @formatter.get_fixture('providers/without_static').each do |provider| %> + <% image = @formatter.get_fixture(provider + "/image")["id"] %> + @<%= provider %> + Scenario: Add <%= provider %> images filter with user without privileges + When I send PUT '/v2.0/filter/<%= provider %>/image' query with user without privileges Then response should be '401' - @openstack - Scenario: Add openstack image filter with header 'Accept' value 'text/*' - When I send PUT '/v2.0/filter/openstack/image' query with JSON body with header 'Accept' value 'text/*' + @<%= provider %> + Scenario: Update images filter with JSON body with header 'Accept' value not 'application/json' + When I send PUT '/v2.0/filter/<%= provider %>/image' query with JSON body with header 'Accept' value 'application/xml' """ [ - "<%= @config["openstack"]["image"] %>" + "<%= image %>" ] """ Then response should be '406' - @openstack - Scenario: Add openstack image filter without header 'Content-Type' - When I send PUT '/v2.0/filter/openstack/image' query with JSON body without header 'Content-Type' + @<%= provider %> + Scenario: Add <%= provider %> image filter without header 'Content-Type' + When I send PUT '/v2.0/filter/<%= provider %>/image' query with JSON body without header 'Content-Type' """ [ - "<%= @config["openstack"]["image"] %>" + "<%= image %>" ] """ Then response should be '415' - @openstack - Scenario: Add openstack image filter, invalid body: empty - When I send PUT '/v2.0/filter/openstack/image' query with JSON body + <% ["", "{}", "[{}]", "[[]]", "[null]"].each do |body| %> + @<%= provider %> + Scenario: Add <%= provider %> image filter, invalid body: '<%= body %>' + When I send PUT '/v2.0/filter/<%= provider %>/image' query with JSON body """ + <%= body %> """ Then response should be '400' + <% end %> - @openstack - Scenario: Add openstack image filter, invalid body: hash - When I send PUT '/v2.0/filter/openstack/image' query with JSON body - """ - { - "foo": "foo" - } - """ - Then response should be '400' - - @openstack - Scenario: Add openstack image filter, invalid body: element is hash - When I send PUT '/v2.0/filter/openstack/image' query with JSON body - """ - [{ - "foo": "foo" - }] - """ - Then response should be '400' - - @openstack - Scenario: Add openstack image filter, invalid body: element is array - When I send PUT '/v2.0/filter/openstack/image' query with JSON body + @<%= provider %> + Scenario: Add <%= provider %> image filter + When I send PUT '/v2.0/filter/<%= provider %>/image' query with JSON body """ [ - [] - ] - """ - Then response should be '400' - - @openstack - Scenario: Add openstack image filter, invalid body: element is null - When I send PUT '/v2.0/filter/openstack/image' query with JSON body - """ - [ - null - ] - """ - Then response should be '400' - - @openstack - Scenario: Add openstack image filter - When I send PUT '/v2.0/filter/openstack/image' query with JSON body - """ - [ - "<%= @config["openstack"]["image"] %>" + "<%= image %>" ] """ Then response should be '200' And the Content-Type header should include 'application/json' And the JSON response should be an object - And the object should contains key 'images' with array and array should contains strings '<%= @config["openstack"]["image"] %>' + And the object should contains key 'images' with array and array should contains strings '<%= image %>' - @openstack - Scenario: Add openstack image filter with invalid JSON - When I send PUT '/v2.0/filter/openstack/image' query with body - """ - [ - "<%= @config["openstack"]["image"] %>", - ] - """ - Then response should be '400' - - @ec2 - Scenario: Add ec2 image filter with user without privileges - When I send PUT '/v2.0/filter/ec2/image' query with user without privileges - Then response should be '401' - - @ec2 - Scenario: Add ec2 image filter with header 'Accept' value 'text/*' - When I send PUT '/v2.0/filter/ec2/image' query with JSON body with header 'Accept' value 'text/*' - """ - [ - "<%= @config["ec2"]["image"] %>" - ] - """ - Then response should be '406' - - @ec2 - Scenario: Add ec2 image filter without header 'Content-Type' - When I send PUT '/v2.0/filter/ec2/image' query with JSON body without header 'Content-Type' - """ - [ - "<%= @config["ec2"]["image"] %>" - ] - """ - Then response should be '415' - - @ec2 - Scenario: Add ec2 image filter, invalid body: empty - When I send PUT '/v2.0/filter/ec2/image' query with JSON body - """ - """ - Then response should be '400' - - @ec2 - Scenario: Add ec2 image filter, invalid body: hash - When I send PUT '/v2.0/filter/ec2/image' query with JSON body - """ - { - "foo": "foo" - } - """ - Then response should be '400' - - @ec2 - Scenario: Add ec2 image filter, invalid body: element is hash - When I send PUT '/v2.0/filter/ec2/image' query with JSON body - """ - [{ - "foo": "foo" - }] - """ - Then response should be '400' - - @ec2 - Scenario: Add ec2 image filter, invalid body: element is array - When I send PUT '/v2.0/filter/ec2/image' query with JSON body - """ - [ - [] - ] - """ - Then response should be '400' - - @ec2 - Scenario: Add ec2 image filter, invalid body: element is null - When I send PUT '/v2.0/filter/ec2/image' query with JSON body - """ - [ - null - ] - """ - Then response should be '400' - - @ec2 - Scenario: Add ec2 image filter - When I send PUT '/v2.0/filter/ec2/image' query with JSON body - """ - [ - "<%= @config["ec2"]["image"] %>" - ] - """ + @<%= provider %> + Scenario: Get new <%= provider %> image filter and check value '<%= image %>' + When I send GET '/v2.0/filter/<%= provider %>/images' query Then response should be '200' And the Content-Type header should include 'application/json' - And the JSON response should be an object - And the object should contains key 'images' with array and array should contains strings '<%= @config["ec2"]["image"] %>' + And the JSON response should be an array + And the array elements should be strings + And the array should contains strings '<%= image %>' - @ec2 - Scenario: Add ec2 image filter with invalid JSON - When I send PUT '/v2.0/filter/ec2/image' query with body + @<%= provider %> + Scenario: Add <%= provider %> image filter with invalid JSON + When I send PUT '/v2.0/filter/<%= provider %>/image' query with body """ [ - "<%= @config["ec2"]["image"] %>", + "<%= image %>", ] """ Then response should be '400' + + <% end %> + diff --git a/devops-service/tests/templates/api_v2/10_create/00_key.feature.erb b/devops-service/tests/templates/api_v2/10_create/00_key.feature.erb index e322187..4f8faa7 100644 --- a/devops-service/tests/templates/api_v2/10_create/00_key.feature.erb +++ b/devops-service/tests/templates/api_v2/10_create/00_key.feature.erb @@ -1,34 +1,44 @@ -@key -Feature: Add new script +<% providers = @formatter.get_fixture('providers/all').map{|p| "@#{p}"} %> +@key <%= providers.join(" ") %> +Feature: Add new key - Scenario: Add new key without file_name + <% new_key = @formatter.get_fixture('key/new') %> + <% new_key.keys.each do |key| %> + <% [[], {}, nil].each do |value| %> + Scenario: Add new key with <%= key %> value <%= value %> When I send POST '/v2.0/key' query with JSON body """ - <%= @formatter.json('key/invalid/blank_file_name', spaces: 6) %> + <%= @formatter.json('key/new', {spaces: 4, value: {key => value}}) %> """ Then response should be '400' - And response error should be "Parameter 'file_name' must be a not empty string" + And response error should be "Parameter '<%= key %>' should be a not empty string" - Scenario: Add new key without key_name + Scenario: Add new key without <%= key %> When I send POST '/v2.0/key' query with JSON body """ - <%= @formatter.json('key/invalid/blank_key_name', spaces: 6) %> + <%= @formatter.json('key/new', {spaces: 4, without_field: key}) %> """ Then response should be '400' - And response error should be "Parameter 'key_name' should be a not empty string" + And response error should be "Parameter '<%= key %>' should be a not empty string" - Scenario: Add new key without content - When I send POST '/v2.0/key' query with JSON body + <% end #value %> + <% end %> + + Scenario: Add new key with header 'Accept' value is not 'application/json' + When I send POST '/v2.0/key' query with JSON body with header 'Accept' value 'application/xml' """ - <%= @formatter.json('key/invalid/blank_content', spaces: 6) %> + <%= @formatter.json('key/new') %> """ - Then response should be '400' - And response error should be "Parameter 'content' should be a not empty string" + Then response should be '406' + + Scenario: Add new key without privileges + When I send POST '/v2.0/key' query with user without privileges + Then response should be '401' Scenario: Add new key When I send POST '/v2.0/key' query with JSON body """ - <%= @formatter.json('key/valid', spaces: 6) %> + <%= @formatter.json('key/new') %> """ Then response should be '201' diff --git a/devops-service/tests/templates/api_v2/10_create/00_user.feature.erb b/devops-service/tests/templates/api_v2/10_create/00_user.feature.erb index caf4af5..d7056b8 100644 --- a/devops-service/tests/templates/api_v2/10_create/00_user.feature.erb +++ b/devops-service/tests/templates/api_v2/10_create/00_user.feature.erb @@ -4,32 +4,47 @@ Feature: create user Scenario: create user with user without privileges When I send POST '/v2.0/user' query with JSON body with user without privileges """ - { - "username": "<%= @config["user"]["name"] %>", - "email": "<%= @config["user"]["name"] %>@test.test", - "password": "<%= @config["user"]["name"] %>" - } + <%= @formatter.json('user/create', spaces: 4) %> """ Then response should be '401' Scenario: create user without header 'Content-Type' When I send POST '/v2.0/user' query with JSON body without header 'Content-Type' """ - { - "username": "<%= @config["user"]["name"] %>", - "email": "<%= @config["user"]["name"] %>@test.test", - "password": "<%= @config["user"]["name"] %>" - } + <%= @formatter.json('user/create', spaces: 4) %> """ Then response should be '415' + Scenario: create user with header 'Accept' value is not 'application/json' + When I send POST '/v2.0/user' query with body with header 'Accept' value 'application/xml' + """ + <%= @formatter.json('user/create', spaces: 4) %> + """ + Then response should be '406' + Scenario: create user, invalid body: empty When I send POST '/v2.0/user' query with JSON body """ """ Then response should be '400' - <% ["{}", "[]"].each do |k| %> + <% invalid_name = "foo]&" %> + Scenario: create user with invalid name '<% invalid_name %>' + When I send POST '/v2.0/user' query with JSON body + """ + <%= @formatter.json('user/create', {spaces: 4, value: {"username" => invalid_name}}) %> + """ + Then response should be '400' + + <% long_name = "a"*250 %> + Scenario: create user with long name '<% long_name %>' + When I send POST '/v2.0/user' query with JSON body + """ + <%= @formatter.json('user/create', {spaces: 4, value: {"username" => long_name}}) %> + """ + Then response should be '400' + + <% [{}, []].each do |k| %> Scenario: create user, invalid body: body is a '<%= k %>' When I send POST '/v2.0/user' query with JSON body """ @@ -38,85 +53,31 @@ Feature: create user Then response should be '400' <% end %> - <% elements = ["{}", "[]", "null" ] %> + <% elements = [{}, [], nil ] %> + <% fields = @formatter.get_fixture('user/create').keys.map{|k| k.to_s} %> + <% fields.each do |field| %> <% elements.each do |k| %> - Scenario: create user, invalid body: username is a '<%= k %>' + Scenario: create user, invalid body: <%= field %> is a '<%= k %>' When I send POST '/v2.0/user' query with JSON body """ - { - "username": <%= k %>, - "email": "<%= @config["user"]["name"] %>@test.test", - "password": "<%= @config["user"]["name"] %>" - } + <%= @formatter.json('user/create', {spaces: 4, value: {field => k}}) %> + """ + Then response should be '400' + + Scenario: create user, invalid body: without <%= field %> + When I send POST '/v2.0/user' query with JSON body + """ + <%= @formatter.json('user/create', {spaces: 4, without_field: field}) %> """ Then response should be '400' <% end %> - <% elements.each do |k| %> - Scenario: create user, invalid body: password is a '<%= k %>' - When I send POST '/v2.0/user' query with JSON body - """ - { - "username": "<%= @config["user"]["name"] %>", - "email": "<%= @config["user"]["name"] %>@test.test", - "password": <%= k %> - } - """ - Then response should be '400' - <% end %> - <% elements.each do |k| %> - Scenario: create user, invalid body: email is a '<%= k %>' - When I send POST '/v2.0/user' query with JSON body - """ - { - "username": "<%= @config["user"]["name"] %>", - "email": <%= k %>, - "password": "<%= @config["user"]["name"] %>" - } - """ - Then response should be '400' - - <% end %> - - Scenario: create user, invalid body: without username - When I send POST '/v2.0/user' query with JSON body - """ - { - "email": "<%= @config["user"]["name"] %>@test.test", - "password": "<%= @config["user"]["name"] %>" - } - """ - Then response should be '400' - - Scenario: create user, invalid body: without email - When I send POST '/v2.0/user' query with JSON body - """ - { - "username": "<%= @config["user"]["name"] %>", - "password": "<%= @config["user"]["name"] %>" - } - """ - Then response should be '400' - - Scenario: create user, invalid body: without password - When I send POST '/v2.0/user' query with JSON body - """ - { - "email": "<%= @config["user"]["name"] %>@test.test", - "username": "<%= @config["user"]["name"] %>" - } - """ - Then response should be '400' Scenario: create user When I send POST '/v2.0/user' query with JSON body """ - { - "username": "<%= @config["user"]["name"] %>", - "email": "<%= @config["user"]["name"] %>@test.test", - "password": "<%= @config["user"]["name"] %>" - } + <%= @formatter.json('user/create', spaces: 4) %> """ Then response should be '201' And the Content-Type header should include 'application/json' diff --git a/devops-service/tests/templates/api_v2/10_create/10_image.feature.erb b/devops-service/tests/templates/api_v2/10_create/10_image.feature.erb index fd2916e..3d065a2 100644 --- a/devops-service/tests/templates/api_v2/10_create/10_image.feature.erb +++ b/devops-service/tests/templates/api_v2/10_create/10_image.feature.erb @@ -1,552 +1,85 @@ @image @project Feature: Manage images - Scenario: Get list of all images - When I send GET '/v2.0/images' query - Then response should be '200' - And the Content-Type header should include 'application/json' - And the JSON response should be an array - And response array should contains elements like: - """ - [ - { - "provider": "foo_provider", - "name": "foo_name", - "remote_user": "foo_user", - "bootstrap_template": "foo_template", - "id": "foo_id" - } - ] - """ - - Scenario: Get list of all images without privileges - When I send GET '/v2.0/images' query with user without privileges - Then response should be '401' - - Scenario: Get list of all images - invalid path - When I send GET '/v2.0/images/foo' query - Then response should be '404' - - @openstack - Scenario: Get list of openstack images - When I send GET '/v2.0/images?provider=openstack' query - Then response should be '200' - And the Content-Type header should include 'application/json' - And the JSON response should be an array - And response array should contains elements like: - """ - [ - { - "provider": "foo_provider", - "name": "foo_name", - "remote_user": "foo_user", - "bootstrap_template": "foo_template", - "id": "foo_id" - } - ] - """ - - @openstack - Scenario: Get list of openstack images (provider) - When I send GET '/v2.0/images/provider/openstack' query - Then response should be '200' - And the Content-Type header should include 'application/json' - And the JSON response should be an array - - @openstack - Scenario: Get images list of openstack without privileges - When I send GET '/v2.0/images/provider/openstack' query with user without privileges - Then response should be '401' - - @ec2 - Scenario: Get list of ec2 images - When I send GET '/v2.0/images?provider=ec2' query - Then response should be '200' - And the Content-Type header should include 'application/json' - And the JSON response should be an array - And response array should contains elements like: - """ - [ - { - "provider": "foo_provider", - "name": "foo_name", - "remote_user": "foo_user", - "bootstrap_template": "foo_template", - "id": "foo_id" - } - ] - """ - - @ec2 - Scenario: Get list of ec2 images (provider) - When I send GET '/v2.0/images/provider/ec2' query - Then response should be '200' - And the Content-Type header should include 'application/json' - And the JSON response should be an array - - @ec2 - Scenario: Get images list of ec2 without privileges - When I send GET '/v2.0/images/provider/ec2' query with user without privileges - Then response should be '401' - - Scenario: Get list of images of unknown provider - When I send GET '/v2.0/images/provider/foo' query - Then response should be '404' - - Scenario: Get images list without privileges - When I send GET '/v2.0/images' query with user without privileges - Then response should be '401' - - Scenario: Get unknown image - When I send GET '/v2.0/image/foo' query - Then response should be '404' - - Scenario: Get unknown image without privileges - When I send GET '/v2.0/image/foo' query with user without privileges - Then response should be '401' - - @openstack - Scenario: Create openstack image with ec2 provider + <% providers = @formatter.get_fixture('providers/without_static') %> + <% providers.each do |provider| %> + <% other_providers = providers.clone - [provider] %> + <% other_providers.each do |oprovider| %> + @<%= provider %> + Scenario: Create <%= provider %> image with '<%= oprovider %>' provider (invalid image id for provider) When I send POST '/v2.0/image' query with JSON body """ - { - "provider": "ec2", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } + <%= @formatter.json(provider + '/image', {value: {"provider" => oprovider}}) %> """ Then response should be '400' - @openstack - Scenario: Create openstack image with invalid provider + <% end #other providers%> + <% image = @formatter.get_fixture(provider + '/image') %> + <% image.keys.each do |key| %> + <% [[], {}].each do |invalid_value| %> + @<%= provider %> + Scenario: Create <%= provider %> image with invalid <%= key %> value: '<%= invalid_value %>' When I send POST '/v2.0/image' query with JSON body """ - { - "provider": "foo", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } + <%= @formatter.json(provider + '/image', {value: {key => invalid_value}}) %> """ Then response should be '400' - @openstack - Scenario: Create openstack image with invalid provider - array + <% end #invalid values%> + + <% end # keys%> + <% (image.keys - ["bootstrap_template"]).each do |key| %> + @<%= provider %> + Scenario: Create <%= provider %> image with invalid <%= key %> value: 'nil' When I send POST '/v2.0/image' query with JSON body """ - { - "provider": ["foo"], - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } + <%= @formatter.json(provider + '/image', {value: {key => nil}}) %> """ Then response should be '400' - @openstack - Scenario: Create openstack image with invalid provider - hash + <% end %> + + <% (image.keys - ["name", "remote_user"]).each do |key| %> + @<%= provider %> + Scenario: Create <%= provider %> image with invalid <%= key %> value: 'foo' When I send POST '/v2.0/image' query with JSON body """ - { - "provider": {}, - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } + <%= @formatter.json(provider + '/image', {value: {key => "foo"}}) %> """ Then response should be '400' - @openstack - Scenario: Create openstack image with invalid name - hash - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "openstack", - "name": {}, - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' + <% end %> - @openstack - Scenario: Create openstack image with invalid name - array + @<%= provider %> + Scenario: Create <%= provider %> image When I send POST '/v2.0/image' query with JSON body """ - { - "provider": "openstack", - "name": [], - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' - - @openstack - Scenario: Create openstack image with invalid remote_user - hash - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": {}, - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' - - @openstack - Scenario: Create openstack image with invalid remote_user - array - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": [], - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' - - @openstack - Scenario: Create openstack image with invalid bootstrap_template - array - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": [], - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' - - @openstack - Scenario: Create openstack image with invalid bootstrap_template - hash - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": {}, - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' - - @openstack - Scenario: Create openstack image with invalid bootstrap_template - unknown - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "unknown", - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' - - @openstack - Scenario: Create openstack image with invalid id - array - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": [] - } - """ - Then response should be '400' - - @openstack - Scenario: Create openstack image with invalid id - hash - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": {} - } - """ - Then response should be '400' - - @openstack - Scenario: Create openstack image - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } + <%= @formatter.json(provider + '/image') %> """ Then response should be '201' And the Content-Type header should include 'application/json' - @ec2 - Scenario: Create ec2 image with openstack provider - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "openstack", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image with invalid provider - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "foo", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image with invalid provider - array - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": ["foo"], - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image with invalid provider - hash - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": {}, - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image with invalid name - hash - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "ec2", - "name": {}, - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image with invalid name - array - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "ec2", - "name": [], - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image with invalid remote_user - hash - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": {}, - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image with invalid remote_user - array - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": [], - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image with invalid bootstrap_template - array - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": [], - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image with invalid bootstrap_template - hash - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": {}, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image with invalid bootstrap_template - unknown - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": "unknown", - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image with invalid id - array - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": [] - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image with invalid id - hash - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": {} - } - """ - Then response should be '400' - - @ec2 - Scenario: Create ec2 image - When I send POST '/v2.0/image' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '201' - And the Content-Type header should include 'application/json' - - @ec2 - Scenario: Get info for single ec2 image - When I send GET '/v2.0/image/<%= @config["ec2"]["image"] %>' query + @<%= provider %> + Scenario: Check new <%= provider %> image + When I send GET '/v2.0/image/<%= image["id"] %>' query Then response should be '200' And the Content-Type header should include 'application/json' And the JSON response should be an object And response should be JSON object like: """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } + <%= @formatter.json(provider + '/image') %> """ - @ec2 - Scenario: Get ec2 image without privileges - When I send GET '/v2.0/image/<%= @config["ec2"]["image"] %>' query with user without privileges + @<%= provider %> + Scenario: Get <%= provider %> image without privileges + When I send GET '/v2.0/image/<%= image["id"] %>' query with user without privileges Then response should be '401' - @openstack - Scenario: Get info for single openstack image - When I send GET '/v2.0/image/<%= @config["openstack"]["image"] %>' query - Then response should be '200' - And the Content-Type header should include 'application/json' - And the JSON response should be an object - And response should be JSON object like: - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } - """ + @<%= provider %> + Scenario: Get list of <%= provider %> images with header 'Accept' value is not 'application/json' + When I send GET '/v2.0/image/<%= image["id"] %>' query with header 'Accept' value 'application/xml' + Then response should be '406' - @openstack - Scenario: Get openstack image without privileges - When I send GET '/v2.0/image/<%= @config["openstack"]["image"] %>' query with user without privileges - Then response should be '401' + <% end %> - Scenario: Get info for single unknown image - When I send GET '/v2.0/image/foo' query - Then response should be '404' - Scenario: Get image path - When I send GET '/v2.0/image' query - Then response should be '404' diff --git a/devops-service/tests/templates/api_v2/10_create/20_project.feature.erb b/devops-service/tests/templates/api_v2/10_create/20_project.feature.erb index 8b5ea2b..21d7782 100644 --- a/devops-service/tests/templates/api_v2/10_create/20_project.feature.erb +++ b/devops-service/tests/templates/api_v2/10_create/20_project.feature.erb @@ -1,32 +1,12 @@ -@project +<% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %> +@project <%= providers.join(" ") %> Feature: create project - @openstack - Scenario: Create project <%= @config["openstack"]["project"]["name"] %> + <% project = @formatter.get_fixture('project') %> + Scenario: Create project <%= project["name"] %> When I send POST '/v2.0/project' query with JSON body """ - { - "deploy_envs": [ - { - "identifier": "<%= @config["openstack"]["project"]["env"] %>", - "run_list": [], - "expires": null, - "provider": "openstack", - "users": [ - "<%= @config["username"] %>" - ], - "flavor": "<%= @config["openstack"]["flavor"] %>", - "image": "<%= @config["openstack"]["image"] %>", - "subnets": [ - "<%= @config["openstack"]["subnet"] %>" - ], - "groups": [ - "default" - ] - } - ], - "name": "<%= @config["openstack"]["project"]["name"] %>" - } + <%= @formatter.json('project') %> """ Then response should be '201' diff --git a/devops-service/tests/templates/api_v2/10_create/21_deploy_env.feature.erb b/devops-service/tests/templates/api_v2/10_create/21_deploy_env.feature.erb new file mode 100644 index 0000000..4de3e3a --- /dev/null +++ b/devops-service/tests/templates/api_v2/10_create/21_deploy_env.feature.erb @@ -0,0 +1,3 @@ +@project @deploy_env +Feature: create deploy env in project + diff --git a/devops-service/tests/templates/api_v2/20_update/00_user.feature.erb b/devops-service/tests/templates/api_v2/20_update/00_user.feature.erb index ca1af8b..5fe838a 100644 --- a/devops-service/tests/templates/api_v2/20_update/00_user.feature.erb +++ b/devops-service/tests/templates/api_v2/20_update/00_user.feature.erb @@ -1,13 +1,15 @@ @user Feature: change user privileges and password - <% %w{password email}.each do |k| %> - <% val = (k == "email" ? "#{@config["user"]["name"]}@test.test" : @config["user"]["name"]) %> + <% user_hash = @formatter.get_fixture('user/create') %> + <% username = user_hash["username"] %> + <% update_user_hash = @formatter.get_fixture('user/update') %> + <% update_user_hash.keys.each do |k| %> Scenario: change user <%= k %> with user without privileges - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>/<%= k %>' query with JSON body with user without privileges + When I send PUT '/v2.0/user/<%= username %>/<%= k %>' query with JSON body with user without privileges """ { - "<%= k %>": "<%= val %>" + "<%= k %>": "<%= update_user_hash[k] %>" } """ Then response should be '401' @@ -16,29 +18,29 @@ Feature: change user privileges and password When I send PUT '/v2.0/user/root/<%= k %>' query with JSON body """ { - "<%= k %>": "<%= val %>" + "<%= k %>": "<%= update_user_hash[k] %>" } """ Then response should be '401' Scenario: change user <%= k %> without header 'Content-Type' - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>/<%= k %>' query with JSON body without header 'Content-Type' + When I send PUT '/v2.0/user/<%= username %>/<%= k %>' query with JSON body without header 'Content-Type' """ { - "<%= k %>": "<%= val %>" + "<%= k %>": "<%= update_user_hash[k] %>" } """ Then response should be '415' Scenario: change user <%= k %>, invalid body: empty - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>/<%= k %>' query with JSON body + When I send PUT '/v2.0/user/<%= username %>/<%= k %>' query with JSON body """ """ Then response should be '400' - <% ["{}", "[]", ""].each do |body| %> + <% ["", "[]"].each do |body| %> Scenario: change user <%= k %>, invalid body: body is a '<%= body %>' - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>/<%= k %>' query with JSON body + When I send PUT '/v2.0/user/<%= username %>/<%= k %>' query with JSON body """ <%= body %> """ @@ -47,7 +49,7 @@ Feature: change user privileges and password <% elements = ["{}", "[]", "null" ] %> <% elements.each do |value| %> Scenario: change user <%= k %>, invalid body: <%= k %> is a '<%= value %>' - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>/<%= k %>' query with JSON body + When I send PUT '/v2.0/user/<%= username %>/<%= k %>' query with JSON body """ { "<%= k %>": <%= value %> @@ -57,10 +59,10 @@ Feature: change user privileges and password <% end %> Scenario: change user <%= k %> - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>/<%= k %>' query with JSON body + When I send PUT '/v2.0/user/<%= username %>/<%= k %>' query with JSON body """ { - "<%= k %>": "<%= val %>" + "<%= k %>": "<%= update_user_hash[k] %>" } """ Then response should be '200' @@ -69,115 +71,93 @@ Feature: change user privileges and password <% end %> Scenario: change user privileges with user without privileges - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body with user without privileges + When I send PUT '/v2.0/user/<%= username %>' query with JSON body with user without privileges """ - {} + <%= @formatter.json('user/privileges', {spaces: 4}) %> """ Then response should be '401' Scenario: change root privileges When I send PUT '/v2.0/user/root' query with JSON body """ - {} + <%= @formatter.json('user/privileges', {spaces: 4}) %> """ Then response should be '401' Scenario: change user privileges without header 'Content-Type' - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body without header 'Content-Type' + When I send PUT '/v2.0/user/<%= username %>' query with JSON body without header 'Content-Type' """ - {} + <%= @formatter.json('user/privileges', {spaces: 4}) %> """ Then response should be '415' - <% ["[]", ""].each do |body| %> - Scenario: change user privileges, invalid body: body is a '<%= body %>' - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body + Scenario: change user privileges with header 'Accept' value is not application/json + When I send PUT '/v2.0/user/<%= username %>' query with JSON body with header 'Accept' value 'application/xml' """ - <%= body %> + <%= @formatter.json('user/privileges', {spaces: 4}) %> """ - Then response should be '400' - <% end %> + Then response should be '406' + <% elements = ["{}", "[]" ] %> <% elements.each do |value| %> Scenario: change user privileges, invalid body: cmd is a '<%= value %>' - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body + When I send PUT '/v2.0/user/<%= username %>' query with JSON body """ - { - "cmd": "<%= value %>", - "privileges": "r" - } + <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => value, "privileges" => "r"}}) %> """ Then response should be '400' Scenario: change user privileges, invalid body: privileges is a '<%= value %>' - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body + When I send PUT '/v2.0/user/<%= username %>' query with JSON body """ - { - "cmd": "all", - "privileges": "<%= value %>" - } + <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => "foo", "privileges" => value}}) %> """ Then response should be '400' <% end %> Scenario: change user privileges: foo - r - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body + When I send PUT '/v2.0/user/<%= username %>' query with JSON body """ - { - "cmd": "foo", - "privileges": "r" - } + <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => "foo", "privileges" => "r"}}) %> """ Then response should be '400' <% %w{foo, rr, rwwww, rwxxx, rwf}.each do |priv| %> Scenario: change user privileges: all - <%= priv %> When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body """ - { - "cmd": "all", - "privileges": "<%= priv %>" - } + <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => "all", "privileges" => priv}}) %> """ Then response should be '400' <% end %> - <% privs = %w{r w x rw rx wx rwx} %> - - <% %w{flavor group image project server key user filter network provider script templates all}.each do |cmd| %> + <% privs = @formatter.get_fixture('user/privileges_values') %> + <% (@formatter.get_fixture('user/privileges').keys.map(&:to_s) << "all").each do |cmd| %> <% privs.each do |priv| %> Scenario: change user privileges: <%= cmd %> - <%= priv %> - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body + When I send PUT '/v2.0/user/<%= username %>' query with JSON body """ - { - "cmd": "<%= cmd %>", - "privileges": "<%= priv %>" - } + <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => cmd, "privileges" => priv}}) %> """ Then response should be '200' <% end %> Scenario: change user privileges: <%= cmd %> - without privileges - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body + When I send PUT '/v2.0/user/<%= username %>' query with JSON body """ - { - "cmd": "<%= cmd %>" - } + <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => cmd}, without_field: "privileges"}) %> """ Then response should be '200' Scenario: change user privileges: <%= cmd %> - ' ' - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body + When I send PUT '/v2.0/user/<%= username %>' query with JSON body """ - { - "cmd": "<%= cmd %>", - "privileges": " " - } + <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => cmd, "privileges" => " "}}) %> """ Then response should be '400' <% end %> Scenario: change user privileges: set default privileges - When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body + When I send PUT '/v2.0/user/<%= username %>' query with JSON body """ { } diff --git a/devops-service/tests/templates/api_v2/20_update/10_image.feature.erb b/devops-service/tests/templates/api_v2/20_update/10_image.feature.erb index e0b48a9..6778035 100644 --- a/devops-service/tests/templates/api_v2/20_update/10_image.feature.erb +++ b/devops-service/tests/templates/api_v2/20_update/10_image.feature.erb @@ -1,171 +1,62 @@ @image @project Feature: Update images - @openstack - Scenario: Update openstack image with ec2 provider - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body + <% providers = @formatter.get_fixture('providers/without_static') %> + <% providers.each do |provider| %> + <% image = @formatter.get_fixture(provider + '/image') %> + <% other_providers = providers.clone - [provider] %> + <% other_providers.each do |oprovider| %> + @<%= provider %> + Scenario: Update <%= provider %> image with '<%= oprovider %>' provider (invalid image id for provider) + When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body """ - { - "provider": "ec2", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } + <%= @formatter.json(provider + '/image', {value: {"provider" => oprovider}}) %> """ Then response should be '400' - @openstack - Scenario: Update openstack image with invalid provider - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body + <% end #other providers%> + + <% (image.keys - ["id"]).each do |key| %> + <% [[], {}].each do |invalid_value| %> + @<%= provider %> + Scenario: Update <%= provider %> image with invalid <%= key %> value: '<%= invalid_value %>' + When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body """ - { - "provider": "foo", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } + <%= @formatter.json(provider + '/image', {value: {key => invalid_value}}) %> """ Then response should be '400' - @openstack - Scenario: Update openstack image with invalid provider - array - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body + <% end #invalid values%> + + <% end # keys%> + <% (image.keys - ["bootstrap_template", "id"]).each do |key| %> + @<%= provider %> + Scenario: Update <%= provider %> image with invalid <%= key %> value: 'nil' + When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body """ - { - "provider": ["foo"], - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } + <%= @formatter.json(provider + '/image', {value: {key => nil}}) %> """ Then response should be '400' - @openstack - Scenario: Update openstack image with invalid provider - hash - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body + <% end %> + + <% (image.keys - ["name", "remote_user", "id"]).each do |key| %> + @<%= provider %> + Scenario: Update <%= provider %> image with invalid <%= key %> value: 'foo' + When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body """ - { - "provider": {}, - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } + <%= @formatter.json(provider + '/image', {value: {key => "foo"}}) %> """ Then response should be '400' - @openstack - Scenario: Update openstack image with invalid name - hash - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body - """ - { - "provider": "openstack", - "name": {}, - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' + <% end %> - @openstack - Scenario: Update openstack image with invalid name - array - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body + <% [[], {}, "foo", nil].each do |value| %> + @<%= provider %> + Scenario: Update <%= provider %> image with invalid id value: '<%= value %>' + When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body """ - { - "provider": "openstack", - "name": [], - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' - - @openstack - Scenario: Update openstack image with invalid remote_user - hash - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": {}, - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' - - @openstack - Scenario: Update openstack image with invalid remote_user - array - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": [], - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' - - @openstack - Scenario: Update openstack image with invalid bootstrap_template - array - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": [], - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' - - @openstack - Scenario: Update openstack image with invalid bootstrap_template - hash - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": {}, - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' - - @openstack - Scenario: Update openstack image with invalid bootstrap_template - unknown - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "unknown", - "id": "<%= @config["openstack"]["image"] %>" - } - """ - Then response should be '400' - - @openstack - Scenario: Update openstack image with invalid id - array - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body - """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": [] - } + <%= @formatter.json(provider + '/image', {value: {"id" => value}}) %> """ Then response should be '200' And the Content-Type header should include 'application/json' @@ -173,21 +64,16 @@ Feature: Update images And response should be JSON object like: """ { - "message" : "Image '<%= @config["openstack"]["image"] %>' has been updated" + "message" : "Image '<%= image["id"] %>' has been updated" } """ - @openstack - Scenario: Update openstack image with invalid id - hash - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body + <% end %> + + Scenario: Update <%= provider %> image without id + When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": {} - } + <%= @formatter.json(provider + '/image', {without_field: "id"}) %> """ Then response should be '200' And the Content-Type header should include 'application/json' @@ -195,21 +81,15 @@ Feature: Update images And response should be JSON object like: """ { - "message" : "Image '<%= @config["openstack"]["image"] %>' has been updated" + "message" : "Image '<%= image["id"] %>' has been updated" } """ - @openstack - Scenario: Update openstack image - When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body + @<%= provider %> + Scenario: Update <%= provider %> image + When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body """ - { - "provider": "openstack", - "name": "freebsd-10.0", - "remote_user": "root", - "bootstrap_template": "chef_freebsd", - "id": "<%= @config["openstack"]["image"] %>" - } + <%= @formatter.json(provider + '/image') %> """ Then response should be '200' And the Content-Type header should include 'application/json' @@ -217,175 +97,15 @@ Feature: Update images And response should be JSON object like: """ { - "message" : "Image '<%= @config["openstack"]["image"] %>' has been updated" + "message" : "Image '<%= image["id"] %>' has been updated" } """ - @ec2 - Scenario: Update ec2 image with openstack provider - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body + @<%= provider %> + Scenario: Update <%= provider %> image with bootstrap_template null + When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body """ - { - "provider": "openstack", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Update ec2 image with invalid provider - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body - """ - { - "provider": "foo", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Update ec2 image with invalid provider - array - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body - """ - { - "provider": ["foo"], - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Update ec2 image with invalid provider - hash - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body - """ - { - "provider": {}, - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Update ec2 image with invalid name - hash - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body - """ - { - "provider": "ec2", - "name": {}, - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Update ec2 image with invalid name - array - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body - """ - { - "provider": "ec2", - "name": [], - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Update ec2 image with invalid remote_user - hash - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": {}, - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Update ec2 image with invalid remote_user - array - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": [], - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Update ec2 image with invalid bootstrap_template - array - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": [], - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Update ec2 image with invalid bootstrap_template - hash - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": {}, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Update ec2 image with invalid bootstrap_template - unknown - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": "unknown", - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '400' - - @ec2 - Scenario: Update ec2 image with invalid id - array - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": [] - } + <%= @formatter.json(provider + '/image', {value: {"bootstrap_template" => nil}}) %> """ Then response should be '200' And the Content-Type header should include 'application/json' @@ -393,21 +113,15 @@ Feature: Update images And response should be JSON object like: """ { - "message" : "Image '<%= @config["openstack"]["image"] %>' has been updated" + "message" : "Image '<%= image["id"] %>' has been updated" } """ - @ec2 - Scenario: Update ec2 image with invalid id - hash - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body + @<%= provider %> + Scenario: Update <%= provider %> image with old bootstrap_template: '<%= image["bootstrap_template"] %>' + When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": {} - } + <%= @formatter.json(provider + '/image', {value: {"bootstrap_template" => image["bootstrap_template"]}}) %> """ Then response should be '200' And the Content-Type header should include 'application/json' @@ -415,28 +129,9 @@ Feature: Update images And response should be JSON object like: """ { - "message" : "Image '<%= @config["openstack"]["image"] %>' has been updated" + "message" : "Image '<%= image["id"] %>' has been updated" } """ - @ec2 - Scenario: Update ec2 image - When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body - """ - { - "provider": "ec2", - "name": "test-ec2", - "remote_user": "ec2-user", - "bootstrap_template": null, - "id": "<%= @config["ec2"]["image"] %>" - } - """ - Then response should be '200' - And the Content-Type header should include 'application/json' - And the JSON response should be an object - And response should be JSON object like: - """ - { - "message" : "Image '<%= @config["openstack"]["image"] %>' has been updated" - } - """ + <% end #providers %> + diff --git a/devops-service/tests/templates/api_v2/90_delete/90_image.feature.erb b/devops-service/tests/templates/api_v2/90_delete/90_image.feature.erb index 6fa7eef..0f8538f 100644 --- a/devops-service/tests/templates/api_v2/90_delete/90_image.feature.erb +++ b/devops-service/tests/templates/api_v2/90_delete/90_image.feature.erb @@ -1,42 +1,37 @@ @image @project Feature: delete image - @openstack - Scenario: Delete openstack image with user without privileges - When I send DELETE '/v2.0/image/<%= @config["openstack"]["image"] %>' query with user without privileges + <% providers = @formatter.get_fixture('providers/without_static') %> + <% providers.each do |provider| %> + <% image = @formatter.get_fixture(provider + '/image') %> + @<%= provider %> + Scenario: Delete <%= provider %> image with user without privileges + When I send DELETE '/v2.0/image/<%= image["id"] %>' query with user without privileges Then response should be '401' - @openstack - Scenario: Delete openstack image - When I send DELETE '/v2.0/image/<%= @config["openstack"]["image"] %>' query + @<%= provider %> + Scenario: Delete <%= provider %> image + When I send DELETE '/v2.0/image/<%= image["id"] %>' query Then response should be '200' And the Content-Type header should include 'application/json' And the JSON response should be an object And response should be JSON object like: """ { - "message" : "Image '<%= @config["openstack"]["image"] %>' has been removed" + "message" : "Image '<%= image["id"] %>' has been removed" } """ - @ec2 - Scenario: Delete ec2 image with user without privileges - When I send DELETE '/v2.0/image/<%= @config["ec2"]["image"] %>' query with user without privileges - Then response should be '401' + @<%= provider %> + Scenario: Delete <%= provider %> image with header 'Accept' value is not 'application/json' + When I send DELETE '/v2.0/image/<%= image["id"] %>' query with header 'Accept' value 'application/xml' + Then response should be '406' - @ec2 - Scenario: Delete ec2 image - When I send DELETE '/v2.0/image/<%= @config["ec2"]["image"] %>' query - Then response should be '200' - And the Content-Type header should include 'application/json' - And the JSON response should be an object - And response should be JSON object like: - """ - { - "message" : "Image '<%= @config["ec2"]["image"] %>' has been removed" - } - """ + <% end #providers %> + + <% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %> + <%= providers.join(" ") %> Scenario: Delete unknown image When I send DELETE '/v2.0/image/foo' query Then response should be '404' diff --git a/devops-service/tests/templates/api_v2/90_delete/90_user.feature.erb b/devops-service/tests/templates/api_v2/90_delete/90_user.feature.erb index 3b67da7..3e9c6e7 100644 --- a/devops-service/tests/templates/api_v2/90_delete/90_user.feature.erb +++ b/devops-service/tests/templates/api_v2/90_delete/90_user.feature.erb @@ -1,16 +1,22 @@ @user Feature: delete user + <% user_hash = @formatter.get_fixture('user/create') %> + <% username = user_hash["username"] %> Scenario: delete user with user without privileges - When I send DELETE '/v2.0/user/<%= @config["user"]["name"] %>' query with user without privileges + When I send DELETE '/v2.0/user/<%= username %>' query with user without privileges Then response should be '401' Scenario: delete unknown user When I send DELETE '/v2.0/user/unknown' query Then response should be '404' + Scenario: delete user with header 'Accept' value is not 'application/json' + When I send DELETE '/v2.0/user/<%= username %>' query with header 'Accept' value 'application/xml' + Then response should be '406' + Scenario: delete user - When I send DELETE '/v2.0/user/<%= @config["user"]["name"] %>' query + When I send DELETE '/v2.0/user/<%= username %>' query Then response should be '200' And the Content-Type header should include 'application/json' diff --git a/devops-service/tests/templates/api_v2/90_delete/99_filter.feature.erb b/devops-service/tests/templates/api_v2/90_delete/99_filter.feature.erb index ff29efa..7958a23 100644 --- a/devops-service/tests/templates/api_v2/90_delete/99_filter.feature.erb +++ b/devops-service/tests/templates/api_v2/90_delete/99_filter.feature.erb @@ -1,153 +1,58 @@ @filter @image @project Feature: Filters - @openstack - Scenario: Delete openstack image filter with user without privileges - When I send DELETE '/v2.0/filter/openstack/image' query with user without privileges + <% @formatter.get_fixture('providers/without_static').each do |provider| %> + <% image = @formatter.get_fixture(provider + "/image")["id"] %> + @<%= provider %> + Scenario: Delete <%= provider %> image filter with user without privileges + When I send DELETE '/v2.0/filter/<%= provider %>/image' query with user without privileges Then response should be '401' - @openstack - Scenario: Delete openstack image filter without header 'Content-Type' - When I send DELETE '/v2.0/filter/openstack/image' query with JSON body without header 'Content-Type' + @<%= provider %> + Scenario: Delete images filter with header 'Accept' value not 'application/json' + When I send DELETE '/v2.0/filter/<%= provider %>/image' query with header 'Accept' value 'application/xml' + Then response should be '406' + + @<%= provider %> + Scenario: Delete <%= provider %> image filter without header 'Content-Type' + When I send DELETE '/v2.0/filter/<%= provider %>/image' query with JSON body without header 'Content-Type' """ [ - "<%= @config["openstack"]["image"] %>" + "<%= image %>" ] """ Then response should be '415' - @openstack - Scenario: Delete openstack image filter, invalid body: empty - When I send DELETE '/v2.0/filter/openstack/image' query with JSON body + <% ["", "{}", "[{}]", "[[]]", "[null]"].each do |body| %> + @<%= provider %> + Scenario: Delete <%= provider %> image filter, invalid body: empty + When I send DELETE '/v2.0/filter/<%= provider %>/image' query with JSON body """ + <%= body %> """ Then response should be '400' - @openstack - Scenario: Delete openstack image filter, invalid body: hash - When I send DELETE '/v2.0/filter/openstack/image' query with JSON body - """ - { - "foo": "foo" - } - """ - Then response should be '400' + <% end %> - @openstack - Scenario: Delete openstack image filter, invalid body: element is hash - When I send DELETE '/v2.0/filter/openstack/image' query with JSON body - """ - [{ - "foo": "foo" - }] - """ - Then response should be '400' - - @openstack - Scenario: Delete openstack image filter, invalid body: element is array - When I send DELETE '/v2.0/filter/openstack/image' query with JSON body + @<%= provider %> + Scenario: Delete <%= provider %> image filter + When I send DELETE '/v2.0/filter/<%= provider %>/image' query with JSON body """ [ - [] - ] - """ - Then response should be '400' - - @openstack - Scenario: Delete openstack image filter, invalid body: element is null - When I send DELETE '/v2.0/filter/openstack/image' query with JSON body - """ - [ - null - ] - """ - Then response should be '400' - - @openstack - Scenario: Delete openstack image filter - When I send DELETE '/v2.0/filter/openstack/image' query with JSON body - """ - [ - "<%= @config["openstack"]["image"] %>" + "<%= image %>" ] """ Then response should be '200' And the Content-Type header should include 'application/json' And the JSON response should be an object - And the object should contains key 'images' with array and array should not contains strings '<%= @config["openstack"]["image"] %>' + And the object should contains key 'images' with array and array should not contains strings '<%= image %>' - @ec2 - Scenario: Delete ec2 image filter with user without privileges - When I send DELETE '/v2.0/filter/ec2/image' query with user without privileges - Then response should be '401' - - @ec2 - Scenario: Delete ec2 image filter without header 'Content-Type' - When I send DELETE '/v2.0/filter/ec2/image' query with JSON body without header 'Content-Type' - """ - [ - "<%= @config["ec2"]["image"] %>" - ] - """ - Then response should be '415' - - @ec2 - Scenario: Delete ec2 image filter, invalid body: empty - When I send DELETE '/v2.0/filter/ec2/image' query with JSON body - """ - """ - Then response should be '400' - - @ec2 - Scenario: Delete ec2 image filter, invalid body: hash - When I send DELETE '/v2.0/filter/ec2/image' query with JSON body - """ - { - "foo": "foo" - } - """ - Then response should be '400' - - @ec2 - Scenario: Delete ec2 image filter, invalid body: element is hash - When I send DELETE '/v2.0/filter/ec2/image' query with JSON body - """ - [{ - "foo": "foo" - }] - """ - Then response should be '400' - - @ec2 - Scenario: Delete ec2 image filter, invalid body: element is array - When I send DELETE '/v2.0/filter/ec2/image' query with JSON body - """ - [ - [] - ] - """ - Then response should be '400' - - @ec2 - Scenario: Delete ec2 image filter, invalid body: element is null - When I send DELETE '/v2.0/filter/ec2/image' query with JSON body - """ - [ - null - ] - """ - Then response should be '400' - - @ec2 - Scenario: Delete ec2 image filter - When I send DELETE '/v2.0/filter/ec2/image' query with JSON body - """ - [ - "<%= @config["ec2"]["image"] %>" - ] - """ + @<%= provider %> + Scenario: Get new (after delete) <%= provider %> image filter and check value '<%= image %>' + When I send GET '/v2.0/filter/<%= provider %>/images' query Then response should be '200' And the Content-Type header should include 'application/json' - And the JSON response should be an object - And the object should contains key 'images' with array and array should not contains strings '<%= @config["ec2"]["image"] %>' + And the JSON response should be an array + And the array should not contains strings '<%= image %>' + <% end %> diff --git a/devops-service/tests/templates/api_v2/90_delete/99_key.feature.erb b/devops-service/tests/templates/api_v2/90_delete/99_key.feature.erb index 08359b7..e54e07f 100644 --- a/devops-service/tests/templates/api_v2/90_delete/99_key.feature.erb +++ b/devops-service/tests/templates/api_v2/90_delete/99_key.feature.erb @@ -1,9 +1,18 @@ -@key +<% providers = @formatter.get_fixture('providers/all').map{|p| "@#{p}"} %> +@key <%= providers.join(" ") %> Feature: Delete key - <% key_name = @fixtures['key']['valid']['key_name'] %> + <% key = @formatter.get_fixture('key/new') %> + Scenario: DELETE key with header 'Accept' value is not 'application/json' + When I send DELETE '/v2.0/key/<%= key["key_name"] %>' query with header 'Accept' value 'application/xml' + Then response should be '406' + + Scenario: Delete key without privileges + When I send DELETE '/v2.0/key/<%= key["key_name"] %>' query with user without privileges + Then response should be '401' + Scenario: Delete key - When I send DELETE '/v2.0/key/<%= key_name %>' query + When I send DELETE '/v2.0/key/<%= key["key_name"] %>' query Then response should be '200' And the Content-Type header should include 'application/json' And the JSON response should be an object diff --git a/devops-service/tests/templates/fixtures/ec2.yml b/devops-service/tests/templates/fixtures/ec2.yml new file mode 100644 index 0000000..34680ae --- /dev/null +++ b/devops-service/tests/templates/fixtures/ec2.yml @@ -0,0 +1,33 @@ +flavor: + id: &flavor_id "t1.micro" + cores: 2 + disk: 0 + name: "Micro Instance" + ram: 613 +image: + id: &image_id "id" + provider: "ec2" + remote_user: "root" + name: &image_name "" + bootstrap_template: "omnibus" +network: + cidr: cidr + vpcId: vpcId + subnetId: subnetId + name: subnetId + zone: availabilityZone +provider_image: + id: *image_id + name: *image_name + status: available +deploy_env: + identifier: ec2_env + provider: "ec2" + run_list: [] + expires: null + users: [] + flavor: *flavor_id + image: *image_id + subnets: [] + groups: [] + stack_template: null diff --git a/devops-service/tests/templates/fixtures/fixture_formatter.rb b/devops-service/tests/templates/fixtures/fixture_formatter.rb index 4bbe657..555e797 100644 --- a/devops-service/tests/templates/fixtures/fixture_formatter.rb +++ b/devops-service/tests/templates/fixtures/fixture_formatter.rb @@ -1,34 +1,42 @@ require 'json' +require 'pp' class FixtureFormatter def initialize(fixtures) @fixtures = fixtures + if ENV["DEBUG"] + puts "Loaded fixtures:" + pp @fixtures + end end def json(path, options={}) + result = nil begin - result = JSON.pretty_generate(get_fixture(path)) + result = JSON.pretty_generate(get_fixture(path, options)) rescue raise "Fixture '#{path}' is absent" end - if options[:spaces] - result = shift_to_right(result, options[:spaces]) - end + options[:spaces] = 4 unless options[:spaces] + result = shift_to_right(result, options[:spaces]) result end - private - - def get_fixture(path) + def get_fixture(path, options={}) keys = path.split('/') hash = @fixtures keys.each do |key| hash = hash[key] end + hash = hash.clone + hash.merge!(options[:value]) if options[:value] + hash.delete(options[:without_field]) if options[:without_field] hash end + private + def shift_to_right(text, spaces_count) buffer = '' first_line = true @@ -42,4 +50,4 @@ class FixtureFormatter end buffer end -end \ No newline at end of file +end diff --git a/devops-service/tests/templates/fixtures/key.yml b/devops-service/tests/templates/fixtures/key.yml index 0ad3179..79a61fd 100644 --- a/devops-service/tests/templates/fixtures/key.yml +++ b/devops-service/tests/templates/fixtures/key.yml @@ -1,20 +1,8 @@ -valid: &valid +list_element: + scope: "system" + id: "devops" +new: &valid file_name: test_file_name key_name: test_key_name content: test_content -invalid: - base: &invalid_base - <<: *valid - blank_file_name: - <<: *invalid_base - file_name: - blank_key_name: - <<: *invalid_base - key_name: - blank_content: - <<: *invalid_base - content: - scope: - <<: *invalid_base - scope: inalid_scope \ No newline at end of file diff --git a/devops-service/tests/templates/fixtures/openstack.yml b/devops-service/tests/templates/fixtures/openstack.yml new file mode 100644 index 0000000..76554a0 --- /dev/null +++ b/devops-service/tests/templates/fixtures/openstack.yml @@ -0,0 +1,30 @@ +flavor: + id: &flavor_id "flavor_id" + v_cpus: "v_cpus" + ram: "ram" + disk: "disk" +image: + id: &image_id "da25f4b0-3183-4993-ac2b-4744e4ed77cb" + provider: "openstack" + remote_user: "centos" + name: &image_name "CentOS-7-x86_64" + bootstrap_template: null +provider_image: + id: *image_id + name: *image_name + status: ACTIVE +network: + cidr: cidr + id: subnetId + name: subnetId +deploy_env: + identifier: ec2_env + provider: "openstack" + run_list: [] + expires: null + users: [] + flavor: *flavor_id + image: *image_id + subnets: [] + groups: [] + stack_template: null diff --git a/devops-service/tests/templates/fixtures/project.yml b/devops-service/tests/templates/fixtures/project.yml new file mode 100644 index 0000000..c410f5c --- /dev/null +++ b/devops-service/tests/templates/fixtures/project.yml @@ -0,0 +1,3 @@ +name: cucumber_project +description: "Cucumber test project" + diff --git a/devops-service/tests/templates/fixtures/providers.yml b/devops-service/tests/templates/fixtures/providers.yml new file mode 100644 index 0000000..63833be --- /dev/null +++ b/devops-service/tests/templates/fixtures/providers.yml @@ -0,0 +1,4 @@ +without_static: + [openstack, ec2] +all: + [openstack, ec2, static] diff --git a/devops-service/tests/templates/fixtures/static.yml b/devops-service/tests/templates/fixtures/static.yml new file mode 100644 index 0000000..53cdf23 --- /dev/null +++ b/devops-service/tests/templates/fixtures/static.yml @@ -0,0 +1,7 @@ +deploy_env: + identifier: static_env + provider: "static" + run_list: [] + expires: null + users: [] + diff --git a/devops-service/tests/templates/fixtures/user.yml b/devops-service/tests/templates/fixtures/user.yml new file mode 100644 index 0000000..7d7e9d5 --- /dev/null +++ b/devops-service/tests/templates/fixtures/user.yml @@ -0,0 +1,34 @@ +privileges: &privileges + flavor: "rwx" + group: "rwx" + image: "rwx" + project: "rwx" + server: "rwx" + key: "rwx" + user: "rwx" + filter: "rwx" + network: "rwx" + provider: "rwx" + script: "rwx" + templates: "rwx" + stack: "rwx" + stack_template: "rwx" + +show: &valid_show + email: "test@test.test" + privileges: *privileges + id: "test" + +update: &valid_update + email: cucumber_test@test.test + password: test + +create: &valid_create + <<: *valid_update + username: cucumber_test + +privileges_values: ['', r, w, x, rw, rx, wx, rwx] + +privileges_update: + cmd: all + privileges: r diff --git a/devops-service/tests/templates/generators/path_scenarios_generator.rb b/devops-service/tests/templates/generators/path_scenarios_generator.rb new file mode 100644 index 0000000..73b3274 --- /dev/null +++ b/devops-service/tests/templates/generators/path_scenarios_generator.rb @@ -0,0 +1,21 @@ +class PathScenariosGenerator + + def generate_get_path_scenarios name, path + %Q( + Scenario: #{name} + When I send GET '#{path}' query with JSON body + Then response should be '200' + And the Content-Type header should include 'application/json' + #{yield} + + Scenario: #{name} with header 'Accept' value is not 'application/json' + When I send GET '#{path}' query with header 'Accept' value 'application/xml' + Then response should be '406' + + Scenario: #{name} without privileges + When I send GET '#{path}' query with user without privileges + Then response should be '401' +) + end + +end