mirror of
https://github.com/puppetlabs/vmpooler.git
synced 2026-01-26 10:08:40 -05:00
155 lines
5.3 KiB
Ruby
155 lines
5.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
require 'vmpooler/pool_manager/rate_provisioner'
|
|
|
|
describe Vmpooler::PoolManager::RateProvisioner do
|
|
let(:logger) { MockLogger.new }
|
|
let(:metrics) { Vmpooler::Metrics::DummyStatsd.new }
|
|
let(:redis_connection_pool) { ConnectionPool.new(size: 1) { MockRedis.new } }
|
|
let(:rate_provisioner) { described_class.new(redis_connection_pool, logger, metrics) }
|
|
|
|
describe '#enabled_for_pool?' do
|
|
it 'returns false when rate_provisioning is not configured' do
|
|
pool = { 'name' => 'test-pool', 'size' => 5 }
|
|
expect(rate_provisioner.enabled_for_pool?(pool)).to be(false)
|
|
end
|
|
|
|
it 'returns false when rate_provisioning enabled is false' do
|
|
pool = { 'name' => 'test-pool', 'size' => 5, 'rate_provisioning' => { 'enabled' => false } }
|
|
expect(rate_provisioner.enabled_for_pool?(pool)).to be(false)
|
|
end
|
|
|
|
it 'returns true when rate_provisioning enabled is true' do
|
|
pool = { 'name' => 'test-pool', 'size' => 5, 'rate_provisioning' => { 'enabled' => true } }
|
|
expect(rate_provisioner.enabled_for_pool?(pool)).to be(true)
|
|
end
|
|
end
|
|
|
|
describe '#get_ready_count' do
|
|
let(:pool_name) { 'test-pool' }
|
|
|
|
before do
|
|
redis_connection_pool.with do |redis|
|
|
redis.lpush("vmpooler__ready__#{pool_name}", 'vm1')
|
|
redis.lpush("vmpooler__ready__#{pool_name}", 'vm2')
|
|
redis.lpush("vmpooler__ready__#{pool_name}", 'vm3')
|
|
end
|
|
end
|
|
|
|
it 'returns correct ready count' do
|
|
count = rate_provisioner.get_ready_count(pool_name)
|
|
expect(count).to eq(3)
|
|
end
|
|
end
|
|
|
|
describe '#get_clone_concurrency' do
|
|
let(:pool_name) { 'test-pool' }
|
|
let(:pool) do
|
|
{
|
|
'name' => pool_name,
|
|
'rate_provisioning' => {
|
|
'enabled' => true,
|
|
'normal_concurrency' => 2,
|
|
'high_demand_concurrency' => 5,
|
|
'queue_depth_threshold' => 5
|
|
}
|
|
}
|
|
end
|
|
|
|
before do
|
|
redis_connection_pool.with(&:flushdb)
|
|
end
|
|
|
|
it 'returns normal concurrency when demand is low' do
|
|
redis_connection_pool.with do |redis|
|
|
# 3 ready VMs, 0 pending requests
|
|
(1..3).each { |i| redis.lpush("vmpooler__ready__#{pool_name}", "vm#{i}") }
|
|
end
|
|
|
|
allow(rate_provisioner).to receive(:get_pending_requests_count).and_return(0)
|
|
|
|
concurrency = rate_provisioner.get_clone_concurrency(pool, pool_name)
|
|
expect(concurrency).to eq(2)
|
|
end
|
|
|
|
it 'returns high demand concurrency when pending requests exceed threshold' do
|
|
redis_connection_pool.with do |redis|
|
|
# 2 ready VMs, 6 pending requests (exceeds threshold of 5)
|
|
(1..2).each { |i| redis.lpush("vmpooler__ready__#{pool_name}", "vm#{i}") }
|
|
end
|
|
|
|
allow(rate_provisioner).to receive(:get_pending_requests_count).and_return(6)
|
|
|
|
concurrency = rate_provisioner.get_clone_concurrency(pool, pool_name)
|
|
expect(concurrency).to eq(5)
|
|
end
|
|
|
|
it 'returns high demand concurrency when no ready VMs and requests pending' do
|
|
redis_connection_pool.with do |redis|
|
|
# 0 ready VMs, 2 pending requests
|
|
end
|
|
|
|
allow(rate_provisioner).to receive(:get_pending_requests_count).and_return(2)
|
|
|
|
concurrency = rate_provisioner.get_clone_concurrency(pool, pool_name)
|
|
expect(concurrency).to eq(5)
|
|
end
|
|
|
|
it 'returns default concurrency when rate provisioning is disabled' do
|
|
pool['rate_provisioning']['enabled'] = false
|
|
pool['clone_target_concurrency'] = 3
|
|
|
|
concurrency = rate_provisioner.get_clone_concurrency(pool, pool_name)
|
|
expect(concurrency).to eq(3)
|
|
end
|
|
|
|
it 'returns default 2 when no configuration exists' do
|
|
pool_without_config = { 'name' => pool_name }
|
|
|
|
concurrency = rate_provisioner.get_clone_concurrency(pool_without_config, pool_name)
|
|
expect(concurrency).to eq(2)
|
|
end
|
|
|
|
it 'logs mode changes' do
|
|
redis_connection_pool.with do |redis|
|
|
# Start in normal mode (3 ready VMs)
|
|
(1..3).each { |i| redis.lpush("vmpooler__ready__#{pool_name}", "vm#{i}") }
|
|
end
|
|
|
|
allow(rate_provisioner).to receive(:get_pending_requests_count).and_return(0)
|
|
|
|
# First call - normal mode
|
|
rate_provisioner.get_clone_concurrency(pool, pool_name)
|
|
|
|
# Change to high demand mode
|
|
redis_connection_pool.with do |redis|
|
|
redis.del("vmpooler__ready__#{pool_name}")
|
|
end
|
|
allow(rate_provisioner).to receive(:get_pending_requests_count).and_return(10)
|
|
|
|
# Second call - should log mode change
|
|
expect(logger).to receive(:log).with('s', /Provisioning mode: normal -> high_demand/)
|
|
rate_provisioner.get_clone_concurrency(pool, pool_name)
|
|
end
|
|
end
|
|
|
|
describe '#get_current_mode' do
|
|
it 'returns normal mode by default' do
|
|
expect(rate_provisioner.get_current_mode('test-pool')).to eq(:normal)
|
|
end
|
|
|
|
it 'returns current mode after it has been set' do
|
|
rate_provisioner.instance_variable_get(:@current_mode)['test-pool'] = :high_demand
|
|
expect(rate_provisioner.get_current_mode('test-pool')).to eq(:high_demand)
|
|
end
|
|
end
|
|
|
|
describe '#reset_to_normal' do
|
|
it 'resets mode to normal' do
|
|
rate_provisioner.instance_variable_get(:@current_mode)['test-pool'] = :high_demand
|
|
rate_provisioner.reset_to_normal('test-pool')
|
|
expect(rate_provisioner.get_current_mode('test-pool')).to eq(:normal)
|
|
end
|
|
end
|
|
end
|