Merge branch 'qa' of /home/git/repositories/cloudtechlab/devops-service into release

This commit is contained in:
Tim Lianov 2015-10-28 03:08:56 +04:00
commit 3c8274cdab
76 changed files with 1430 additions and 1589 deletions

View File

@ -1,7 +1,6 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
require 'rubygems' require 'rubygems'
require 'bundler' require 'devops-client'
Bundler.require(:default, :development)
DevopsClient.run DevopsClient.run

View File

@ -94,19 +94,36 @@ module Devops
end end
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) 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? env.identifier = deploy_env if env.identifier.nil?
begin begin
db_env = project.deploy_env(deploy_env)
unless env.identifier == deploy_env unless env.identifier == deploy_env
servers = Devops::Db.connector.servers_by_project_and_deploy_env(id, 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? raise InvalidRecord.new("Environment '#{deploy_env}' can't be updated: it has #{servers.size} running servers.") unless servers.empty?
end end
begin begin
project.deploy_env(env.identifier) project.deploy_env(env.identifier)
raise InvalidRecord.new("Can not change environment '#{deploy_env}' to '#{env.identifier}', environment '#{env.identifier}' already exist") unless deploy_env == env.identifier raise InvalidRecord.new("Environment '#{deploy_env}' can't be renamed to '#{env.identifier}', environment '#{env.identifier}' already exists") unless deploy_env == env.identifier
rescue RecordNotFound => e rescue RecordNotFound => e
end end
env.validate! env.validate!
@ -168,13 +185,15 @@ module Devops
def delete_project id def delete_project id
deploy_env = parser.delete deploy_env = parser.delete
servers = Devops::Db.connector.servers id
raise DependencyError.new "Deleting #{id} is forbidden: Project has servers" if !servers.empty?
project = Devops::Db.connector.project(id) project = Devops::Db.connector.project(id)
info = if deploy_env.nil? if deploy_env.nil?
servers = Devops::Db.connector.servers id
raise DependencyError.new "Deleting project #{id} is forbidden: Project has servers" unless servers.empty?
project.delete project.delete
"Project '#{id}' is deleted" "Project '#{id}' is deleted"
else else
servers = Devops::Db.connector.servers id, deploy_env
raise DependencyError.new "Deleting deploy_env #{deploy_env} is forbidden: Project has servers" unless servers.empty?
project.delete_deploy_env(deploy_env) project.delete_deploy_env(deploy_env)
"Project '#{id}'. Deploy environment '#{deploy_env}' has been deleted" "Project '#{id}'. Deploy environment '#{deploy_env}' has been deleted"
end end
@ -279,49 +298,6 @@ module Devops
return [uri] return [uri]
end 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 end
end end

View File

@ -186,6 +186,13 @@ module Devops
return s, rl || d.run_list, t return s, rl || d.run_list, t
end end
def unbootstrap_server id
s = get_server_by_key(id, parser.instance_key)
### Authorization
Devops::Db.connector.check_project_auth s.project, s.deploy_env, parser.current_user
Devops::Executor::ServerExecutor.new(s, "").unbootstrap
end
def add_server def add_server
body = parser.add_server body = parser.add_server
project = body["project"] project = body["project"]

View File

@ -35,22 +35,29 @@ module Devops
if envs_with_this_template.empty? if envs_with_this_template.empty?
Devops::Db.connector.stack_template_delete id Devops::Db.connector.stack_template_delete id
else else
raise ConflictException.new("Stack template '#{id}' is already in use in #{envs_with_this_template.join(', ')}") raise ConflictException.new("Stack template '#{id}' is already in use in #{envs_with_this_template.map{|project, envs| "#{project}: #{envs.join(', ')}"}.join('; ')}", {projects: envs_with_this_template})
end end
end end
private private
# returns:
# {
# "project" => ["deploy_env"]
# }
def envs_using_stack_template(id) def envs_using_stack_template(id)
projects = Devops::Db.connector.projects_and_deploy_envs_by_field('stack_template', id) projects = Devops::Db.connector.projects_and_deploy_envs_by_field('stack_template', id)
envs_with_this_template = [] envs_with_this_template = []
res = {}
projects.each do |project| projects.each do |project|
array = []
res[project.id] = array
project.deploy_envs.each do |env| project.deploy_envs.each do |env|
envs_with_this_template << "#{project.id}-#{env.identifier}" array << env.identifier
end end
end end
envs_with_this_template res
end end
end end

View File

@ -6,7 +6,8 @@ module Devops
class ImageParser < RequestParser class ImageParser < RequestParser
def images def images
provider = @params[:provider] provider = @params["provider"]
puts "Provider: #{provider}"
check_provider(provider) if provider check_provider(provider) if provider
provider provider
end end

View File

@ -7,7 +7,7 @@ module Devops
def create def create
key = create_object_from_json_body 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") 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") content = check_string(key["content"], "Parameter 'content' should be a not empty string")
key key

View File

@ -50,10 +50,16 @@ module Devops
Devops::Model::DeployEnvFactory.create(body) Devops::Model::DeployEnvFactory.create(body)
end end
def add_or_update_deploy_env def update_deploy_env_field
body = create_object_from_json_body body = create_object_from_json_body
rl = check_array(body["run_list"], "Parameter 'run_list' should be an array of string", String, false, true) raise InvalidRecord.new("'value' key not found") if body["value"].nil?
Validators::Helpers::RunList.new(rl).validate! 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) Devops::Model::DeployEnvFactory.create(body)
end end

View File

@ -16,18 +16,16 @@ module Devops
def user_privileges def user_privileges
data = create_object_from_json_body data = create_object_from_json_body
cmd = check_string(data["cmd"], "Parameter 'cmd' should be a not empty string", true) 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 return cmd, privileges
end end
def change_password 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 body = create_object_from_json_body
check_string(body["password"], "Parameter 'password' must be a not empty string") check_string(body["password"], "Parameter 'password' must be a not empty string")
end end
def change_email 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 body = create_object_from_json_body
check_string(body["email"], "Parameter 'email' must be a not empty string") check_string(body["email"], "Parameter 'email' must be a not empty string")
end end

View File

@ -22,7 +22,7 @@ module Devops
# ] # ]
app.get_with_headers "/keys", :headers => [:accept] do app.get_with_headers "/keys", :headers => [:accept] do
check_privileges("key", "r") 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 end
# Create ssh key on devops server # Create ssh key on devops server

View File

@ -36,7 +36,8 @@ module Devops
# ] # ]
app.get_with_headers "/projects", :headers => [:accept] do app.get_with_headers "/projects", :headers => [:accept] do
check_privileges("project", "r") check_privileges("project", "r")
json Devops::API2_0::Handler::Project.new(request).projects.map(&:to_hash_list) projects = Devops::API2_0::Handler::Project.new(request).projects
json projects.map(&:to_hash)
end end
# Get project by id # Get project by id
@ -217,6 +218,27 @@ module Devops
# - method : POST # - method : POST
# - headers : # - headers :
# - Accept: application/json # - 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| app.post_with_headers "/project/:project/deploy_env", :headers => [:accept, :content_type] do |project|
check_privileges("project", "w") check_privileges("project", "w")
res, env = Devops::API2_0::Handler::Project.new(request).add_deploy_env(project) res, env = Devops::API2_0::Handler::Project.new(request).add_deploy_env(project)
@ -235,7 +257,7 @@ module Devops
json Devops::API2_0::Handler::Project.new(request).project_deploy_env(project, env) 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* # * *Request*
# - method : PUT # - method : PUT
@ -266,7 +288,7 @@ module Devops
deploy_env_hash["PUT"] = lambda{|id, deploy_env| deploy_env_hash["PUT"] = lambda{|id, deploy_env|
check_privileges("project", "w") check_privileges("project", "w")
begin 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) create_response(res, nil, 200)
rescue InvalidRecord => e rescue InvalidRecord => e
halt_response(e.message) halt_response(e.message)
@ -293,6 +315,12 @@ module Devops
} }
app.multi_routes "/project/:id/deploy_envs/:deploy_env", {}, deploy_env_hash 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 # Create project
# #
# * *Request* # * *Request*

