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

This commit is contained in:
Tim Lianov 2015-12-08 16:54:33 +04:00
commit 1e012d3e8f
41 changed files with 1234 additions and 96 deletions

View File

@ -10,7 +10,7 @@ gem "sinatra-websocket"#, "~>0.3.0"
gem "fog", "~>1.20"
gem "mixlib-shellout"
gem "chef", ">=12"
gem "mongo"
gem "mongo", '1.12.3'
gem "bson_ext"
gem "multi_json", "1.7.8"
gem "sidekiq", "3.2.6"

View File

@ -344,7 +344,7 @@ DEPENDENCIES
httpclient
mime-types (~> 1.25.1)
mixlib-shellout
mongo
mongo (= 1.12.3)
multi_json (= 1.7.8)
rack (= 1.5.2)
rack-accept-media-types

View File

@ -29,6 +29,7 @@ config[:openstack_ssh_key] = "ssh_key"
config[:openstack_certificate] = "/path/to/.ssh/openstack.pem"
# aws settings
config[:aws_use_iam_profile] = false
config[:aws_access_key_id] = "access_key_id"
config[:aws_secret_access_key] = "secret_access_key"
config[:aws_ssh_key] = "ssh_key"

View File

@ -20,23 +20,24 @@ module Connectors
f = collection.find('type' => 'image', 'provider' => provider).to_a.first
if f.nil?
collection.insert('type' => 'image', 'provider' => provider, 'images' => images)
return images
images
else
f['images'] |= images
collection.update({'_id' => f['_id']}, f)
return f['images']
f['images']
end
end
def delete_available_images images, provider
return unless images.is_a?(Array)
f = collection.find('type' => 'image', 'provider' => provider).to_a.first
unless f.nil?
f['images'] -= images
collection.update({'_id' => f['_id']}, f)
return f['images']
end
filter = collection.find('type' => 'image', 'provider' => provider).to_a.first
if filter
filter['images'] -= images
collection.update({'_id' => filter['_id']}, filter)
filter['images']
else
[]
end
end
end
end

View File

@ -14,16 +14,10 @@ module Connectors
end
def update(record)
begin
record.validate!
collection.update({"_id" => record.id}, record.to_mongo_hash)
r = collection.update({"_id" => record.id}, record.to_mongo_hash)
raise RecordNotFound.new("'#{record.id}' not found") if r['n'] == 0
record
rescue Mongo::OperationFailure => e
if e.message =~ /^11000/
resource_name = StringHelper.underscore_class(record.class)
raise InvalidRecord.new("Duplicate key error: #{resource_name} with id '#{record.id}'")
end
end
end
end

View File

@ -2,9 +2,7 @@ module Connectors
class Project < Base
include Helpers::InsertCommand,
Helpers::ShowCommand,
# Helpers::ListCommand,
Helpers::DeleteCommand
# Helpers::UpdateCommand
def initialize(db)
@ -73,7 +71,7 @@ module Connectors
res.each do |ar|
r[ar['_id']] = ar['envs']
end
return r
r
end
def projects_by_image(image)
@ -98,10 +96,9 @@ module Connectors
project
end
def projects_and_deploy_envs_by_field field, value
q = {}
q[field] = value
# {find all projects with deploy_envs with field=value}, {return deploy_envs with field=value}
def projects_and_deploy_envs_by_field field, value
q = {field => value}
list( {'deploy_envs' => {'$elemMatch' => q}}, {:fields => {'deploy_envs' => {'$elemMatch' => q}}} )
end
@ -114,12 +111,12 @@ module Connectors
end
def set_project_env_run_list(project_id, env, run_list)
Helpers::RunList.new(run_list).validate!
::Validators::Helpers::RunList.new(run_list).validate!
set_project_deploy_env_field(project_id, env, {"run_list" => run_list})
end
def set_project_run_list(project_id, env, run_list)
Helpers::RunList.new(run_list).validate!
def set_project_run_list(project_id, run_list)
::Validators::Helpers::RunList.new(run_list).validate!
@collection.update({"_id" => project_id}, {"$set" => {run_list: run_list}})
end
@ -128,17 +125,16 @@ module Connectors
end
def remove_deploy_env_from_project id, env
raise ArgumentError unless env.is_a?(String)
@collection.update({"_id" => id}, {'$pull' => {deploy_envs: {identifier: env}} })
end
def project_update_field id, field, value
obj = {}
obj[field] = value
obj = {field => value}
@collection.update({"_id" => id}, {'$set' => obj })
end
def project_update id, params
#raise InvalidRecord.new("You can not change project name for '#{id}'.") if params["name"]
keys = %w(run_list description)
params.delete_if{|k,v| !keys.include?(k)}
@collection.update({"_id" => id}, {'$set' => params })

View File

@ -11,13 +11,12 @@ module Devops
module Model
class CloudDeployEnv < DeployEnvBase
# attr_accessor :flavor, :image, :subnets, :groups, :stack_template
attr_accessor :flavor, :image, :subnets, :groups, :stack_template
set_validators ::Validators::DeployEnv::Flavor,
::Validators::DeployEnv::Image,
::Validators::DeployEnv::Groups,
::Validators::DeployEnv::StackTemplate
# set_validators ::Validators::DeployEnv::CloudParameters
set_field_validators :flavor, [::Validators::FieldValidator::Nil,
::Validators::FieldValidator::FieldType::String,
::Validators::FieldValidator::Flavor], order: 2

View File