View File

@ -279,6 +279,25 @@ module Devops
end end
end end
# Unbootstrap devops server
#
# * *Request*
# - method : POST
# - headers :
# - Accept: application/json
# - Content-Type: application/json
# - body :
# {
# "key": "instance", -> search server by instance_id rather then chef_node_name
# }
#
# * *Returns* : 200
app.post_with_headers "/server/:id/unbootstrap", :headers => [:accept, :content_type] do |id|
check_privileges("server", "w")
info = Devops::API2_0::Handler::Server.new(request).unbootstrap_server(id)
create_response("Unbootstrap", info)
end
# Add external server to devops # Add external server to devops
# #
# * *Request* # * *Request*

View File

@ -113,7 +113,9 @@ module Devops
# * *Returns* : # * *Returns* :
# 200 - Updated # 200 - Updated
app.put_with_headers %r{\A/user/#{DevopsConfig::OBJECT_NAME}/email\z}, :headers => [:accept, :content_type] do |user| 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) Devops::API2_0::Handler::User.new(request).change_email(user)
create_response("Updated") create_response("Updated")
end end
@ -133,7 +135,9 @@ module Devops
# * *Returns* : # * *Returns* :
# 200 - Updated # 200 - Updated
app.put_with_headers %r{\A/user/#{DevopsConfig::OBJECT_NAME}/password\z}, :headers => [:accept, :content_type] do |user| 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) Devops::API2_0::Handler::User.new(request).change_password(user)
create_response("Updated") create_response("Updated")
end end

View File

@ -10,6 +10,7 @@ require "exceptions/dependency_error"
require "exceptions/conflict_exception" require "exceptions/conflict_exception"
require "exceptions/parser_error" require "exceptions/parser_error"
require "exceptions/validation_error" require "exceptions/validation_error"
require "exceptions/knife_config_error"
require 'core/devops-logger' require 'core/devops-logger'
require_relative "../helpers/version_2" require_relative "../helpers/version_2"
@ -58,8 +59,12 @@ module Devops
# set current logger and call handlers # set current logger and call handlers
def call env def call env
DevopsLogger.logger = @@logger DevopsLogger.logger = @@logger
begin
res = super(env) res = super(env)
@@access_logger.info(env["REQUEST_METHOD"] + " " + env["REQUEST_URI"] + " - from #{env["HTTP_USER_AGENT"]}") rescue DevopsError => e
return [e.code, {}, e.message]
end
@@access_logger.info(env["REQUEST_METHOD"] + " " + env["REQUEST_URI"] + " - from #{env["HTTP_USER_AGENT"]} (#{env["REMOTE_USER"]}) / #{res.inspect}")
res res
end end
@ -75,6 +80,12 @@ module Devops
halt_response(e.message, 400) halt_response(e.message, 400)
end end
error Devops::Exception::KnifeConfigError do
e = env["sinatra.error"]
logger.error e.message
halt_response(e.message, 500)
end
error RecordNotFound do error RecordNotFound do
e = env["sinatra.error"] e = env["sinatra.error"]
logger.warn e.message logger.warn e.message
@ -103,7 +114,7 @@ module Devops
error ConflictException do error ConflictException do
e = env["sinatra.error"] e = env["sinatra.error"]
logger.warn e.message logger.warn e.message
halt_response(e.message, 409) create_response(e.message, e.object, 409)
end end
error InvalidPrivileges do error InvalidPrivileges do

View File

@ -2,7 +2,7 @@ require "socket"
class DevopsConfig class DevopsConfig
OBJECT_NAME = /[\w\-]+/ OBJECT_NAME = /([\w\-]+)/
@@config = nil @@config = nil

View File

@ -20,7 +20,8 @@ module Connectors
collection.insert(record.to_mongo_hash) collection.insert(record.to_mongo_hash)
record record
rescue Mongo::OperationFailure => e rescue Mongo::OperationFailure => e
if e.message =~ /^11000/ # exception's message doesn't always start from error code
if e.message =~ /11000/
resource_name = StringHelper.underscore_class(record.class) resource_name = StringHelper.underscore_class(record.class)
raise InvalidRecord.new("Duplicate key error: #{resource_name} with id '#{record.id}'") raise InvalidRecord.new("Duplicate key error: #{resource_name} with id '#{record.id}'")
end end

View File

@ -35,6 +35,7 @@ module Connectors
else else
query["archived"] = {"$exists" => false} query["archived"] = {"$exists" => false}
end end
fields << '_id'
list(query, fields: fields) list(query, fields: fields)
end end
@ -93,7 +94,7 @@ module Connectors
def check_project_auth(project_id, env, user_id) def check_project_auth(project_id, env, user_id)
project = show(project_id) project = show(project_id)
raise InvalidPrivileges.new("User '#{user_id}' unauthorized to work with project '#{project_id}'") unless project.check_authorization(user_id, env) raise InvalidPrivileges.new("User '#{user_id}' is unauthorized to work with project '#{project_id}' and environment '#{env}'") unless project.check_authorization(user_id, env)
project project
end end
@ -104,13 +105,17 @@ module Connectors
list( {'deploy_envs' => {'$elemMatch' => q}}, {:fields => {'deploy_envs' => {'$elemMatch' => q}}} ) list( {'deploy_envs' => {'$elemMatch' => q}}, {:fields => {'deploy_envs' => {'$elemMatch' => q}}} )
end end
def set_project_deploy_env_field(project_id, env, field, value) def set_project_deploy_env_field(project_id, env, field_value_hash)
@collection.update({"_id" => project_id, "deploy_envs.identifier" => env}, {"$set" => {"deploy_envs.$.#{field}" => value}}) 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 end
def set_project_env_run_list(project_id, env, run_list) def set_project_env_run_list(project_id, env, run_list)
Helpers::RunList.new(run_list).validate! 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 end
def set_project_run_list(project_id, env, run_list) def set_project_run_list(project_id, env, run_list)

View File

@ -12,7 +12,8 @@ module Devops
class CloudDeployEnv < DeployEnvBase class CloudDeployEnv < DeployEnvBase
attr_accessor :flavor, :image, :subnets, :groups, :stack_template attr_accessor :flavor, :image, :subnets, :groups, :stack_template
=begin
@Deprecated
types :identifier => {:type => String, :empty => false}, types :identifier => {:type => String, :empty => false},
:image => {:type => String, :empty => false}, :image => {:type => String, :empty => false},
:flavor => {:type => String, :empty => false}, :flavor => {:type => String, :empty => false},
@ -23,6 +24,7 @@ module Devops
:subnets => {:type => Array, :empty => true}, :subnets => {:type => Array, :empty => true},
:groups => {:type => Array, :empty => false}, :groups => {:type => Array, :empty => false},
:stack_template => {:type => String, :empty => false, :nil => true} :stack_template => {:type => String, :empty => false, :nil => true}
=end
set_validators ::Validators::DeployEnv::Flavor, set_validators ::Validators::DeployEnv::Flavor,
::Validators::DeployEnv::Image, ::Validators::DeployEnv::Image,
@ -31,6 +33,22 @@ module Devops
::Validators::DeployEnv::Groups, ::Validators::DeployEnv::Groups,
::Validators::DeployEnv::StackTemplate ::Validators::DeployEnv::StackTemplate
# set_validators ::Validators::DeployEnv::CloudParameters # 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={} def initialize d={}
super(d) super(d)

View File

@ -1,9 +1,6 @@
require "db/mongo/models/mongo_model" require "db/mongo/models/mongo_model"
require "providers/provider_factory" require "providers/provider_factory"
require "db/mongo/models/model_with_provider" 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 Devops
module Model module Model
@ -17,6 +14,22 @@ module Devops
::Validators::DeployEnv::Expiration, ::Validators::DeployEnv::Expiration,
::Validators::DeployEnv::Users ::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={} def initialize d={}
self.identifier = d["identifier"] self.identifier = d["identifier"]
b = d["run_list"] || [] b = d["run_list"] || []
@ -41,12 +54,40 @@ module Devops
self.users = (self.users + users).uniq self.users = (self.users + users).uniq
end 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) def build_error_message(message)
"Deploy environment '#{self.identifier}'. " + message "Deploy environment '#{self.identifier}'. " + message
end end
def create_role project_id def create_role project_id
knife = KnifeFactory.instance knife = knife_instance
if knife.nil? if knife.nil?
DevopsLogger.logger.error "Can not get knife instance" DevopsLogger.logger.error "Can not get knife instance"
return nil return nil
@ -56,25 +97,29 @@ module Devops
if all_roles.nil? if all_roles.nil?
msg = "Can't get roles list from chef" msg = "Can't get roles list from chef"
DevopsLogger.logger.error msg DevopsLogger.logger.error msg
return {error: msg} return {error: [msg]}
end end
role_name = knife.role_name(project_id, self.identifier) role_name = knife.role_name(project_id, self.identifier)
begin begin
if all_roles.include? role_name if all_roles.include? role_name
info[:exist] = role_name info[:exist] = [role_name]
else else
knife.create_role role_name, project_id, self.identifier knife.create_role role_name, project_id, self.identifier
info[:new] = role_name info[:new] = [role_name]
DevopsLogger.logger.info "Role '#{role_name}' created" DevopsLogger.logger.info "Role '#{role_name}' created"
end end
self.run_list << "role[#{role_name}]" self.run_list << "role[#{role_name}]"
rescue => er rescue => er
info[:error] = role_name info[:error] = [role_name]
DevopsLogger.logger.error "Role '#{role_name}' can not be created: #{er.message}" DevopsLogger.logger.error "Role '#{role_name}' can not be created: #{er.message}"
end end
info info
end end
def knife_instance
KnifeFactory.instance
end
end end
end end
end end

View File

@ -4,6 +4,8 @@ module Devops
module Model module Model
class DeployEnvEc2 < CloudDeployEnv class DeployEnvEc2 < CloudDeployEnv
=begin
@Deprecated
types :identifier => {:type => String, :empty => false}, types :identifier => {:type => String, :empty => false},
:image => {:type => String, :empty => false}, :image => {:type => String, :empty => false},
:flavor => {:type => String, :empty => false}, :flavor => {:type => String, :empty => false},
@ -14,6 +16,7 @@ module Devops
:subnets => {:type => Array, :empty => true}, :subnets => {:type => Array, :empty => true},
:groups => {:type => Array, :empty => false}, :groups => {:type => Array, :empty => false},
:stack_template => {:type => String, :empty => false, :nil => true} :stack_template => {:type => String, :empty => false, :nil => true}
=end
=begin =begin
set_validators ::Validators::DeployEnv::RunList, set_validators ::Validators::DeployEnv::RunList,

View File

@ -1,20 +1,55 @@
require "db/mongo/models/mongo_model" require "db/mongo/models/mongo_model"
require "db/validators/image/bootstrap_template" require "db/validators/image/bootstrap_template"
require "db/validators/image/image_in_filter" require "db/validators/image/image_in_filter"
require "db/mongo/models/model_with_provider"
module Devops module Devops
module Model module Model
class Image < MongoModel 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}, types :id => {:type => String, :empty => false},
:provider => {:type => String, :empty => false}, :provider => {:type => String, :empty => false},
:remote_user => {:type => String, :empty => false}, :remote_user => {:type => String, :empty => false},
:name => {:type => String, :empty => true}, :name => {:type => String, :empty => true},
:bootstrap_template => {:type => String, :empty => false, :nil => true} :bootstrap_template => {:type => String, :empty => false, :nil => true}
set_validators ::Validators::Image::ImageInFilter, =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 ::Validators::Image::BootstrapTemplate
def validate!
validate_id!
validate_provider!
validate_remote_user!
validate_name!
validate_bootstrap_template!
end
def initialize p={} def initialize p={}
self.id = p["id"] self.id = p["id"]
self.provider = p["provider"] self.provider = p["provider"]

View File

@ -6,6 +6,14 @@ module Devops
attr_accessor :provider 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 def provider_instance
@provider_instance ||= Provider::ProviderFactory.get(self.provider) @provider_instance ||= Provider::ProviderFactory.get(self.provider)
end end

View File

@ -55,7 +55,7 @@ module Devops
def validate! def validate!
begin begin
# TODO: we should validate type in request parser # TODO: we should validate type in request parser
self.validate_fields_types # self.validate_fields_types
self.class.validate_model(self) self.class.validate_model(self)
true true
rescue InvalidRecord => e rescue InvalidRecord => e
@ -120,13 +120,17 @@ module Devops
end end
@validators = [] @validators = []
# @field_validators = []
class << self class << self
attr_accessor :validators attr_accessor :validators
# attr_accessor :field_validators
def inherited(subclass) def inherited(subclass)
subclass.validators = [] subclass.validators = []
subclass.validators += self.validators subclass.validators += self.validators
# subclass.field_validators = []
# subclass.field_validators += self.field_validators
end end
# all exceptions are handled in @validate! method # all exceptions are handled in @validate! method
@ -136,6 +140,16 @@ module Devops
end end
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 class methods
private private

View File

@ -67,7 +67,7 @@ module Devops
def add_deploy_env deploy_env def add_deploy_env deploy_env
res = deploy_env.create_role(self.id) res = deploy_env.create_role(self.id)
Devops::Db.connector.add_deploy_env_to_project self.id, deploy_env Devops::Db.connector.add_deploy_env_to_project self.id, deploy_env
create_roles_response(res) Project.create_roles_response(res)
end end
def add_authorized_user user, env=nil def add_authorized_user user, env=nil
@ -210,7 +210,7 @@ module Devops
end end
end end
def create_roles_response roles def self.create_roles_response roles
if roles.is_a?(String) if roles.is_a?(String)
roles roles
else else

View File

@ -17,6 +17,15 @@ module Devops
:email => {:type => String, :empty => false}, :email => {:type => String, :empty => false},
:password => {:type => String, :empty => true} :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={} def initialize p={}
self.id = p['username'] self.id = p['username']
self.email = p['email'] self.email = p['email']
@ -24,6 +33,13 @@ module Devops
self.privileges = p["privileges"] || self.default_privileges self.privileges = p["privileges"] || self.default_privileges
end end
def validate!
validate_id!
validate_password!
validate_email!
validate_privileges!
end
def all_privileges def all_privileges
privileges_with_value("rwx") privileges_with_value("rwx")
end end
@ -33,6 +49,8 @@ module Devops
end end
def grant cmd, priv='' def grant cmd, priv=''
priv='' if priv.nil?
cmd='' if cmd.nil?
if !priv.empty? and PRIVILEGES_REGEX.match(priv).to_s.empty? if !priv.empty? and PRIVILEGES_REGEX.match(priv).to_s.empty?
raise InvalidCommand.new "Invalid privileges '#{priv}'. Available values are '#{PRIVILEGES.join("', '")}'" raise InvalidCommand.new "Invalid privileges '#{priv}'. Available values are '#{PRIVILEGES.join("', '")}'"
end end
@ -46,7 +64,7 @@ module Devops
when "" when ""
self.privileges = self.default_privileges self.privileges = self.default_privileges
else 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 self.privileges[cmd] = priv
end end
end end

View File

@ -3,6 +3,8 @@ module Validators
module DeployEnv; end module DeployEnv; end
module Key; end module Key; end
module Image; end module Image; end
module FieldValidator; end
end end
require "db/validators/base" require "db/validators/base"
@ -10,7 +12,8 @@ require "db/validators/base"
'db/validators/helpers/*.rb', 'db/validators/helpers/*.rb',
'db/validators/deploy_env/*.rb', 'db/validators/deploy_env/*.rb',
'db/validators/key/*.rb', 'db/validators/key/*.rb',
'db/validators/image/*.rb' 'db/validators/image/*.rb',
'db/validators/field_validators/*.rb'
].each do |files_regexp| ].each do |files_regexp|
Dir[files_regexp].each {|file| require file } Dir[files_regexp].each {|file| require file }
end end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,14 @@
require_relative "base"
module Validators
module FieldValidator
class Nil < Base
def validate!
!@value.nil?
end
end
end
end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,4 +1,11 @@
class ConflictException < StandardError class ConflictException < StandardError
attr_reader :object
def initialize msg, object=nil
super(msg)
@object = object
end
end end