@ -23,16 +23,27 @@ module Devops
attr_accessor :id, :deploy_envs, :type, :archived, :description, :run_list
types :id => {:type => String, :empty => false},
:deploy_envs => {:type => Array, :value_type => false, :empty => false},
:description => {:type => String, :empty => true, :nil => true},
:run_list => {:type => Array, :value_type => String, :empty => true, :nil => false}
MULTI_TYPE = "multi"
set_field_validators :id, [::Validators::FieldValidator::NotNil,
::Validators::FieldValidator::FieldType::String,
::Validators::FieldValidator::NotEmpty]
set_field_validators :deploy_envs, [::Validators::FieldValidator::NotNil,
::Validators::FieldValidator::FieldType::Array,
::Validators::FieldValidator::NotEmpty]
set_field_validators :description, [::Validators::FieldValidator::Nil,
::Validators::FieldValidator::FieldType::String]
set_field_validators :run_list, [::Validators::FieldValidator::NotNil,
::Validators::FieldValidator::FieldType::Array,
::Validators::FieldValidator::RunList]
set_validators ::Validators::DeployEnv::RunList,
::Validators::DeployEnv::DeployEnvs
def self.fields
["deploy_envs", "type", "description"]
end
@ -70,11 +81,14 @@ module Devops
Project.create_roles_response(res)
end
# user could be a String or an Array of strings.
# if env is nil, add given user(s) to all project's envs,
# otherwise only to specified one.
def add_authorized_user user, env=nil
return if user.nil?
new_users = ( user.is_a?(Array) ? user : [ user ] )
environments = env.nil? ? self.deploy_envs : [ self.deploy_env(env) ]
environments .each do |e|
environments.each do |e|
e.add_users new_users
Devops::Db.connector.set_project_deploy_env_field(self.id, e.identifier, {users: e.users})
end
@ -202,7 +216,8 @@ module Devops
end
def self.create_roles_response roles
if !roles || roles.is_a?(String)
return "error in creating roles" unless roles
if roles.is_a?(String)
roles
else
info = ""

View File

@ -13,6 +13,9 @@ module Devops
set_field_validators :secret_access_key, [::Validators::FieldValidator::NotNil,
::Validators::FieldValidator::FieldType::String,
::Validators::FieldValidator::NotEmpty]
set_field_validators :use_iam_profile, [::Validators::FieldValidator::Nil,
::Validators::FieldValidator::FieldType::Boolean]
def initialize a={}
super(a)
self.provider = Provider::Ec2::PROVIDER
@ -45,6 +48,7 @@ module Devops
{
access_key_id: "AWS account access key",
secret_access_key: "AWS account secret key",
use_iam_profile: "Should use iam profile?",
availability_zone: "Availability zone, todo: remove field?"
}.merge(ProviderAccount::ACCOUNT_FIELDS)
end

View File