View File

@ -0,0 +1,13 @@
module Devops
module Exception
class DevopsError < StandardError
def code
500
end
end
end
end

View File

@ -0,0 +1,9 @@
require 'exceptions/devops_error'
module Devops
module Exception
class KnifeConfigError < DevopsError
end
end
end

View File

@ -281,17 +281,27 @@ module Devops
k = Devops::Db.connector.key(@server.key) k = Devops::Db.connector.key(@server.key)
cert_path = k.path cert_path = k.path
i = 0 i = 0
res = delete_from_chef_server(@server.chef_node_name)
begin begin
r = `ssh -i #{cert_path} -q #{@server.remote_user}@#{@server.private_ip} rm -Rf /etc/chef` new_name = "/etc/chef.backup_#{Time.now.strftime("%d-%m-%Y_%H.%M.%S")}"
# r = `ssh -i #{cert_path} -q #{@server.remote_user}@#{@server.private_ip} rm -Rf /etc/chef`
cmd = "ssh -i #{cert_path} -q #{@server.remote_user}@#{@server.private_ip} \"/bin/sh -c 'if [[ -d /etc/chef ]]; then mv /etc/chef #{new_name}; else echo not found; fi'\""
DevopsLogger.logger.info("Trying to run command '#{cmd}'")
r = `#{cmd}`.strip
if r == 'not found'
res[:server] = "Directory '/etc/chef' does not exists"
else
raise(r) unless $?.success? raise(r) unless $?.success?
res[:server] = "'/etc/chef' renamed to '#{new_name}'"
end
rescue => e rescue => e
DevopsLogger.logger.error "Unbootstrap error: " + e.message DevopsLogger.logger.error "Unbootstrap error: " + e.message
i += 1 i += 1
sleep(1) sleep(1)
retry unless i == 5 retry unless i == 5
return e.message return {error: e.message}
end end
nil res
end end
def deploy_server_with_tags tags, deploy_info def deploy_server_with_tags tags, deploy_info

View File

@ -6,6 +6,11 @@ When(/^I send GET '(.*)' query$/) do |path|
get(path, {}, DEFAULT_HEADERS) get(path, {}, DEFAULT_HEADERS)
end 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| When(/^I send GET '(.*)' query with user without privileges$/) do |path|
get_without_privileges(path, {}, DEFAULT_HEADERS) get_without_privileges(path, {}, DEFAULT_HEADERS)
end end
@ -31,9 +36,16 @@ When(/^I send POST '(.*)' query with JSON body$/) do |path, body|
res = post_body(path, body, DEFAULT_HEADERS) res = post_body(path, body, DEFAULT_HEADERS)
end 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 = 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) res = post_body(path, body, headers)
end end
@ -57,13 +69,19 @@ When(/^I send DELETE '(.*)' query$/) do |path|
delete(path, {}, DEFAULT_HEADERS) delete(path, {}, DEFAULT_HEADERS)
end 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? JSON.parse(body) unless body.strip.empty?
headers = DEFAULT_HEADERS.clone headers = DEFAULT_HEADERS.clone
headers["Accept"] = hv headers[header] = hv
res = delete_body(path, body, headers) res = delete_body(path, body, headers)
end 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| When(/^I send DELETE '(.*)' query with JSON body$/) do |path, body|
JSON.parse(body) unless body.strip.empty? JSON.parse(body) unless body.strip.empty?
res = delete_body(path, body, DEFAULT_HEADERS) 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) put_without_privileges(path, {}, DEFAULT_HEADERS)
end 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? JSON.parse(body) unless body.strip.empty?
headers = DEFAULT_HEADERS.clone headers = DEFAULT_HEADERS.clone
headers["Accept"] = hv headers[header] = hv
res = put_body(path, body, headers) res = put_body(path, body, headers)
end end

View File

@ -1,5 +1,5 @@
Then(/^response array should contains elements like:$/) do |string| 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 = JSON.parse(last_response.body)
array.each do |e| array.each do |e|
src.each do |key, value| src.each do |key, value|
@ -44,15 +44,14 @@ Then(/^response should be JSON object like:$/) do |string|
end end
Then(/^the array should contains strings '(.*)'$/) do |string| Then(/^the array should contains strings '(.*)'$/) do |string|
buf = string.split(",") buf = string.split(",").map(&:strip)
array = JSON.parse(last_response.body) array = JSON.parse(last_response.body)
buf.each do |v| res = buf - array
assert array.include?(v), "Array should contains '#{v}'" assert res.empty?, "Response has no strings '#{res.join("', '")}'"
end
end end
Then(/^the array should not contains strings '(.*)'$/) do |string| Then(/^the array should not contains strings '(.*)'$/) do |string|
buf = string.split(",") buf = string.split(",").map(&:strip)
array = JSON.parse(last_response.body) array = JSON.parse(last_response.body)
buf.each do |v| buf.each do |v|
assert !array.include?(v), "Array should not contains '#{v}'" assert !array.include?(v), "Array should not contains '#{v}'"

View File

@ -5,6 +5,7 @@ require "yaml"
require "ostruct" require "ostruct"
require "fileutils" require "fileutils"
require "./templates/fixtures/fixture_formatter" require "./templates/fixtures/fixture_formatter"
require "./templates/generators/path_scenarios_generator.rb"
class Generator < OpenStruct class Generator < OpenStruct
@ -15,7 +16,8 @@ class Generator < OpenStruct
config_file = ENV["DEVOPS_FEATURES_GENERATOR_CONFIG"] || ENV["CONFIG"] || CONFIG config_file = ENV["DEVOPS_FEATURES_GENERATOR_CONFIG"] || ENV["CONFIG"] || CONFIG
@config = YAML.load_file(File.new(config_file)) @config = YAML.load_file(File.new(config_file))
load_fixtures() load_fixtures()
super(:config => @config, :formatter => @formatter, :fixtures => @fixtures) @generator = PathScenariosGenerator.new
super(:config => @config, :formatter => @formatter, :fixtures => @fixtures, :generator => @generator)
end end
def configure! def configure!
@ -31,6 +33,7 @@ class Generator < OpenStruct
templates.each do |input, output| templates.each do |input, output|
puts "Input: #{input}" puts "Input: #{input}"
if File.exists?(input) if File.exists?(input)
begin
file_data = File.read(input) file_data = File.read(input)
if file_data.nil? if file_data.nil?
puts "Data of file '#{input}' is nil" puts "Data of file '#{input}' is nil"
@ -40,20 +43,31 @@ class Generator < OpenStruct
FileUtils.mkdir_p(dir) unless File.exists?(dir) FileUtils.mkdir_p(dir) unless File.exists?(dir)
File.open(output, "w") {|f| f.write(data)} File.open(output, "w") {|f| f.write(data)}
end end
rescue => e
puts "\tError: #{e.message}"
end
else else
puts "WARN: file '#{input}' does not exist" puts "WARN: file '#{input}' does not exist"
end end
end end
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| feature_files.each do |feature_file|
if File.exists?(feature_file) if File.exists?(feature_file)
FileUtils.rm(feature_file) FileUtils.rm_f(feature_file)
else else
puts "WARN: file '#{feature_file}' does not exist" puts "WARN: file '#{feature_file}' does not exist"
end end
end end
=end
end end
private private
@ -63,10 +77,13 @@ class Generator < OpenStruct
end end
def load_fixtures def load_fixtures
puts "Load fixures:"
@fixtures = {} @fixtures = {}
Dir["templates/fixtures/*.yml"].each do |fixture_path| Dir["templates/fixtures/*.yml"].each do |fixture_path|
fixture_name = File.basename(fixture_path, '.yml') fixture_name = File.basename(fixture_path, '.yml')
print "\t#{fixture_path}..."
@fixtures[fixture_name] = YAML.load_file(fixture_path) @fixtures[fixture_name] = YAML.load_file(fixture_path)
puts " ok"
end end
@formatter = FixtureFormatter.new(@fixtures) @formatter = FixtureFormatter.new(@fixtures)
@ -78,7 +95,14 @@ templates = {
#list #list
"templates/api_v2/00_list/flavor.feature.erb" => "features/api_v2/00_list/flavor.feature", "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/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_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 #create
"templates/api_v2/10_create/00_filter.feature.erb" => "features/api_v2/10_create/00_filter.feature", "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/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/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/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/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/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", "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' if ARGV.first != 'clean'
generator = Generator.new.configure!
generator.generate!(templates) generator.generate!(templates)
else else
generator.clean!(templates.values) Generator.clean!
end end

View File

@ -7,30 +7,3 @@ path_prefix: ""
username_without_privileges: "user_for_testing_" username_without_privileges: "user_for_testing_"
password_without_privileges: "test" 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"

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -1,4 +1,5 @@
@user <% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %>
@list @user <%= providers.join(" ") %>
Feature: list user Feature: list user
Scenario: Get list of all users Scenario: Get list of all users
@ -9,27 +10,14 @@ Feature: list user
And response array should contains elements like: And response array should contains elements like:
""" """
[ [
{ <%= @formatter.json('user/show', spaces: 6) %>
"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"
}
] ]
""" """
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 Scenario: Get list of all users without privileges
When I send GET '/v2.0/users' query with user without privileges When I send GET '/v2.0/users' query with user without privileges
Then response should be '401' Then response should be '401'

View File

@ -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'

View File

@ -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'

View File

@ -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)} %>