@ -18,8 +18,8 @@ module Devops
set_field_validators :id, [::Validators::FieldValidator::NotNil,
::Validators::FieldValidator::FieldType::String,
::Validators::FieldValidator::NotEmpty,]
::Validators::FieldValidator::Name
::Validators::FieldValidator::NotEmpty,
::Validators::FieldValidator::Name]
set_field_validators :provider, [::Validators::FieldValidator::NotNil,
::Validators::FieldValidator::FieldType::String,

View File

@ -1,6 +1,8 @@
require_relative "stack_template_base"
require_relative "stack_template_openstack"
require_relative "stack_template_ec2"
require 'providers/openstack'
require 'providers/ec2'
module Devops
module Model

View File

@ -25,6 +25,17 @@ module Validators
end
end
class Boolean < FieldType
def valid?
@value == true or @value == false
end
def type_name
"boolean"
end
end
class Array < FieldType
def type

View File

@ -15,10 +15,14 @@ module Provider
self.certificate_path = config[:aws_certificate]
self.ssh_key = config[:aws_ssh_key]
options = {
:provider => "aws",
:aws_access_key_id => config[:aws_access_key_id],
:aws_secret_access_key => config[:aws_secret_access_key]
:provider => "aws"
}
if config[:aws_use_iam_profile]
options[:use_iam_profile] = true
else
options[:aws_access_key_id] = config[:aws_access_key_id]
options[:aws_secret_access_key] = config[:aws_secret_access_key]
end
if config[:aws_proxy] and config[:aws_no_proxy]
options[:connection_options] = {
:proxy => config[:aws_proxy],

View File

@ -20,6 +20,7 @@ module Provider
aws_ssh_key: account.ssh_key,
aws_access_key_id: account.access_key_id,
aws_secret_access_key: account.secret_access_key,
aws_use_iam_profile: account.use_iam_profile,
aws_availability_zone: account.availability_zone,
aws_proxy: config[:aws_proxy],

View File

@ -0,0 +1,90 @@
require 'db/mongo/connectors/filter'
require 'spec/connectors/tester_connector/filter'
require_relative 'shared_connectors_context'
RSpec.describe Connectors::Filter, type: :connector do
set_tester_connector TesterConnector::Filter
include_context 'connectors'
let(:provider) {'ec2'}
describe '#available_images' do
subject { @connector.available_images(provider) }
context 'when there is no filter for given provider' do
it 'returns empty array' do
expect(subject).to eq []
end
context 'when there is filter for given provider but for another type' do
it 'returns empty array' do
test_filter = {provider: provider, type: 'foo', images: ['foo', 'bar']}
@tester_connector.create(test_filter) do
expect(subject).to eq []
end
end
end
end
context 'when there is filter for given provider' do
it "returns array with images' names" do
test_filter = {provider: provider, type: 'image', images: ['foo', 'bar']}
@tester_connector.create(test_filter) do
expect(subject).to match_array ['foo', 'bar']
end
end
end
end
describe '#add_available_images', cleanup_after: :each do
subject { @connector.add_available_images(['foo'], provider) }
it "do nothing if images is not Array" do
expect {
result = @connector.add_available_images('foo', provider)
expect(result).to be_nil
}.not_to change {@tester_connector.list}
end
it 'creates filter if there is no one' do
expect(@tester_connector.list.empty?).to be true
expect(subject).to match_array ['foo']
expect(@tester_connector.list.empty?).to be false
end
it 'updates filter if one already exists' do
@tester_connector.create(provider: provider, type: 'image', images: ['bar'])
expect(subject).to match_array ['bar', 'foo']
expect(@tester_connector.list.first['images']).to match_array ['bar', 'foo']
end
it "doesn't duplicate images in filter" do
@tester_connector.create(provider: provider, type: 'image', images: ['foo'])
expect(subject).to match_array ['foo']
expect(@tester_connector.list.first['images']).to match_array ['foo']
end
end
describe '#delete_available_images' do
subject { @connector.delete_available_images(['foo'], provider) }
after { @tester_connector.cleanup }
let(:create_filter) { @tester_connector.create(provider: provider, type: 'image', images: ['foo', 'bar']) }
it 'does nothing if images is not Array' do
create_filter
expect {
result = @connector.delete_available_images('foo', provider)
expect(result).to be_nil
}.not_to change{ @tester_connector.list.first['images'] }
end
it 'removes given images from filter' do
create_filter
expect(subject).to match_array ['bar']
expect(@tester_connector.list.first['images']).to match_array ['bar']
end
it 'returns empty array if there is no filter' do
expect(subject).to eq []
end
end
end

View File

@ -0,0 +1,37 @@
require 'db/mongo/connectors/image'
require 'spec/connectors/tester_connector/image'
require_relative 'shared_connectors_context'
RSpec.describe Connectors::Image, type: :connector do
set_tester_connector TesterConnector::Image
include_context 'connectors'
let(:model_class) { Devops::Model::Image }
include_examples 'mongo connector', {
model_name: :image,
only: [:insert, :show, :update, :delete],
field_to_update: :name
}
describe '#images', cleanup_after: :each do
subject { @connector.images('ec2') }
it 'should be empty if collection is empty' do
expect(subject).to eq []
end
it "returns array of Model::Key's of given provider" do
@tester_connector.create(provider: 'ec2')
@tester_connector.create(provider: 'openstack')
expect(subject).to be_an_array_of(model_class).and have_size(1)
expect(subject.first.provider).to eq 'ec2'
end
it 'returns images for both providers if is is unset' do
@tester_connector.create(provider: 'ec2')
@tester_connector.create(provider: 'openstack')
expect(@connector.images.length).to eq 2
end
end
end

View File

@ -0,0 +1,62 @@
require 'db/mongo/connectors/key'
require 'db/mongo/models/key'
require 'spec/connectors/tester_connector/key'
require_relative 'shared_connectors_context'
RSpec.describe Connectors::Key, type: :connector do
set_tester_connector TesterConnector::Key
include_context 'connectors'
let(:model_class) { Devops::Model::Key }
include_examples 'mongo connector', model_name: :key, only: [:insert, :list]
describe '#key' do
context 'when scope was passed' do
subject { @connector.key('foo') }
it 'raises RecordNotFound when there is no such record' do
expect { subject }.to raise_error(RecordNotFound)
end
it 'returns record if was found' do
@tester_connector.create(id: 'foo') do
expect(subject).to be_an_instance_of(model_class)
end
end
end
context 'when scope was passed' do
subject { @connector.key('foo', 'user') }
it 'raises RecordNotFound when there is no such record' do
expect { subject }.to raise_error(RecordNotFound)
end
it 'returns record if was found' do
@tester_connector.create(id: 'foo', scope: 'user') do
expect(subject).to be_an_instance_of(model_class)
end
end
end
end
describe '#key_delete' do
subject { @connector.key_delete('foo') }
it 'raises RecordNotFound if there is no such record' do
expect{ subject }.to raise_error(RecordNotFound)
end
it 'remove key in "user" scope' do
@tester_connector.create(id: 'foo', scope: 'user')
subject
expect(@tester_connector.list).to eq []
end
it "doesn't remove key in 'system' scope" do
@tester_connector.create(id: 'foo', scope: 'system') do
expect {subject}.to raise_error RecordNotFound
end
end
end
end

View File

@ -0,0 +1,295 @@
require 'db/mongo/connectors/project'
require 'spec/connectors/tester_connector/project'
require_relative 'shared_connectors_context'
RSpec.describe Connectors::Project, type: :connector do
set_tester_connector TesterConnector::Project
include_context 'connectors'
let(:model_class) { Devops::Model::Project }
include_examples 'mongo connector', {
model_name: :project,
factory_name: :project,
only: [:insert, :show, :delete],
field_to_update: :deploy_envs
}
describe '#is_project_exists?' do
subject { @connector.is_project_exists?(build(:project, id: 'foo')) }
it 'returns true if project exists' do
@tester_connector.create(id: 'foo') do
expect(subject).to be true
end
end
it 'returns false if project doesn\'t exists' do
expect(subject).to be false
end
end
describe '#projects_all' do
it 'returns array of projects' do
@tester_connector.create_list(2) do
result = @connector.projects_all
expect(result).to be_an_array_of(model_class).and have_size(2)
end
end
end
describe '#projects', cleanup_after: :all do
before(:all) do
@tester_connector.create build(:project, id: 'foo', type: 'multi').to_mongo_hash
@tester_connector.create build(:project, id: 'bar', archived: true).to_mongo_hash
@tester_connector.create build(:project, id: 'baz').to_mongo_hash
end
it 'returns non archived projects with all params unset' do
expect(@connector.projects).to have_size(2)
end
it 'returns projects with given ids' do
result = @connector.projects(%w(foo baz))
expect(result).to be_an_array_of(model_class)
expect(result.map(&:id)).to match_array(%w(foo baz))
end
it 'returns multi projects if @type == :multi' do
expect(
@connector.projects(nil, :multi).map(&:id)
).to match_array ['foo']
end
it 'returns only given fields and id if @fields is set' do
result = @connector.projects(nil, nil, [:deploy_envs])
expect(result.map(&:id).compact).not_to eq []
expect(result.map(&:deploy_envs).compact).not_to eq []
expect(result.map(&:description).compact).to eq []
end
it 'returns only archived projects if @archived=true' do
result = @connector.projects(nil, nil, [], true)
expect(result.map(&:id)).to match_array(%w(bar))
end
end
describe '#project_names_with_envs', cleanup_after: :all do
before(:all) do
@tester_connector.create(
id: 'foo',
deploy_envs: [{identifier: 'env1'}, {identifier: 'env2'}]
)
@tester_connector.create(
id: 'bar',
deploy_envs: [{identifier: 'env3'}, {identifier: 'env4'}]
)
end
it 'returns hash like {"project_name" => ["env1", "env2]}' do
result = @connector.project_names_with_envs
expect(result.keys.sort).to match_array %w(foo bar)
expect(result['foo'].sort).to match_array %w(env1 env2)
expect(result['bar'].sort).to match_array %w(env3 env4)
end
it 'returns only projects with given names' do
expect(@connector.project_names_with_envs(['bar']).keys).to match_array %w(bar)
end
end
describe '#projects_by_image', cleanup_after: :each do
def env(image)
{image: image, provider: 'ec2'}
end
it 'returns projects deploy_envs of which have given image' do
@tester_connector.create(id: 'foo', deploy_envs: [env('a'), env('b')])
@tester_connector.create(id: 'bar', deploy_envs: [env('a'), env('a')])
@tester_connector.create(id: 'baz', deploy_envs: [env('b'), env('b')])
result = @connector.projects_by_image('a')
expect(result).to be_an_array_of(model_class)
expect(result.map(&:id)).to match_array %w(foo bar)
end
end
describe '#projects_by_user', cleanup_after: :each do
def env(users)
{users: users, provider: 'ec2'}
end
it 'returns projects deploy_envs of which have given user' do
@tester_connector.create(id: 'foo', deploy_envs: [ env(%w(user1 user2)) ])
@tester_connector.create(id: 'bar', deploy_envs: [ env(%w(user1 user1)) ])
@tester_connector.create(id: 'baz', deploy_envs: [ env(%w(user2 user2)) ])
@tester_connector.create(id: 'baf', deploy_envs: [ env(%w(user1)), env(%w(user2)) ])
result = @connector.projects_by_user('user1')
expect(result).to be_an_array_of(model_class)
expect(result.map(&:id)).to match_array %w(foo bar baf)
end
end
describe '#archive_project' do
it 'sets archived to true' do
@tester_connector.create(id: 'foo') do
@connector.archive_project('foo')
expect(@tester_connector.show('foo')).to include('archived' => true)
end
end
end
describe '#unarchive_project' do
it 'unsets archived' do
@tester_connector.create(id: 'foo', archived: true) do
@connector.unarchive_project('foo')
expect(@tester_connector.show('foo')).not_to include('archived')
end
end
end
describe '#check_project_auth', cleanup_after: :all do
before(:all) do
@tester_connector.create(id: 'foo', deploy_envs: [
{identifier: 'bar', provider: 'ec2', users: %w(user1)}
])
end
it "raises InvalidPrivileges if given env users don't include given user" do
expect {
@connector.check_project_auth('foo', 'bar', 'user2')
}.to raise_error(InvalidPrivileges)
end
it "returns project if env's users include given user" do
result = @connector.check_project_auth('foo', 'bar', 'user1')
expect(result).to be_an_instance_of(model_class)
expect(result.id).to eq 'foo'
end
end
describe '#projects_and_deploy_envs_by_field', cleanup_after: :all do
def env(field, value)
{provider: 'ec2', field => value}
end
before(:all) do
@tester_connector.create(id: 'foo', deploy_envs: [
env(:image, 'image1'), env(:stack_template, 'template1')
])
end
it 'returns projects with deploy envs containing given field with given value' do
expect(
@connector.projects_and_deploy_envs_by_field(:image, 'image1').map(&:id)
).to match_array %w(foo)
expect(
@connector.projects_and_deploy_envs_by_field(:stack_template, 'template1').map(&:id)
).to match_array %w(foo)
end
end
describe '#set_project_deploy_env_field', cleanup_after: :each do
it 'updates given env from given field_value_hash' do
@tester_connector.create(id: 'foo', deploy_envs: [
{identifier: 'bar', provider: 'ec2'}
])
@connector.set_project_deploy_env_field('foo', 'bar', image: 'a', stack_template: 'b')
updated_project = @tester_connector.show('foo')
expect(updated_project['deploy_envs'].first['image']).to eq 'a'
expect(updated_project['deploy_envs'].first['stack_template']).to eq 'b'
end
end
describe '#set_project_env_run_list', cleanup_after: :all do
before(:all) do
@tester_connector.create(id: 'foo', deploy_envs: [{identifier: 'bar', provider: 'ec2'}])
end
before { allow_any_instance_of(Validators::Helpers::RunList).to receive(:validate!) }
it 'validates run list' do
run_list = []
expect_any_instance_of(Validators::Helpers::RunList).to receive(:validate!)
@connector.set_project_env_run_list('foo', 'bar', run_list)
end
it "updates env's RunList" do
run_list = ['role[foo]']
@connector.set_project_env_run_list('foo', 'bar', run_list)
expect(@tester_connector.show('foo')['deploy_envs'].first['run_list']).to eq run_list
end
end
describe '#set_project_env_run_list', cleanup_after: :all do
before(:all) do
@tester_connector.create(id: 'foo')
end
before { allow_any_instance_of(Validators::Helpers::RunList).to receive(:validate!) }
it 'validates run list' do
run_list = []
expect_any_instance_of(Validators::Helpers::RunList).to receive(:validate!)
@connector.set_project_run_list('foo', run_list)
end
it "updates project's RunList" do
run_list = ['role[foo]']
@connector.set_project_run_list('foo', run_list)
expect(@tester_connector.show('foo')['run_list']).to eq run_list
end
end
describe '#add_deploy_env_to_project' do
it 'adds env to project' do
@tester_connector.create(id: 'foo', deploy_envs: []) do
@connector.add_deploy_env_to_project('foo', build(:deploy_env))
expect(@tester_connector.show('foo')['deploy_envs']).not_to be_empty
end
end
end
describe '#remove_deploy_env_from_project', cleanup_after: :each do
before { @tester_connector.create(id: 'foo', deploy_envs: [{identifier: 'bar'}]) }
it "removes env from project" do
@connector.remove_deploy_env_from_project('foo', 'bar')
expect(@tester_connector.show('foo')['deploy_envs']).to be_empty
end
it 'raises ArgumentError if given env is not a String' do
env = build(:deploy_env_ec2, identifier: 'bar')
expect { @connector.remove_deploy_env_from_project('foo', env) }.to raise_error(ArgumentError)
end
end
describe '#project_update_field', cleanup_after: :each do
before { @tester_connector.create(id: 'foo', description: 'desc', run_list: []) }
subject { @connector.project_update_field('foo', 'run_list', ['role[a]']) }
it 'updates given field of given project' do
expect {subject}.to change { @tester_connector.show('foo')['run_list'] }.to ['role[a]']
end
it "doesn't affect other fields" do
expect {subject}.not_to change { @tester_connector.show('foo')['desc'] }
end
end
describe '#project_update', cleanup_after: :each do
before { @tester_connector.create(id: 'foo', deploy_envs: [], description: 'desc', run_list: []) }
subject {
attrs = {'id' => 'foo2', 'deploy_envs' => [build(:deploy_env)], 'description' => 'desc2', 'run_list' => ['role[asd]']}
@connector.project_update('foo', attrs)
}
let(:updated_project) { @tester_connector.show('foo') }
it 'can update run_list and description' do
subject
expect(updated_project['run_list']).to eq ['role[asd]']
expect(updated_project['description']).to eq 'desc2'
end
it 'can not update other fields' do
subject
expect(updated_project['_id']).to eq 'foo'
expect(updated_project['deploy_envs']).to eq []
end
end
end

View File

@ -0,0 +1,22 @@
def set_tester_connector(klass)
define_method :tester_connector_class do
klass
end
end
RSpec.shared_context 'connectors' do
before(:all) do
@connector = described_class.new(SpecSupport.db)
@tester_connector = tester_connector_class.new
@tester_connector.cleanup
end
after(:all){ @tester_connector.cleanup }
end
RSpec.shared_context 'cleanup after all', cleanup_after: :all do
after(:all){ @tester_connector.cleanup }
end
RSpec.shared_context 'cleanup after each', cleanup_after: :each do
after { @tester_connector.cleanup }
end

View File

@ -0,0 +1,42 @@
require 'db/mongo/connectors/stack_template'
require 'spec/connectors/tester_connector/stack_template'
require_relative 'shared_connectors_context'
RSpec.describe Connectors::StackTemplate, type: :connector do
set_tester_connector TesterConnector::StackTemplate
include_context 'connectors'
let(:model_class) { Devops::Model::StackTemplateEc2 }
include_examples 'mongo connector', {
model_name: :stack_template,
factory_name: :stack_template_ec2,
only: [:insert, :show, :update, :delete],
field_to_update: :owner
}
describe '#stack_templates' do
subject { @connector.stack_templates('ec2') }
it 'should be empty if collection is empty' do
expect(subject).to eq []
end
it "returns array of stack_templates of given provider" do
@tester_connector.create(provider: 'ec2')
@tester_connector.create(provider: 'openstack')
expect(subject).to be_a(Array)
expect(subject.length).to eq 1
expect(subject.first).to be_an_instance_of(model_class)
expect(subject.first.provider).to eq 'ec2'
@tester_connector.cleanup
end
it 'returns stack_templates for both providers if is is unset' do
@tester_connector.create(provider: 'ec2')
@tester_connector.create(provider: 'openstack')
expect(@connector.stack_templates.length).to eq 2
@tester_connector.cleanup
end
end
end

View File

@ -0,0 +1,53 @@
module TesterConnector
class Base
attr_reader :collection
def initialize
collection_name = self.class.name.demodulize.underscore.pluralize
@collection = SpecSupport.db.collection(collection_name)
@next_id = 1
end
def create(hash={})
collection.insert(create_params(hash))
if block_given?
yield
cleanup
end
end
def create_list(size=2, hash={})
size.times { create(hash) }
if block_given?
yield
cleanup
end
end
def list
collection.find().to_a
end
def show(id)
collection.find({'_id' => id}).to_a.first
end
def cleanup
collection.remove
end
private
def create_params(hash)
params = hash.dup
if params[:id]
params['_id'] = params.delete(:id)
end
unless params['_id']
params['_id'] = @next_id
@next_id += 1
end
params
end
end
end

View File

@ -0,0 +1,6 @@
require_relative 'base'
module TesterConnector
class Filter < Base
end
end

View File

@ -0,0 +1,6 @@
require_relative 'base'
module TesterConnector
class Image < Base
end
end

View File

@ -0,0 +1,6 @@
require_relative 'base'
module TesterConnector
class Key < Base
end
end

View File

@ -0,0 +1,6 @@
require_relative 'base'
module TesterConnector
class Project < Base
end
end

View File

@ -0,0 +1,6 @@
require_relative 'base'
module TesterConnector
class StackTemplate < Base
end
end

View File

@ -2,6 +2,7 @@ require 'db/mongo/models/key'
FactoryGirl.define do
factory :key, class: Devops::Model::Key do
id 'user_key'
path SpecSupport::BLANK_FILE
scope 'user'
end

View File

@ -0,0 +1,23 @@
require 'db/mongo/models/project'
FactoryGirl.define do
factory :project, class: Devops::Model::Project do
transient do
with_deploy_env_identifier false
with_deploy_env_identifiers ['foo']
end
id 'my_project'
run_list []
description 'desc'
after(:build) do |project, evaluator|
unless project.deploy_envs
project.deploy_envs = []
evaluator.with_deploy_env_identifiers.each do |env_id|
project.deploy_envs << build(:deploy_env_ec2, identifier: env_id)
end
end
end
end
end

View File

@ -13,8 +13,6 @@ FactoryGirl.define do
updated_at Time.now
status 'completed'
initialize_with {
new(attributes.stringify_keys)
}
initialize_with { new(attributes.stringify_keys) }
end
end

View File

@ -1,19 +1,9 @@
require 'db/mongo/models/deploy_env/deploy_env_ec2'
require_relative '../shared_models_context'
RSpec.describe Devops::Model::DeployEnvEc2, type: :model do
let(:env) { build(:deploy_env_ec2) }
before do
allow(Provider::ProviderFactory).to receive(:providers).and_return(%w(ec2))
allow_any_instance_of(Validators::Helpers::Users).to receive(:available_users).and_return(['root'])
allow_any_instance_of(Validators::DeployEnv::Flavor).to receive(:available_flavors).and_return([{'id' => 'flavor'}])
allow_any_instance_of(Validators::FieldValidator::Flavor).to receive(:available_flavors).and_return([{'id' => 'flavor'}])
allow_any_instance_of(Validators::DeployEnv::Groups).to receive(:available_groups).and_return(['default'])
allow_any_instance_of(Validators::DeployEnv::Image).to receive(:available_images).and_return([{'id' => 'image'}])
allow_any_instance_of(Validators::DeployEnv::Image).to receive(:available_images).and_return([{'id' => 'image'}])
allow_any_instance_of(Validators::DeployEnv::StackTemplate).to receive(:available_stack_templates).and_return([{'id' => 'template'}])
allow_any_instance_of(Validators::FieldValidator::Image).to receive(:available_images).and_return([{'id' => 'image'}])
end
include_context 'stubbed calls to connector in env validators'
it_behaves_like 'deploy env'
it_behaves_like 'cloud deploy env'

View File

@ -1,19 +1,9 @@
require 'db/mongo/models/deploy_env/deploy_env_openstack'
require_relative '../shared_models_context'
RSpec.describe Devops::Model::DeployEnvOpenstack, type: :model do
let(:env) { build(:deploy_env_openstack) }
before do
allow(Provider::ProviderFactory).to receive(:providers).and_return(%w(openstack))
allow_any_instance_of(Validators::Helpers::Users).to receive(:available_users).and_return(['root'])
allow_any_instance_of(Validators::DeployEnv::Flavor).to receive(:available_flavors).and_return([{'id' => 'flavor'}])
allow_any_instance_of(Validators::FieldValidator::Flavor).to receive(:available_flavors).and_return([{'id' => 'flavor'}])
allow_any_instance_of(Validators::DeployEnv::Groups).to receive(:available_groups).and_return(['default'])
allow_any_instance_of(Validators::DeployEnv::Image).to receive(:available_images).and_return([{'id' => 'image'}])
allow_any_instance_of(Validators::DeployEnv::Image).to receive(:available_images).and_return([{'id' => 'image'}])
allow_any_instance_of(Validators::DeployEnv::StackTemplate).to receive(:available_stack_templates).and_return([{'id' => 'template'}])
allow_any_instance_of(Validators::FieldValidator::Image).to receive(:available_images).and_return([{'id' => 'image'}])
end
include_context 'stubbed calls to connector in env validators'
it_behaves_like 'deploy env'
it_behaves_like 'cloud deploy env'

View File

@ -0,0 +1,274 @@
require 'db/mongo/models/project'
require_relative 'shared_models_context'
RSpec.describe Devops::Model::Project, type: :model do
let(:project) { build(:project) }
include_context 'stubbed calls to connector in env validators'
describe 'validation rules:' do
include_examples 'field type validation', :id, :not_nil, :non_empty_string
include_examples 'field type validation', :deploy_envs, :not_nil, :non_empty_array
include_examples 'field type validation', :description, :maybe_nil, :maybe_empty_string
include_examples 'field type validation', :run_list, :not_nil, :maybe_empty_array, :run_list
it "isn't valid when has envs with same identifier" do
project = build(:project, with_deploy_env_identifiers: %w(foo foo))
expect(project).not_to be_valid
end
it "is valid when all envs have uniq identifiers" do
project = build(:project, with_deploy_env_identifiers: %w(foo bar))
expect(project).to be_valid
end
it "isn't valid when at least one of envs isn't valid" do
project = build(:project, with_deploy_env_identifiers: ['foo', nil])
expect(project).not_to be_valid
end
end
describe '.fields' do
subject { described_class.fields }
it { should eq %w(deploy_envs type description) }
end
describe '#initialize' do
it 'sets @type to generic by default' do
expect(described_class.new.type).to eq 'generic'
end
it 'sets @archived to false by default' do
expect(described_class.new.archived).to eq false
end
it 'sets run_list to empty_array by default' do
expect(described_class.new.run_list).to eq []
end
describe 'deploy envs building' do
let(:params) { {'deploy_envs' => [ {'provider' => @env_provider, 'identifier' => 'foo'} ]} }
it 'builds envs array from given params' do
@env_provider = 'ec2'
expect(
described_class.new(params).deploy_envs
).to be_an_array_of(Devops::Model::DeployEnvEc2).and have_size(1)
end
it 'builds ec2 deploy envs from given params' do
@env_provider = 'ec2'
builded_env = described_class.new(params).deploy_envs.first
expect(builded_env).to be_a(Devops::Model::DeployEnvEc2)
expect(builded_env.identifier).to eq 'foo'
end
it 'build openstack deploy envs from given params' do
@env_provider = 'openstack'
builded_env = described_class.new(params).deploy_envs.first
expect(builded_env).to be_a(Devops::Model::DeployEnvOpenstack)
end
it 'build static deploy envs from given params' do
@env_provider = 'static'
builded_env = described_class.new(params).deploy_envs.first
expect(builded_env).to be_a(Devops::Model::DeployEnvStatic)
end
end
end
describe '#deploy_env' do
let(:project) { project = build(:project, with_deploy_env_identifiers: %w(foo bar)) }
it 'returns found env' do
expect(project.deploy_env('bar')).to be_an(Devops::Model::DeployEnvEc2)
end
it 'raises RecordNotFound if there is no such env' do
expect {
project.deploy_env('missing')
}.to raise_error RecordNotFound
end
end
describe '#add_deploy_env', stub_logger: true do
let(:env) {build(:deploy_env_ec2)}
subject { project.add_deploy_env(env) }
before do
allow(Devops::Db).to receive_message_chain('connector.add_deploy_env_to_project')
end
it 'inserts deploy env into mongo via connector' do
expect(
Devops::Db
).to receive_message_chain('connector.add_deploy_env_to_project').with(project.id, env)
subject
end
it 'creates chef role' do
expect(env).to receive(:create_role).with(project.id)
subject
end
it 'returns string' do
expect(subject).to be_a(String)
end
end
describe '#add_authorized_user' do
before do
allow(Devops::Db).to receive_message_chain('connector.set_project_deploy_env_field')
end
let(:env1) { build(:deploy_env_ec2, identifier: 'foo') }
let(:env2) { build(:deploy_env_ec2, identifier: 'bar') }
let(:project) { build(:project, deploy_envs: [env1, env2]) }
it 'returns nil if user is nil' do
expect(project.add_authorized_user(nil)).to be_nil
end
context "when env isn't given" do
context 'when user is a String' do
it 'adds given user to all envs' do
project.add_authorized_user('John')
expect(env1.users).to match_array(%w(root John))
expect(env2.users).to match_array(%w(root John))
end
end
context 'when user is an Array of strings' do
it 'adds given users to all envs' do
project.add_authorized_user(['John', 'Matz'])
expect(env1.users).to match_array(%w(root John Matz))
expect(env2.users).to match_array(%w(root John Matz))
end
end
end
context 'when env is given' do
context 'when user is a String' do
it 'adds given user to given env' do
project.add_authorized_user('John', 'bar')
expect(env1.users).to match_array(%w(root))
expect(env2.users).to match_array(%w(root John))
end
end
context 'when user is an Array of strings' do
it 'adds given users to all envs' do
project.add_authorized_user(['John', 'Matz'], 'bar')
expect(env1.users).to match_array(%w(root))
expect(env2.users).to match_array(%w(root John Matz))
end
end
end
end
describe '#remove_authorized_user' do
before do
allow(Devops::Db).to receive_message_chain('connector.set_project_deploy_env_field')
end
let(:env1) { build(:deploy_env_ec2, identifier: 'foo', users: %w(root John Matz)) }
let(:env2) { build(:deploy_env_ec2, identifier: 'bar', users: %w(root John Matz)) }
let(:project) { build(:project, deploy_envs: [env1, env2]) }
it 'returns nil if user is nil' do
expect(project.remove_authorized_user(nil)).to be_nil
end
context "when env isn't given" do
context 'when user is a String' do
it 'adds given user to all envs' do
project.remove_authorized_user('John')
expect(env1.users).to match_array(%w(root Matz))
expect(env2.users).to match_array(%w(root Matz))
end
end
context 'when user is an Array of strings' do
it 'adds given users to all envs' do
project.remove_authorized_user(['John', 'Matz'])
expect(env1.users).to match_array(%w(root))
expect(env2.users).to match_array(%w(root))
end
end
end
context 'when env is given' do
context 'when user is a String' do
it 'adds given user to given env' do
project.remove_authorized_user('John', 'bar')
expect(env1.users).to match_array(%w(root John Matz))
expect(env2.users).to match_array(%w(root Matz))
end
end
context 'when user is an Array of strings' do
it 'adds given users to all envs' do
project.remove_authorized_user(['John', 'Matz'], 'bar')
expect(env1.users).to match_array(%w(root John Matz))
expect(env2.users).to match_array(%w(root))
end
end
end
end
describe '#check_authorization' do
subject { project.check_authorization(@user || 'Matz', 'foo') }
it 'returns true for root user' do
@user = 'root'
expect(subject).to be true
end
it "returns false if env's users don't include given user" do
expect(subject).to be false
end
it "returns true if env's users include given user" do
project.deploy_env('foo').users = %w(root Matz)
expect(subject).to be true
end
it 'returns false if there is no such env' do
expect(project.check_authorization('root', 'wrong')).to be false
end
end
describe '#delete_deploy_env' do
it 'removes env' do
allow(Devops::Db).to receive_message_chain('connector.remove_deploy_env_from_project')
expect(Devops::Db).to receive_message_chain('connector.remove_deploy_env_from_project').with(project.id, 'foo')
project.delete_deploy_env('foo')
expect(project.deploy_envs).to match_array []
end
end
describe '#to_hash' do
subject { project.to_hash }
it 'returns hash' do
expect(subject).to be_a(Hash)
end
it 'contains project id under name key' do
expect(subject['name']).to eq project.id
end
it 'contains deploy_envs converted to hashes' do
expect(subject['deploy_envs']).to be_an_array_of(Hash)
end
it 'also contains descriptions and run_list' do
expect(subject).to include('description', 'run_list')
end
it 'contains archived key if project is archived' do
project.archived = true
expect(subject).to include('archived')
end
it "doesn't contain archived if project isn't archived" do
expect(subject).not_to include('archived')
end
end
end

View File

@ -24,8 +24,7 @@ RSpec.describe Devops::Model::Server, type: :model do
include_examples 'field type validation', :chef_node_name, :not_nil, :maybe_empty_string
include_examples 'field type validation', :reserved_by, :not_nil, :maybe_empty_string
include_examples 'field type validation', :stack, :maybe_nil, :non_empty_string
include_examples 'field type validation', :run_list, :not_nil, :maybe_empty_array
include_examples 'field type validation', :run_list, :run_list
include_examples 'field type validation', :run_list, :not_nil, :maybe_empty_array, :run_list
end
describe '#initialize' do

View File

@ -0,0 +1,21 @@
RSpec.shared_context 'stubbed calls to connector in env validators' do
before do
allow(Provider::ProviderFactory).to receive(:providers).and_return(%w(ec2 openstack))
allow_any_instance_of(Validators::Helpers::Users).to receive(:available_users).and_return(['root'])
allow_any_instance_of(Validators::DeployEnv::Flavor).to receive(:available_flavors).and_return([{'id' => 'flavor'}])
allow_any_instance_of(Validators::FieldValidator::Flavor).to receive(:available_flavors).and_return([{'id' => 'flavor'}])
allow_any_instance_of(Validators::DeployEnv::Groups).to receive(:available_groups).and_return(['default'])
allow_any_instance_of(Validators::DeployEnv::Image).to receive(:available_images).and_return([{'id' => 'image'}])
allow_any_instance_of(Validators::DeployEnv::Image).to receive(:available_images).and_return([{'id' => 'image'}])
allow_any_instance_of(Validators::DeployEnv::StackTemplate).to receive(:available_stack_templates).and_return([{'id' => 'template'}])
allow_any_instance_of(Validators::FieldValidator::Image).to receive(:available_images).and_return([{'id' => 'image'}])
end
end
RSpec.shared_context 'stubbed calls to logger', stub_logger: true do
before do
allow(DevopsLogger).to receive_message_chain('logger.debug')
allow(DevopsLogger).to receive_message_chain('logger.info')
allow(DevopsLogger).to receive_message_chain('logger.error')
end
end

View File

@ -8,6 +8,10 @@ require 'active_support/inflector'
root = File.join(File.dirname(__FILE__), "..")
$LOAD_PATH.push root unless $LOAD_PATH.include? root
# suppress output
original_stdout = $stdout
$stdout = File.open(File::NULL, "w")
Dir[("./spec/support/**/*.rb")].each { |f| require f }
# Factory girl configuration
@ -21,6 +25,10 @@ FactoryGirl.find_definitions
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.after(:all) do
$stdout = original_stdout
end
# rspec-expectations config goes here. You can use an alternate
# assertion/expectation library such as wrong or the stdlib/minitest
# assertions if you prefer.

View File

@ -0,0 +1,13 @@
RSpec::Matchers.define :be_an_array_of do |klass|
match do |actual|
actual.class == Array &&
actual.all? {|item| item.class == klass}
end
end
RSpec::Matchers.define :have_size do |length|
match { |actual| actual.length == length }
failure_message do |actual|
"expected #{actual} to have size #{expected} but have #{actual.length}"
end
end

View File

@ -0,0 +1,7 @@
# only :db key is required
mongo:
:db: devops_test
:host:
:port:
:user:
:password:

View File

@ -0,0 +1,127 @@
RSpec.shared_examples 'mongo connector' do |options|
model_name = options.fetch(:model_name)
factory_name = options[:factory_name] || model_name
commands = options.fetch(:only)
if commands.include?(:insert)
insert_method_name = "#{model_name}_insert"
describe "##{insert_method_name}" do
let(:model) { build(factory_name) }
subject { @connector.send(insert_method_name, model) }
before { allow(model).to receive(:validate!).and_return(true) }
after { @tester_connector.cleanup }
it 'inserts new record' do
expect {subject}.to change {@tester_connector.list.size}.from(0).to(1)
end
it 'validates inserted record' do
expect(model).to receive(:validate!)
subject
end
it "doesn't insert nonvalid records" do
allow(model).to receive(:validate!) { raise InvalidRecord.new('') }
expect {subject}.to raise_error(InvalidRecord)
end
it 'sets created_at of record' do
expect(model.created_at).to be nil
subject
expect(@tester_connector.list.first['created_at']).not_to be nil
end
it 'raises error if record with such id already exists' do
@tester_connector.create(id: model.id)
expect {subject}.to raise_error(InvalidRecord)
end
end
end
if commands.include?(:list)
list_method_name = "#{model_name.to_s.pluralize}"
describe "##{list_method_name}" do
subject { @connector.send(list_method_name) }
it 'should be empty if collection is empty' do
expect(subject).to eq []
end
it "returns array of #{model_name.to_s.pluralize} if collection isn't empty" do
@tester_connector.create_list(2) do
expect(subject).to be_an_array_of(model_class).and have_size(2)
end
end
end
end
if commands.include?(:show)
show_method_name = model_name
describe "##{show_method_name}" do
subject { @connector.send(show_method_name, 'foo') }
it 'raises RecordNotFound when there is no such record' do
expect { subject }.to raise_error(RecordNotFound)
end
it 'returns record if was found' do
@tester_connector.create(build(factory_name, id: 'foo').to_mongo_hash) do
expect(subject).to be_an_instance_of(model_class)
end
end
end
end
if commands.include?(:update)
update_method_name = "#{model_name}_update"
field_to_update = options.fetch(:field_to_update).to_s
describe "##{update_method_name}" do
let(:model) { build(model_name, field_to_update => 'new_value') }
let(:insert_model_to_update) { @tester_connector.create(attributes_for(factory_name)) }
subject { @connector.send(update_method_name, model) }
before { allow(model).to receive(:validate!).and_return(true) }
after { @tester_connector.cleanup }
it 'validates updated record' do
insert_model_to_update
expect(model).to receive(:validate!)
subject
end
it 'updates record' do
insert_model_to_update
subject
updated_value = @tester_connector.list.first[field_to_update]
expect(updated_value).to eq 'new_value'
end
it 'raises RecordNotFound if there is no such record' do
expect{ subject }.to raise_error(RecordNotFound)
end
end
end
if commands.include?(:delete)
delete_method_name = "#{model_name}_delete"
describe "##{delete_method_name}" do
let(:model) { build(factory_name) }
let(:insert_model_to_delete) { @tester_connector.create(model.to_mongo_hash) }
subject { @connector.send(delete_method_name, model.id) }
it 'deletes record' do
insert_model_to_delete
expect {subject}.to change {@tester_connector.list.empty?}.to(true)
@tester_connector.cleanup
end
it 'raises RecordNotFound if there is no such record' do
expect { subject }.to raise_error(RecordNotFound)
end
end
end
end

View File

@ -103,10 +103,9 @@ RSpec.shared_examples 'deploy env' do
end
end
describe '#create_role' do
describe '#create_role', stub_logger: true do
subject { env.create_role('project_name') }
before do
stub_loggers
allow(env).to receive_message_chain('knife_instance.role_name') { 'role_name' }
end
@ -153,7 +152,7 @@ RSpec.shared_examples 'deploy env' do
end
end
describe '#rename' do
describe '#rename', stub_logger: true do
subject { env.rename('project_id', 'new_name') }
let(:old_role_name) {'project_id_name'}
let(:new_role_name) {'project_id_new_name'}
@ -161,7 +160,6 @@ RSpec.shared_examples 'deploy env' do
let(:suggested_new_roles) {["role[#{new_role_name}]"]}
before do
stub_loggers
# simulate correct start conditions
env.run_list = suggested_old_roles

View File

@ -9,7 +9,9 @@ RSpec.shared_examples 'field type validation' do |field, *properties|
describe field do
it 'should not be nil' do
expect(build(validated_model_name, field => nil)).not_to be_valid
model = build(validated_model_name)
model.send("#{field}=", nil)
expect(model).not_to be_valid
end if properties.include?(:not_nil)
it 'may be nil' do
@ -37,7 +39,8 @@ RSpec.shared_examples 'field type validation' do |field, *properties|
end if properties.include?(:maybe_empty_array)
it 'should contain only word symbols' do
expect(build(validated_model_name, field => 'asd-asd')).not_to be_valid
expect(build(validated_model_name, field => '!')).not_to be_valid
expect(build(validated_model_name, field => '/')).not_to be_valid
end if properties.include?(:only_word_symbols)
it 'should contain elements like role[asd] or recipe[asd]' do
@ -99,9 +102,12 @@ RSpec.shared_examples 'field type validation' do |field, *properties|
}.not_to raise_error
end if properties.include?(:maybe_empty_array)
it 'should contain only word symbols' do
it 'should contain only symbols in [a-zA-Z0-9_-]' do
expect{
build(validated_model_name, field => 'asd-asd').send(field_validation_method)
build(validated_model_name, field => '!').send(field_validation_method)
}.to raise_error InvalidRecord
expect{
build(validated_model_name, field => '/').send(field_validation_method)
}.to raise_error InvalidRecord
end if properties.include?(:only_word_symbols)

View File

@ -1,11 +1,35 @@
require 'core/devops-application'
require 'yaml'
module SpecSupport
BLANK_FILE = File.join(Devops::Application.root, 'spec/support/blank_file')
ROOT = File.join(__dir__, '../../')
BLANK_FILE = File.join(ROOT, 'spec/support/blank_file')
def stub_loggers
allow(DevopsLogger).to receive_message_chain('logger.debug')
allow(DevopsLogger).to receive_message_chain('logger.info')
allow(DevopsLogger).to receive_message_chain('logger.error')
def self.db_params
@db ||= begin
conf = config['mongo']
db_name = conf.fetch(:db)
[db_name, conf[:host], conf[:port], conf[:user], conf[:password]]
end
end
def self.db
unless @db
require 'mongo'
db_name, host, port, user, password = db_params
@db = MongoClient.new(host, port).db(db_name)
@db.authenticate(user, password) unless user.nil? or password.nil?
end
@db
end
def self.config
@config ||= begin
config_file = ENV['RSPEC_CONFIG_PATH'] || File.join(ROOT, 'spec/support/config.yml')
if File.exists?(config_file)
YAML.load_file(config_file)
else
raise "There is no config file: '#{config_file}'"
end
end
end
end