View File

@ -1,42 +1,26 @@
@flavor @flavor @list
Feature: Flavors Feature: Flavors
@openstack <% @formatter.get_fixture('providers/without_static').each do |provider| %>
Scenario: Get list of openstack flavors @<%= provider %>
When I send GET '/v2.0/flavors/openstack' query Scenario: Get list of <%= provider %> flavors
When I send GET '/v2.0/flavors/<%= provider %>' query
Then response should be '200' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
And the JSON response should be an array And the JSON response should be an array
And response array should contains elements like: And response array should contains elements like:
""" """
[ [
{ <%= @formatter.json(provider + '/flavor', spaces: 6) %>
"id": "flavor_id",
"v_cpus": "v_cpus",
"ram": "ram",
"disk": "disk"
}
] ]
""" """
@ec2 @<%= provider %>
Scenario: Get list of ec2 flavors Scenario: Get list of <%= provider %> flavors with header 'Accept' value is not 'application/json'
When I send GET '/v2.0/flavors/ec2' query When I send GET '/v2.0/flavors/<%= provider %>' query with header 'Accept' value 'application/xml'
Then response should be '200' Then response should be '406'
And the Content-Type header should include 'application/json'
And the JSON response should be an array <% end %>
And response array should contains elements like:
"""
[
{
"id": "t1.micro",
"cores": 2,
"disk": 0,
"name": "Micro Instance",
"ram": 613
}
]
"""
@static @static
Scenario: Get list of static flavors Scenario: Get list of static flavors
@ -46,10 +30,13 @@ Feature: Flavors
And the JSON response should be an array And the JSON response should be an array
And response array should be empty And response array should be empty
<% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %>
<%= providers.join(" ") %>
Scenario: Get flavors list of unknown provider Scenario: Get flavors list of unknown provider
When I send GET '/v2.0/flavors/foo' query When I send GET '/v2.0/flavors/foo' query
Then response should be '404' Then response should be '404'
<%= providers.join(" ") %>
Scenario: Get flavors list of unknown provider without privileges Scenario: Get flavors list of unknown provider without privileges
When I send GET '/v2.0/flavors/foo' query with user without privileges When I send GET '/v2.0/flavors/foo' query with user without privileges
Then response should be '401' Then response should be '401'

View File

@ -1,4 +1,4 @@
@stack_preset @stack_preset @list
Feature: stack template preset list Feature: stack template preset list
Scenario: Get list of all stack template presets Scenario: Get list of all stack template presets

View File

@ -1,192 +1,74 @@
@filter @image @project @filter @image @project
Feature: Filters Feature: Filters
@openstack <% @formatter.get_fixture('providers/without_static').each do |provider| %>
Scenario: Add openstack image filter with user without privileges <% image = @formatter.get_fixture(provider + "/image")["id"] %>
When I send PUT '/v2.0/filter/openstack/image' query with user without privileges @<%= 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' Then response should be '401'
@openstack @<%= provider %>
Scenario: Add openstack image filter with header 'Accept' value 'text/*' Scenario: Update images filter with JSON body with header 'Accept' value not 'application/json'
When I send PUT '/v2.0/filter/openstack/image' query with JSON body with header 'Accept' value 'text/*' 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' Then response should be '406'
@openstack @<%= provider %>
Scenario: Add openstack image filter without header 'Content-Type' Scenario: Add <%= provider %> image filter without header 'Content-Type'
When I send PUT '/v2.0/filter/openstack/image' query with JSON body 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' Then response should be '415'
@openstack <% ["", "{}", "[{}]", "[[]]", "[null]"].each do |body| %>
Scenario: Add openstack image filter, invalid body: empty @<%= provider %>
When I send PUT '/v2.0/filter/openstack/image' query with JSON body 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' Then response should be '400'
<% end %>
@openstack @<%= provider %>
Scenario: Add openstack image filter, invalid body: hash Scenario: Add <%= provider %> image filter
When I send PUT '/v2.0/filter/openstack/image' query with JSON body When I send PUT '/v2.0/filter/<%= provider %>/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
""" """
[ [
[] "<%= image %>"
]
"""
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"] %>"
] ]
""" """
Then response should be '200' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
And the JSON response should be an object 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 @<%= provider %>
Scenario: Add openstack image filter with invalid JSON Scenario: Get new <%= provider %> image filter and check value '<%= image %>'
When I send PUT '/v2.0/filter/openstack/image' query with body When I send GET '/v2.0/filter/<%= provider %>/images' query
"""
[
"<%= @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"] %>"
]
"""
Then response should be '200' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
And the JSON response should be an object And the JSON response should be an array
And the object should contains key 'images' with array and array should contains strings '<%= @config["ec2"]["image"] %>' And the array elements should be strings
And the array should contains strings '<%= image %>'
@ec2 @<%= provider %>
Scenario: Add ec2 image filter with invalid JSON Scenario: Add <%= provider %> image filter with invalid JSON
When I send PUT '/v2.0/filter/ec2/image' query with body When I send PUT '/v2.0/filter/<%= provider %>/image' query with body
""" """
[ [
"<%= @config["ec2"]["image"] %>", "<%= image %>",
] ]
""" """
Then response should be '400' Then response should be '400'
<% end %>

View File

@ -1,34 +1,44 @@
@key <% providers = @formatter.get_fixture('providers/all').map{|p| "@#{p}"} %>
Feature: Add new script @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 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' 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 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' 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 <% end #value %>
When I send POST '/v2.0/key' query with JSON body <% 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' Then response should be '406'
And response error should be "Parameter 'content' should be a not empty string"
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 Scenario: Add new key
When I send POST '/v2.0/key' query with JSON body 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' Then response should be '201'

View File

@ -4,32 +4,47 @@ Feature: create user
Scenario: create user with user without privileges Scenario: create user with user without privileges
When I send POST '/v2.0/user' query with JSON body with user without privileges When I send POST '/v2.0/user' query with JSON body with user without privileges
""" """
{ <%= @formatter.json('user/create', spaces: 4) %>
"username": "<%= @config["user"]["name"] %>",
"email": "<%= @config["user"]["name"] %>@test.test",
"password": "<%= @config["user"]["name"] %>"
}
""" """
Then response should be '401' Then response should be '401'
Scenario: create user without header 'Content-Type' Scenario: create user without header 'Content-Type'
When I send POST '/v2.0/user' query with JSON body without header 'Content-Type' When I send POST '/v2.0/user' query with JSON body without header 'Content-Type'
""" """
{ <%= @formatter.json('user/create', spaces: 4) %>
"username": "<%= @config["user"]["name"] %>",
"email": "<%= @config["user"]["name"] %>@test.test",
"password": "<%= @config["user"]["name"] %>"
}
""" """
Then response should be '415' 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 Scenario: create user, invalid body: empty
When I send POST '/v2.0/user' query with JSON body When I send POST '/v2.0/user' query with JSON body
""" """
""" """
Then response should be '400' 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 %>' Scenario: create user, invalid body: body is a '<%= k %>'
When I send POST '/v2.0/user' query with JSON body When I send POST '/v2.0/user' query with JSON body
""" """
@ -38,85 +53,31 @@ Feature: create user
Then response should be '400' Then response should be '400'
<% end %> <% 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| %> <% 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 When I send POST '/v2.0/user' query with JSON body
""" """
{ <%= @formatter.json('user/create', {spaces: 4, value: {field => k}}) %>
"username": <%= k %>, """
"email": "<%= @config["user"]["name"] %>@test.test", Then response should be '400'
"password": "<%= @config["user"]["name"] %>"
} 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' Then response should be '400'
<% end %> <% 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 %> <% 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 Scenario: create user
When I send POST '/v2.0/user' query with JSON body When I send POST '/v2.0/user' query with JSON body
""" """
{ <%= @formatter.json('user/create', spaces: 4) %>
"username": "<%= @config["user"]["name"] %>",
"email": "<%= @config["user"]["name"] %>@test.test",
"password": "<%= @config["user"]["name"] %>"
}
""" """
Then response should be '201' Then response should be '201'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'

View File

@ -1,552 +1,85 @@
@image @project @image @project
Feature: Manage images Feature: Manage images
Scenario: Get list of all images <% providers = @formatter.get_fixture('providers/without_static') %>
When I send GET '/v2.0/images' query <% providers.each do |provider| %>
Then response should be '200' <% other_providers = providers.clone - [provider] %>
And the Content-Type header should include 'application/json' <% other_providers.each do |oprovider| %>
And the JSON response should be an array @<%= provider %>
And response array should contains elements like: Scenario: Create <%= provider %> image with '<%= oprovider %>' provider (invalid image id for provider)
"""
[
{
"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
When I send POST '/v2.0/image' query with JSON body When I send POST '/v2.0/image' query with JSON body
""" """
{ <%= @formatter.json(provider + '/image', {value: {"provider" => oprovider}}) %>
"provider": "ec2",
"name": "freebsd-10.0",
"remote_user": "root",
"bootstrap_template": "chef_freebsd",
"id": "<%= @config["openstack"]["image"] %>"
}
""" """
Then response should be '400' Then response should be '400'
@openstack <% end #other providers%>
Scenario: Create openstack image with invalid provider <% 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 When I send POST '/v2.0/image' query with JSON body
""" """
{ <%= @formatter.json(provider + '/image', {value: {key => invalid_value}}) %>
"provider": "foo",
"name": "freebsd-10.0",
"remote_user": "root",
"bootstrap_template": "chef_freebsd",
"id": "<%= @config["openstack"]["image"] %>"
}
""" """
Then response should be '400' Then response should be '400'
@openstack <% end #invalid values%>
Scenario: Create openstack image with invalid provider - array
<% 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 When I send POST '/v2.0/image' query with JSON body
""" """
{ <%= @formatter.json(provider + '/image', {value: {key => nil}}) %>
"provider": ["foo"],
"name": "freebsd-10.0",
"remote_user": "root",
"bootstrap_template": "chef_freebsd",
"id": "<%= @config["openstack"]["image"] %>"
}
""" """
Then response should be '400' Then response should be '400'
@openstack <% end %>
Scenario: Create openstack image with invalid provider - hash
<% (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 When I send POST '/v2.0/image' query with JSON body
""" """
{ <%= @formatter.json(provider + '/image', {value: {key => "foo"}}) %>
"provider": {},
"name": "freebsd-10.0",
"remote_user": "root",
"bootstrap_template": "chef_freebsd",
"id": "<%= @config["openstack"]["image"] %>"
}
""" """
Then response should be '400' Then response should be '400'
@openstack <% end %>
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'
@openstack @<%= provider %>
Scenario: Create openstack image with invalid name - array Scenario: Create <%= provider %> image
When I send POST '/v2.0/image' query with JSON body When I send POST '/v2.0/image' query with JSON body
""" """
{ <%= @formatter.json(provider + '/image') %>
"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"] %>"
}
""" """
Then response should be '201' Then response should be '201'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
@ec2 @<%= provider %>
Scenario: Create ec2 image with openstack provider Scenario: Check new <%= provider %> image
When I send POST '/v2.0/image' query with JSON body When I send GET '/v2.0/image/<%= image["id"] %>' query
"""
{
"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
Then response should be '200' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
And the JSON response should be an object And the JSON response should be an object
And response should be JSON object like: And response should be JSON object like:
""" """
{ <%= @formatter.json(provider + '/image') %>
"provider": "ec2",
"name": "test-ec2",
"remote_user": "ec2-user",
"bootstrap_template": null,
"id": "<%= @config["ec2"]["image"] %>"
}
""" """
@ec2 @<%= provider %>
Scenario: Get ec2 image without privileges Scenario: Get <%= provider %> image without privileges
When I send GET '/v2.0/image/<%= @config["ec2"]["image"] %>' query with user without privileges When I send GET '/v2.0/image/<%= image["id"] %>' query with user without privileges
Then response should be '401' Then response should be '401'
@openstack @<%= provider %>
Scenario: Get info for single openstack image Scenario: Get list of <%= provider %> images with header 'Accept' value is not 'application/json'
When I send GET '/v2.0/image/<%= @config["openstack"]["image"] %>' query When I send GET '/v2.0/image/<%= image["id"] %>' query with header 'Accept' value 'application/xml'
Then response should be '200' Then response should be '406'
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"] %>"
}
"""
@openstack <% end %>
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'
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'

View File

@ -1,32 +1,12 @@
@project <% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %>
@project <%= providers.join(" ") %>
Feature: create project Feature: create project
@openstack <% project = @formatter.get_fixture('project') %>
Scenario: Create project <%= @config["openstack"]["project"]["name"] %> Scenario: Create project <%= project["name"] %>
When I send POST '/v2.0/project' query with JSON body When I send POST '/v2.0/project' query with JSON body
""" """
{ <%= @formatter.json('project') %>
"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"] %>"
}
""" """
Then response should be '201' Then response should be '201'

View File

@ -0,0 +1,3 @@
@project @deploy_env
Feature: create deploy env in project

View File

@ -1,13 +1,15 @@
@user @user
Feature: change user privileges and password Feature: change user privileges and password
<% %w{password email}.each do |k| %> <% user_hash = @formatter.get_fixture('user/create') %>
<% val = (k == "email" ? "#{@config["user"]["name"]}@test.test" : @config["user"]["name"]) %> <% 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 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' 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 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' Then response should be '401'
Scenario: change user <%= k %> without header 'Content-Type' 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' Then response should be '415'
Scenario: change user <%= k %>, invalid body: empty 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' Then response should be '400'
<% ["{}", "[]", ""].each do |body| %> <% ["", "[]"].each do |body| %>
Scenario: change user <%= k %>, invalid body: body is a '<%= 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 %> <%= body %>
""" """
@ -47,7 +49,7 @@ Feature: change user privileges and password
<% elements = ["{}", "[]", "null" ] %> <% elements = ["{}", "[]", "null" ] %>
<% elements.each do |value| %> <% elements.each do |value| %>
Scenario: change user <%= k %>, invalid body: <%= k %> is a '<%= 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 %> "<%= k %>": <%= value %>
@ -57,10 +59,10 @@ Feature: change user privileges and password
<% end %> <% end %>
Scenario: change user <%= k %> 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' Then response should be '200'
@ -69,115 +71,93 @@ Feature: change user privileges and password
<% end %> <% end %>
Scenario: change user privileges with user without privileges 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' Then response should be '401'
Scenario: change root privileges Scenario: change root privileges
When I send PUT '/v2.0/user/root' query with JSON body When I send PUT '/v2.0/user/root' query with JSON body
""" """
{} <%= @formatter.json('user/privileges', {spaces: 4}) %>
""" """
Then response should be '401' Then response should be '401'
Scenario: change user privileges without header 'Content-Type' 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' Then response should be '415'
<% ["[]", ""].each do |body| %> Scenario: change user privileges with header 'Accept' value is not application/json
Scenario: change user privileges, invalid body: body is a '<%= body %>' When I send PUT '/v2.0/user/<%= username %>' query with JSON body with header 'Accept' value 'application/xml'
When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body
""" """
<%= body %> <%= @formatter.json('user/privileges', {spaces: 4}) %>
""" """
Then response should be '400' Then response should be '406'
<% end %>
<% elements = ["{}", "[]" ] %> <% elements = ["{}", "[]" ] %>
<% elements.each do |value| %> <% elements.each do |value| %>
Scenario: change user privileges, invalid body: cmd is a '<%= 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
""" """
{ <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => value, "privileges" => "r"}}) %>
"cmd": "<%= value %>",
"privileges": "r"
}
""" """
Then response should be '400' Then response should be '400'
Scenario: change user privileges, invalid body: privileges is a '<%= value %>' 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
""" """
{ <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => "foo", "privileges" => value}}) %>
"cmd": "all",
"privileges": "<%= value %>"
}
""" """
Then response should be '400' Then response should be '400'
<% end %> <% end %>
Scenario: change user privileges: foo - r 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
""" """
{ <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => "foo", "privileges" => "r"}}) %>
"cmd": "foo",
"privileges": "r"
}
""" """
Then response should be '400' Then response should be '400'
<% %w{foo, rr, rwwww, rwxxx, rwf}.each do |priv| %> <% %w{foo, rr, rwwww, rwxxx, rwf}.each do |priv| %>
Scenario: change user privileges: all - <%= priv %> Scenario: change user privileges: all - <%= priv %>
When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body When I send PUT '/v2.0/user/<%= @config["user"]["name"] %>' query with JSON body
""" """
{ <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => "all", "privileges" => priv}}) %>
"cmd": "all",
"privileges": "<%= priv %>"
}
""" """
Then response should be '400' Then response should be '400'
<% end %> <% end %>
<% privs = %w{r w x rw rx wx rwx} %> <% privs = @formatter.get_fixture('user/privileges_values') %>
<% (@formatter.get_fixture('user/privileges').keys.map(&:to_s) << "all").each do |cmd| %>
<% %w{flavor group image project server key user filter network provider script templates all}.each do |cmd| %>
<% privs.each do |priv| %> <% privs.each do |priv| %>
Scenario: change user privileges: <%= cmd %> - <%= 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
""" """
{ <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => cmd, "privileges" => priv}}) %>
"cmd": "<%= cmd %>",
"privileges": "<%= priv %>"
}
""" """
Then response should be '200' Then response should be '200'
<% end %> <% end %>
Scenario: change user privileges: <%= cmd %> - without privileges 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
""" """
{ <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => cmd}, without_field: "privileges"}) %>
"cmd": "<%= cmd %>"
}
""" """
Then response should be '200' Then response should be '200'
Scenario: change user privileges: <%= cmd %> - ' ' 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
""" """
{ <%= @formatter.json('user/privileges_update', {spaces: 4, value: {"cmd" => cmd, "privileges" => " "}}) %>
"cmd": "<%= cmd %>",
"privileges": " "
}
""" """
Then response should be '400' Then response should be '400'
<% end %> <% end %>
Scenario: change user privileges: set default privileges 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
""" """
{ {
} }

View File

@ -1,171 +1,62 @@
@image @project @image @project
Feature: Update images Feature: Update images
@openstack <% providers = @formatter.get_fixture('providers/without_static') %>
Scenario: Update openstack image with ec2 provider <% providers.each do |provider| %>
When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body <% 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
""" """
{ <%= @formatter.json(provider + '/image', {value: {"provider" => oprovider}}) %>
"provider": "ec2",
"name": "freebsd-10.0",
"remote_user": "root",
"bootstrap_template": "chef_freebsd",
"id": "<%= @config["openstack"]["image"] %>"
}
""" """
Then response should be '400' Then response should be '400'
@openstack <% end #other providers%>
Scenario: Update openstack image with invalid provider
When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body <% (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
""" """
{ <%= @formatter.json(provider + '/image', {value: {key => invalid_value}}) %>
"provider": "foo",
"name": "freebsd-10.0",
"remote_user": "root",
"bootstrap_template": "chef_freebsd",
"id": "<%= @config["openstack"]["image"] %>"
}
""" """
Then response should be '400' Then response should be '400'
@openstack <% end #invalid values%>
Scenario: Update openstack image with invalid provider - array
When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body <% 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
""" """
{ <%= @formatter.json(provider + '/image', {value: {key => nil}}) %>
"provider": ["foo"],
"name": "freebsd-10.0",
"remote_user": "root",
"bootstrap_template": "chef_freebsd",
"id": "<%= @config["openstack"]["image"] %>"
}
""" """
Then response should be '400' Then response should be '400'
@openstack <% end %>
Scenario: Update openstack image with invalid provider - hash
When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body <% (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
""" """
{ <%= @formatter.json(provider + '/image', {value: {key => "foo"}}) %>
"provider": {},
"name": "freebsd-10.0",
"remote_user": "root",
"bootstrap_template": "chef_freebsd",
"id": "<%= @config["openstack"]["image"] %>"
}
""" """
Then response should be '400' Then response should be '400'
@openstack <% end %>
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'
@openstack <% [[], {}, "foo", nil].each do |value| %>
Scenario: Update openstack image with invalid name - array @<%= provider %>
When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body Scenario: Update <%= provider %> image with invalid id value: '<%= value %>'
When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body
""" """
{ <%= @formatter.json(provider + '/image', {value: {"id" => value}}) %>
"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": []
}
""" """
Then response should be '200' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
@ -173,21 +64,16 @@ Feature: Update images
And response should be JSON object like: And response should be JSON object like:
""" """
{ {
"message" : "Image '<%= @config["openstack"]["image"] %>' has been updated" "message" : "Image '<%= image["id"] %>' has been updated"
} }
""" """
@openstack <% end %>
Scenario: Update openstack image with invalid id - hash
When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body Scenario: Update <%= provider %> image without id
When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body
""" """
{ <%= @formatter.json(provider + '/image', {without_field: "id"}) %>
"provider": "openstack",
"name": "freebsd-10.0",
"remote_user": "root",
"bootstrap_template": "chef_freebsd",
"id": {}
}
""" """
Then response should be '200' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
@ -195,21 +81,15 @@ Feature: Update images
And response should be JSON object like: And response should be JSON object like:
""" """
{ {
"message" : "Image '<%= @config["openstack"]["image"] %>' has been updated" "message" : "Image '<%= image["id"] %>' has been updated"
} }
""" """
@openstack @<%= provider %>
Scenario: Update openstack image Scenario: Update <%= provider %> image
When I send PUT '/v2.0/image/<%= @config["openstack"]["image"] %>' query with JSON body When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body
""" """
{ <%= @formatter.json(provider + '/image') %>
"provider": "openstack",
"name": "freebsd-10.0",
"remote_user": "root",
"bootstrap_template": "chef_freebsd",
"id": "<%= @config["openstack"]["image"] %>"
}
""" """
Then response should be '200' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
@ -217,175 +97,15 @@ Feature: Update images
And response should be JSON object like: And response should be JSON object like:
""" """
{ {
"message" : "Image '<%= @config["openstack"]["image"] %>' has been updated" "message" : "Image '<%= image["id"] %>' has been updated"
} }
""" """
@ec2 @<%= provider %>
Scenario: Update ec2 image with openstack provider Scenario: Update <%= provider %> image with bootstrap_template null
When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body
""" """
{ <%= @formatter.json(provider + '/image', {value: {"bootstrap_template" => nil}}) %>
"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": []
}
""" """
Then response should be '200' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
@ -393,21 +113,15 @@ Feature: Update images
And response should be JSON object like: And response should be JSON object like:
""" """
{ {
"message" : "Image '<%= @config["openstack"]["image"] %>' has been updated" "message" : "Image '<%= image["id"] %>' has been updated"
} }
""" """
@ec2 @<%= provider %>
Scenario: Update ec2 image with invalid id - hash Scenario: Update <%= provider %> image with old bootstrap_template: '<%= image["bootstrap_template"] %>'
When I send PUT '/v2.0/image/<%= @config["ec2"]["image"] %>' query with JSON body When I send PUT '/v2.0/image/<%= image["id"] %>' query with JSON body
""" """
{ <%= @formatter.json(provider + '/image', {value: {"bootstrap_template" => image["bootstrap_template"]}}) %>
"provider": "ec2",
"name": "test-ec2",
"remote_user": "ec2-user",
"bootstrap_template": null,
"id": {}
}
""" """
Then response should be '200' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
@ -415,28 +129,9 @@ Feature: Update images
And response should be JSON object like: And response should be JSON object like:
""" """
{ {
"message" : "Image '<%= @config["openstack"]["image"] %>' has been updated" "message" : "Image '<%= image["id"] %>' has been updated"
} }
""" """
@ec2 <% end #providers %>
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"
}
"""

View File

@ -1,42 +1,37 @@
@image @project @image @project
Feature: delete image Feature: delete image
@openstack <% providers = @formatter.get_fixture('providers/without_static') %>
Scenario: Delete openstack image with user without privileges <% providers.each do |provider| %>
When I send DELETE '/v2.0/image/<%= @config["openstack"]["image"] %>' query with user without privileges <% 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' Then response should be '401'
@openstack @<%= provider %>
Scenario: Delete openstack image Scenario: Delete <%= provider %> image
When I send DELETE '/v2.0/image/<%= @config["openstack"]["image"] %>' query When I send DELETE '/v2.0/image/<%= image["id"] %>' query
Then response should be '200' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
And the JSON response should be an object And the JSON response should be an object
And response should be JSON object like: And response should be JSON object like:
""" """
{ {
"message" : "Image '<%= @config["openstack"]["image"] %>' has been removed" "message" : "Image '<%= image["id"] %>' has been removed"
} }
""" """
@ec2 @<%= provider %>
Scenario: Delete ec2 image with user without privileges Scenario: Delete <%= provider %> image with header 'Accept' value is not 'application/json'
When I send DELETE '/v2.0/image/<%= @config["ec2"]["image"] %>' query with user without privileges When I send DELETE '/v2.0/image/<%= image["id"] %>' query with header 'Accept' value 'application/xml'
Then response should be '401' Then response should be '406'
@ec2 <% end #providers %>
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"
}
"""
<% providers = @formatter.get_fixture('providers/all').map{|provider| "@#{provider}"} %>
<%= providers.join(" ") %>
Scenario: Delete unknown image Scenario: Delete unknown image
When I send DELETE '/v2.0/image/foo' query When I send DELETE '/v2.0/image/foo' query
Then response should be '404' Then response should be '404'

View File

@ -1,16 +1,22 @@
@user @user
Feature: delete user Feature: delete user
<% user_hash = @formatter.get_fixture('user/create') %>
<% username = user_hash["username"] %>
Scenario: delete user with user without privileges 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' Then response should be '401'
Scenario: delete unknown user Scenario: delete unknown user
When I send DELETE '/v2.0/user/unknown' query When I send DELETE '/v2.0/user/unknown' query
Then response should be '404' 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 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' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'

View File

@ -1,153 +1,58 @@
@filter @image @project @filter @image @project
Feature: Filters Feature: Filters
@openstack <% @formatter.get_fixture('providers/without_static').each do |provider| %>
Scenario: Delete openstack image filter with user without privileges <% image = @formatter.get_fixture(provider + "/image")["id"] %>
When I send DELETE '/v2.0/filter/openstack/image' query with user without privileges @<%= 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' Then response should be '401'
@openstack @<%= provider %>
Scenario: Delete openstack image filter without header 'Content-Type' Scenario: Delete images filter with header 'Accept' value not 'application/json'
When I send DELETE '/v2.0/filter/openstack/image' query with JSON body without header 'Content-Type' 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' Then response should be '415'
@openstack <% ["", "{}", "[{}]", "[[]]", "[null]"].each do |body| %>
Scenario: Delete openstack image filter, invalid body: empty @<%= provider %>
When I send DELETE '/v2.0/filter/openstack/image' query with JSON body 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' Then response should be '400'
@openstack <% end %>
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'
@openstack @<%= provider %>
Scenario: Delete openstack image filter, invalid body: element is hash Scenario: Delete <%= provider %> image filter
When I send DELETE '/v2.0/filter/openstack/image' query with JSON body When I send DELETE '/v2.0/filter/<%= provider %>/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
""" """
[ [
[] "<%= image %>"
]
"""
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"] %>"
] ]
""" """
Then response should be '200' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
And the JSON response should be an object 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 @<%= provider %>
Scenario: Delete ec2 image filter with user without privileges Scenario: Get new (after delete) <%= provider %> image filter and check value '<%= image %>'
When I send DELETE '/v2.0/filter/ec2/image' query with user without privileges When I send GET '/v2.0/filter/<%= provider %>/images' query
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"] %>"
]
"""
Then response should be '200' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
And the JSON response should be an object And the JSON response should be an array
And the object should contains key 'images' with array and array should not contains strings '<%= @config["ec2"]["image"] %>' And the array should not contains strings '<%= image %>'
<% end %>

View File

@ -1,9 +1,18 @@
@key <% providers = @formatter.get_fixture('providers/all').map{|p| "@#{p}"} %>
@key <%= providers.join(" ") %>
Feature: Delete key 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 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' Then response should be '200'
And the Content-Type header should include 'application/json' And the Content-Type header should include 'application/json'
And the JSON response should be an object And the JSON response should be an object

View File

@ -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

View File

@ -1,34 +1,42 @@
require 'json' require 'json'
require 'pp'
class FixtureFormatter class FixtureFormatter
def initialize(fixtures) def initialize(fixtures)
@fixtures = fixtures @fixtures = fixtures
if ENV["DEBUG"]
puts "Loaded fixtures:"
pp @fixtures
end
end end
def json(path, options={}) def json(path, options={})
result = nil
begin begin
result = JSON.pretty_generate(get_fixture(path)) result = JSON.pretty_generate(get_fixture(path, options))
rescue rescue
raise "Fixture '#{path}' is absent" raise "Fixture '#{path}' is absent"
end end
if options[:spaces] options[:spaces] = 4 unless options[:spaces]
result = shift_to_right(result, options[:spaces]) result = shift_to_right(result, options[:spaces])
end
result result
end end
private def get_fixture(path, options={})
def get_fixture(path)
keys = path.split('/') keys = path.split('/')
hash = @fixtures hash = @fixtures
keys.each do |key| keys.each do |key|
hash = hash[key] hash = hash[key]
end end
hash = hash.clone
hash.merge!(options[:value]) if options[:value]
hash.delete(options[:without_field]) if options[:without_field]
hash hash
end end
private
def shift_to_right(text, spaces_count) def shift_to_right(text, spaces_count)
buffer = '' buffer = ''
first_line = true first_line = true

View File

@ -1,20 +1,8 @@
valid: &valid list_element:
scope: "system"
id: "devops"
new: &valid
file_name: test_file_name file_name: test_file_name
key_name: test_key_name key_name: test_key_name
content: test_content 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

View File

@ -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

View File

@ -0,0 +1,3 @@
name: cucumber_project
description: "Cucumber test project"

View File

@ -0,0 +1,4 @@
without_static:
[openstack, ec2]
all:
[openstack, ec2, static]

View File

@ -0,0 +1,7 @@
deploy_env:
identifier: static_env
provider: "static"
run_list: []
expires: null
users: []

View File

@ -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

View File

@ -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