diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ac38a53..71bb52a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,10 +20,10 @@ jobs: draft: false prerelease: false generateReleaseNotes: true - - name: Install Ruby 2.5.8 + - name: Install Ruby jruby-9.3.6.0 uses: ruby/setup-ruby@v1 with: - ruby-version: '2.5.8' + ruby-version: 'jruby-9.3.6.0' - name: Build gem run: gem build *.gemspec - name: Publish gem diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 501403f..068495e 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: ruby-version: - - '2.5.8' + - 'jruby-9.3.6.0' steps: - uses: actions/checkout@v2 - name: Set up Ruby @@ -34,8 +34,7 @@ jobs: strategy: matrix: ruby-version: - - '2.5.8' - - 'jruby-9.2.12.0' + - 'jruby-9.3.6.0' steps: - uses: actions/checkout@v2 - name: Set up Ruby diff --git a/Gemfile.lock b/Gemfile.lock index 6811abd..eb102a8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - vmpooler-provider-vsphere (1.5.0) + vmpooler-provider-vsphere (1.6.0) rbvmomi (>= 2.1, < 4.0) GEM @@ -10,123 +10,108 @@ GEM ast (2.4.2) bindata (2.4.10) builder (3.2.4) - climate_control (1.0.1) + climate_control (1.2.0) coderay (1.1.3) - concurrent-ruby (1.1.9) + concurrent-ruby (1.1.10) connection_pool (2.2.5) - diff-lcs (1.4.4) + deep_merge (1.2.2) + diff-lcs (1.5.0) docile (1.4.0) - faraday (1.8.0) - faraday-em_http (~> 1.0) - faraday-em_synchrony (~> 1.0) - faraday-excon (~> 1.1) - faraday-httpclient (~> 1.0.1) - faraday-net_http (~> 1.0) - faraday-net_http_persistent (~> 1.1) - faraday-patron (~> 1.0) - faraday-rack (~> 1.0) - multipart-post (>= 1.2, < 3) + faraday (2.3.0) + faraday-net_http (~> 2.0) ruby2_keywords (>= 0.0.4) - faraday-em_http (1.0.0) - faraday-em_synchrony (1.0.0) - faraday-excon (1.1.0) - faraday-httpclient (1.0.1) - faraday-net_http (1.0.1) - faraday-net_http_persistent (1.2.0) - faraday-patron (1.0.0) - faraday-rack (1.0.0) - ffi (1.15.4-java) - google-cloud-env (1.5.0) - faraday (>= 0.17.3, < 2.0) - json (2.6.1) - json (2.6.1-java) + faraday-net_http (2.0.3) + ffi (1.15.5-java) + google-cloud-env (1.6.0) + faraday (>= 0.17.3, < 3.0) + json (2.6.2-java) method_source (1.0.0) - mock_redis (0.29.0) + mock_redis (0.32.0) ruby2_keywords - multipart-post (2.1.1) - mustermann (1.1.1) + mustermann (2.0.2) ruby2_keywords (~> 0.0.1) - net-ldap (0.17.0) - nio4r (2.5.8) + net-ldap (0.17.1) nio4r (2.5.8-java) - nokogiri (1.12.5-java) + nokogiri (1.13.8-java) racc (~> 1.4) - nokogiri (1.12.5-x86_64-linux) - racc (~> 1.4) - opentelemetry-api (0.17.0) - opentelemetry-common (0.17.0) - opentelemetry-api (~> 0.17.0) - opentelemetry-exporter-jaeger (0.17.0) - opentelemetry-api (~> 0.17.0) - opentelemetry-common (~> 0.17.0) - opentelemetry-sdk (~> 0.17.0) + opentelemetry-api (1.0.2) + opentelemetry-common (0.19.6) + opentelemetry-api (~> 1.0) + opentelemetry-exporter-jaeger (0.20.1) + opentelemetry-api (~> 1.0) + opentelemetry-common (~> 0.19.2) + opentelemetry-sdk (~> 1.0) thrift - opentelemetry-instrumentation-base (0.17.0) - opentelemetry-api (~> 0.17.0) - opentelemetry-instrumentation-concurrent_ruby (0.17.0) - opentelemetry-api (~> 0.17.0) - opentelemetry-instrumentation-base (~> 0.17.0) - opentelemetry-instrumentation-redis (0.17.0) - opentelemetry-api (~> 0.17.0) - opentelemetry-common (~> 0.17.0) - opentelemetry-instrumentation-base (~> 0.17.0) - opentelemetry-instrumentation-sinatra (0.17.0) - opentelemetry-api (~> 0.17.0) - opentelemetry-instrumentation-base (~> 0.17.0) - opentelemetry-resource_detectors (0.17.0) + opentelemetry-instrumentation-base (0.19.0) + opentelemetry-api (~> 1.0) + opentelemetry-instrumentation-concurrent_ruby (0.19.2) + opentelemetry-api (~> 1.0) + opentelemetry-instrumentation-base (~> 0.19.0) + opentelemetry-instrumentation-http_client (0.19.4) + opentelemetry-api (~> 1.0) + opentelemetry-common (~> 0.19.3) + opentelemetry-instrumentation-base (~> 0.19.0) + opentelemetry-instrumentation-redis (0.21.3) + opentelemetry-api (~> 1.0) + opentelemetry-common (~> 0.19.3) + opentelemetry-instrumentation-base (~> 0.19.0) + opentelemetry-instrumentation-sinatra (0.19.3) + opentelemetry-api (~> 1.0) + opentelemetry-common (~> 0.19.3) + opentelemetry-instrumentation-base (~> 0.19.0) + opentelemetry-registry (0.1.0) + opentelemetry-api (~> 1.0.1) + opentelemetry-resource_detectors (0.19.1) google-cloud-env opentelemetry-sdk - opentelemetry-sdk (0.17.0) - opentelemetry-api (~> 0.17.0) - opentelemetry-common (~> 0.17.0) - opentelemetry-instrumentation-base (~> 0.17.0) + opentelemetry-sdk (1.1.0) + opentelemetry-api (~> 1.0) + opentelemetry-common (~> 0.19.3) + opentelemetry-registry (~> 0.1) + opentelemetry-semantic_conventions + opentelemetry-semantic_conventions (1.8.0) + opentelemetry-api (~> 1.0) optimist (3.0.1) - parallel (1.21.0) - parser (3.0.3.2) + parallel (1.22.1) + parser (3.1.2.0) ast (~> 2.4.1) pickup (0.0.11) prometheus-client (2.1.0) - pry (0.14.1) - coderay (~> 1.1) - method_source (~> 1.0) pry (0.14.1-java) coderay (~> 1.1) method_source (~> 1.0) spoon (~> 0.0) - puma (5.5.2) + puma (5.6.4-java) nio4r (~> 2.0) - puma (5.5.2-java) - nio4r (~> 2.0) - racc (1.6.0) racc (1.6.0-java) - rack (2.2.3) - rack-protection (2.1.0) + rack (2.2.4) + rack-protection (2.2.2) rack - rack-test (1.1.0) - rack (>= 1.0, < 3) - rainbow (3.0.0) + rack-test (2.0.2) + rack (>= 1.3) + rainbow (3.1.1) rake (13.0.6) rbvmomi (3.0.0) builder (~> 3.2) json (~> 2.3) nokogiri (~> 1.10) optimist (~> 3.0) - redis (4.5.1) - regexp_parser (2.2.0) + redis (4.7.1) + regexp_parser (2.5.0) rexml (3.2.5) - rspec (3.10.0) - rspec-core (~> 3.10.0) - rspec-expectations (~> 3.10.0) - rspec-mocks (~> 3.10.0) - rspec-core (3.10.1) - rspec-support (~> 3.10.0) - rspec-expectations (3.10.1) + rspec (3.11.0) + rspec-core (~> 3.11.0) + rspec-expectations (~> 3.11.0) + rspec-mocks (~> 3.11.0) + rspec-core (3.11.0) + rspec-support (~> 3.11.0) + rspec-expectations (3.11.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-mocks (3.10.2) + rspec-support (~> 3.11.0) + rspec-mocks (3.11.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-support (3.10.3) + rspec-support (~> 3.11.0) + rspec-support (3.11.0) rubocop (1.1.0) parallel (~> 1.10) parser (>= 2.7.1.5) @@ -136,8 +121,8 @@ GEM rubocop-ast (>= 1.0.1) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (1.15.0) - parser (>= 3.0.1.1) + rubocop-ast (1.19.1) + parser (>= 3.1.1.0) ruby-progressbar (1.11.0) ruby2_keywords (0.0.5) simplecov (0.21.2) @@ -145,32 +130,33 @@ GEM simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) simplecov-html (0.12.3) - simplecov_json_formatter (0.1.3) - sinatra (2.1.0) - mustermann (~> 1.0) + simplecov_json_formatter (0.1.4) + sinatra (2.2.2) + mustermann (~> 2.0) rack (~> 2.2) - rack-protection (= 2.1.0) + rack-protection (= 2.2.2) tilt (~> 2.0) - spicy-proton (2.1.13) + spicy-proton (2.1.14) bindata (~> 2.3) spoon (0.0.6) ffi statsd-ruby (1.5.0) - thor (1.1.0) - thrift (0.15.0) - tilt (2.0.10) + thor (1.2.1) + thrift (0.16.0) + tilt (2.0.11) unicode-display_width (1.8.0) - vmpooler (2.1.0) + vmpooler (2.4.0) concurrent-ruby (~> 1.1) connection_pool (~> 2.2) + deep_merge (~> 1.2) net-ldap (~> 0.16) - nokogiri (~> 1.10) - opentelemetry-exporter-jaeger (= 0.17.0) - opentelemetry-instrumentation-concurrent_ruby (= 0.17.0) - opentelemetry-instrumentation-redis (= 0.17.0) - opentelemetry-instrumentation-sinatra (= 0.17.0) - opentelemetry-resource_detectors (= 0.17.0) - opentelemetry-sdk (= 0.17.0) + opentelemetry-exporter-jaeger (= 0.20.1) + opentelemetry-instrumentation-concurrent_ruby (= 0.19.2) + opentelemetry-instrumentation-http_client (= 0.19.4) + opentelemetry-instrumentation-redis (= 0.21.3) + opentelemetry-instrumentation-sinatra (= 0.19.3) + opentelemetry-resource_detectors (= 0.19.1) + opentelemetry-sdk (~> 1.0, >= 1.0.2) pickup (~> 0.0.11) prometheus-client (~> 2.0) puma (~> 5.0, >= 5.0.4) @@ -186,7 +172,6 @@ GEM PLATFORMS universal-java-11 - x86_64-linux DEPENDENCIES climate_control (>= 0.2.0) @@ -197,9 +182,9 @@ DEPENDENCIES rubocop (~> 1.1.0) simplecov (>= 0.11.2) thor (~> 1.0, >= 1.0.1) - vmpooler (~> 2.1) + vmpooler (~> 2.4) vmpooler-provider-vsphere! yarjuf (>= 2.0) BUNDLED WITH - 2.2.22 + 2.2.29 diff --git a/lib/vmpooler-provider-vsphere/version.rb b/lib/vmpooler-provider-vsphere/version.rb index ec8c193..e8ab665 100644 --- a/lib/vmpooler-provider-vsphere/version.rb +++ b/lib/vmpooler-provider-vsphere/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module VmpoolerProviderVsphere - VERSION = '1.5.0' + VERSION = '1.6.0' end diff --git a/spec/unit/pool_manager_spec.rb b/spec/unit/pool_manager_spec.rb index 4f551eb..0b14668 100644 --- a/spec/unit/pool_manager_spec.rb +++ b/spec/unit/pool_manager_spec.rb @@ -235,180 +235,6 @@ EOT end end - describe '#move_pending_vm_to_ready' do - let(:host) { { 'hostname' => vm }} - - before do - expect(subject).not_to be_nil - end - - before(:each) do - redis_connection_pool.with do |redis| - create_pending_vm(pool,vm,redis) - end - end - - context 'when hostname matches VM name' do - it 'should move the VM from pending to ready pool' do - redis_connection_pool.with do |redis| - expect(redis.sismember("vmpooler__pending__#{pool}", vm)).to be(true) - expect(redis.sismember("vmpooler__ready__#{pool}", vm)).to be(false) - subject.move_pending_vm_to_ready(vm, pool, redis) - expect(redis.sismember("vmpooler__pending__#{pool}", vm)).to be(false) - expect(redis.sismember("vmpooler__ready__#{pool}", vm)).to be(true) - end - end - - it 'should log a message' do - expect(logger).to receive(:log).with('s', "[>] [#{pool}] '#{vm}' moved from 'pending' to 'ready' queue") - - redis_connection_pool.with do |redis| - subject.move_pending_vm_to_ready(vm, pool, redis) - end - end - - it 'should receive time_to_ready_state metric' do - redis_connection_pool.with do |redis| - redis.hset("vmpooler__vm__#{vm}", 'clone',Time.now.to_s) - expect(metrics).to receive(:timing).with(/time_to_ready_state\./,/0/) - - subject.move_pending_vm_to_ready(vm, pool, redis) - end - end - - - it 'should set the boot time in redis' do - redis_connection_pool.with do |redis| - redis.hset("vmpooler__vm__#{vm}", 'clone',Time.now.to_s) - expect(redis.hget('vmpooler__boot__' + Date.today.to_s, pool + ':' + vm)).to be_nil - subject.move_pending_vm_to_ready(vm, pool, redis) - expect(redis.hget('vmpooler__boot__' + Date.today.to_s, pool + ':' + vm)).to_not be_nil - # TODO Should we inspect the value to see if it's valid? - end - end - - it 'should not determine boot timespan if clone start time not set' do - redis_connection_pool.with do |redis| - expect(redis.hget('vmpooler__boot__' + Date.today.to_s, pool + ':' + vm)).to be_nil - subject.move_pending_vm_to_ready(vm, pool, redis) - expect(redis.hget('vmpooler__boot__' + Date.today.to_s, pool + ':' + vm)).to match(/\d\.\d{2}/) - end - end - - it 'should raise error if clone start time is not parsable' do - redis_connection_pool.with do |redis| - redis.hset("vmpooler__vm__#{vm}", 'clone','iamnotparsable_asdate') - expect{subject.move_pending_vm_to_ready(vm, pool, redis)}.to raise_error(/iamnotparsable_asdate/) - end - end - - it 'should save the last boot time' do - redis_connection_pool.with do |redis| - expect(redis.hget('vmpooler__lastboot', pool)).to be(nil) - subject.move_pending_vm_to_ready(vm, pool, redis) - expect(redis.hget('vmpooler__lastboot', pool)).to_not be(nil) - end - end - end - - context 'with request_id' do - context 'with a pending request' do - before(:each) do - allow(subject).to receive(:check_ondemand_request_ready) - config[:config]['ondemand_request_ttl'] = 20 - end - - it 'sets the vm as active' do - redis_connection_pool.with do |redis| - expect(Time).to receive(:now).and_return(current_time).at_least(:once) - redis.hset("vmpooler__vm__#{vm}", 'pool_alias', pool) - subject.move_pending_vm_to_ready(vm, pool, redis, request_id) - expect(redis.hget("vmpooler__active__#{pool}", vm)).to eq(current_time.to_s) - expect(redis.hget("vmpooler__vm__#{vm}", 'checkout')).to eq(current_time.to_s) - expect(redis.sismember("vmpooler__#{request_id}__#{pool}__#{pool}", vm)).to be true - end - end - - it 'logs that the vm is ready for the request' do - redis_connection_pool.with do |redis| - redis.hset("vmpooler__vm__#{vm}", 'pool_alias', pool) - expect(logger).to receive(:log).with('s', "[>] [#{pool}] '#{vm}' is 'ready' for request '#{request_id}'") - - subject.move_pending_vm_to_ready(vm, pool, redis, request_id) - end - end - end - - context 'when the request has been marked as failed' do - before(:each) do - redis_connection_pool.with do |redis| - redis.hset("vmpooler__odrequest__#{request_id}", 'status', 'failed') - end - end - - it 'moves the vm to completed' do - redis_connection_pool.with do |redis| - expect(subject).to receive(:move_vm_queue).with(pool, vm, 'pending', 'completed', redis, "moved to completed queue. '#{request_id}' could not be filled in time") - subject.move_pending_vm_to_ready(vm, pool, redis, request_id) - end - end - - it 'returns nil' do - redis_connection_pool.with do |redis| - result = subject.move_pending_vm_to_ready(vm, pool, redis, request_id) - expect(result).to be nil - end - end - end - - context 'when the request has been marked as deleted' do - before(:each) do - redis_connection_pool.with do |redis| - redis.hset("vmpooler__odrequest__#{request_id}", 'status', 'deleted') - end - end - - it 'moves the vm to completed' do - redis_connection_pool.with do |redis| - expect(subject).to receive(:move_vm_queue).with(pool, vm, 'pending', 'completed', redis, "moved to completed queue. '#{request_id}' has been deleted") - subject.move_pending_vm_to_ready(vm, pool, redis, request_id) - end - end - - it 'returns nil' do - redis_connection_pool.with do |redis| - result = subject.move_pending_vm_to_ready(vm, pool, redis, request_id) - expect(result).to be nil - end - end - end - - context 'with auth on the request' do - let(:user) { 'vmpuser' } - let(:platform_alias) { pool } - let(:platforms_string) { "#{platform_alias}:#{pool}:1" } - let(:score) { current_time.to_i } - before(:each) do - config[:config]['ondemand_request_ttl'] = 20 - allow(subject).to receive(:check_ondemand_request_ready) - redis_connection_pool.with do |redis| - create_ondemand_request_for_test(request_id, score, platforms_string, redis, user, token) - end - end - - it 'should specify auth data on the vm' do - redis_connection_pool.with do |redis| - allow(redis).to receive(:hset) - expect(redis).to receive(:hset).with("vmpooler__vm__#{vm}", 'token:token', token) - expect(redis).to receive(:hset).with("vmpooler__vm__#{vm}", 'token:user', user) - - subject.move_pending_vm_to_ready(vm, pool, redis, request_id) - end - end - end - end - end - describe '#check_ready_vm' do let(:ttl) { 5 } let(:poolconfig) { config[:pools][0] } @@ -771,168 +597,6 @@ EOT end end - describe '#_clone_vm' do - let (:pool_object) { { 'name' => pool } } - let (:redis_ttl) { 1 } - - before do - expect(subject).not_to be_nil - end - - let(:config) { - YAML.load(<<-EOT ---- -:config: - prefix: "prefix" -:redis: - ttl: #{redis_ttl} -EOT - ) - } - - context 'with no errors during cloning' do - before(:each) do - allow(metrics).to receive(:timing) - expect(metrics).to receive(:timing).with(/clone\./,/0/) - expect(provider).to receive(:create_vm).with(pool, String) - allow(logger).to receive(:log) - redis_connection_pool.with do |redis| - expect(subject).to receive(:find_unique_hostname).with(pool).and_return(vm) - end - end - - it 'should create a cloning VM' do - redis_connection_pool.with do |redis| - expect(redis.scard("vmpooler__pending__#{pool}")).to eq(0) - - subject._clone_vm(pool,provider) - - expect(redis.scard("vmpooler__pending__#{pool}")).to eq(1) - expect(redis.hget("vmpooler__vm__#{vm}", 'clone')).to_not be_nil - expect(redis.hget("vmpooler__vm__#{vm}", 'template')).to eq(pool) - expect(redis.hget("vmpooler__clone__#{Date.today.to_s}", "#{pool}:#{vm}")).to_not be_nil - expect(redis.hget("vmpooler__vm__#{vm}", 'clone_time')).to_not be_nil - end - end - - it 'should decrement the clone tasks counter' do - redis_connection_pool.with do |redis| - redis.incr('vmpooler__tasks__clone') - redis.incr('vmpooler__tasks__clone') - expect(redis.get('vmpooler__tasks__clone')).to eq('2') - subject._clone_vm(pool,provider) - expect(redis.get('vmpooler__tasks__clone')).to eq('1') - end - end - - it 'should log a message that is being cloned from a template' do - expect(logger).to receive(:log).with('d',/\[ \] \[#{pool}\] Starting to clone '(.+)'/) - - subject._clone_vm(pool,provider) - end - - it 'should log a message that it completed being cloned' do - expect(logger).to receive(:log).with('s',/\[\+\] \[#{pool}\] '(.+)' cloned in [0-9.]+ seconds/) - - subject._clone_vm(pool,provider) - end - end - - context 'with an error during cloning' do - before(:each) do - expect(provider).to receive(:create_vm).with(pool, String).and_raise('MockError') - allow(logger).to receive(:log) - redis_connection_pool.with do |redis| - expect(subject).to receive(:find_unique_hostname).with(pool).and_return(vm) - end - end - - it 'should not create a cloning VM' do - redis_connection_pool.with do |redis| - expect(redis.scard("vmpooler__pending__#{pool}")).to eq(0) - - expect{subject._clone_vm(pool,provider)}.to raise_error(/MockError/) - - expect(redis.scard("vmpooler__pending__#{pool}")).to eq(0) - # Get the new VM Name from the pending pool queue as it should be the only entry - vm_name = redis.smembers("vmpooler__pending__#{pool}")[0] - expect(vm_name).to be_nil - end - end - - it 'should decrement the clone tasks counter' do - redis_connection_pool.with do |redis| - redis.incr('vmpooler__tasks__clone') - redis.incr('vmpooler__tasks__clone') - expect(redis.get('vmpooler__tasks__clone')).to eq('2') - expect{subject._clone_vm(pool,provider)}.to raise_error(/MockError/) - expect(redis.get('vmpooler__tasks__clone')).to eq('1') - end - end - - it 'should expire the vm metadata' do - redis_connection_pool.with do |redis| - expect(redis).to receive(:expire) - expect{subject._clone_vm(pool,provider)}.to raise_error(/MockError/) - end - end - - it 'should raise the error' do - expect{subject._clone_vm(pool,provider)}.to raise_error(/MockError/) - end - - end - - context 'with request_id' do - before(:each) do - allow(metrics).to receive(:timing) - expect(metrics).to receive(:timing).with(/clone\./,/0/) - expect(provider).to receive(:create_vm).with(pool, String) - allow(logger).to receive(:log) - redis_connection_pool.with do |redis| - expect(subject).to receive(:find_unique_hostname).with(pool).and_return(vm) - end - end - - it 'should set request_id and pool_alias on the vm data' do - redis_connection_pool.with do |redis| - subject._clone_vm(pool,provider,request_id,pool) - expect(redis.hget("vmpooler__vm__#{vm}", 'pool_alias')).to eq(pool) - expect(redis.hget("vmpooler__vm__#{vm}", 'request_id')).to eq(request_id) - end - end - - it 'should reduce the clone count' do - redis_connection_pool.with do |redis| - expect(redis).to receive(:decr).with('vmpooler__tasks__ondemandclone') - subject._clone_vm(pool,provider,request_id,pool) - end - end - end - - context 'with #check_dns_available' do - before(:each) do - allow(logger).to receive(:log) - end - it 'should error out if DNS already exists' do - vm_name = "foo" - resolv = class_double("Resolv").as_stubbed_const(:transfer_nested_constants => true) - expect(subject).to receive(:generate_and_check_hostname).exactly(3).times.and_return([vm_name, true]) #skip this, make it available all times - expect(resolv).to receive(:getaddress).exactly(3).times.and_return("1.2.3.4") - expect(metrics).to receive(:increment).with("errors.staledns.#{pool}").exactly(3).times - expect{subject._clone_vm(pool,provider)}.to raise_error(/Unable to generate a unique hostname after/) - end - it 'should be successful if DNS does not exist' do - vm_name = "foo" - resolv = class_double("Resolv").as_stubbed_const(:transfer_nested_constants => true) - expect(subject).to receive(:generate_and_check_hostname).and_return([vm_name, true]) - expect(resolv).to receive(:getaddress).exactly(1).times.and_raise(Resolv::ResolvError) - expect(provider).to receive(:create_vm).with(pool, String) - subject._clone_vm(pool,provider) - end - end - end - describe '#destroy_vm' do before do expect(subject).not_to be_nil @@ -954,112 +618,6 @@ EOT end end - describe "#_destroy_vm" do - before(:each) do - expect(subject).not_to be_nil - - redis_connection_pool.with do |redis| - create_completed_vm(vm,pool,redis,true) - end - - allow(provider).to receive(:destroy_vm).with(pool,vm).and_return(true) - - # Set redis configuration - config[:redis] = {} - config[:redis]['data_ttl'] = 168 - end - - context 'when redis data_ttl is not specified in the configuration' do - before(:each) do - config[:redis]['data_ttl'] = nil - end - - it 'should call redis expire with 0' do - redis_connection_pool.with do |redis| - expect(redis).to receive(:expire).with("vmpooler__vm__#{vm}", 0) - subject._destroy_vm(vm,pool,provider) - end - end - end - - context 'when there is no redis section in the configuration' do - before(:each) do - config[:redis] = nil - end - - it 'should raise an error' do - expect{ subject._destroy_vm(vm,pool,provider) }.to raise_error(NoMethodError) - end - end - - context 'when a VM does not exist' do - before(:each) do - # As per base_spec, destroy_vm will return true if the VM does not exist - expect(provider).to receive(:destroy_vm).with(pool,vm).and_return(true) - end - - it 'should not raise an error' do - subject._destroy_vm(vm,pool,provider) - end - end - - context 'when the VM is destroyed without error' do - it 'should log a message the VM was destroyed' do - expect(logger).to receive(:log).with('s', /\[-\] \[#{pool}\] '#{vm}' destroyed in [0-9.]+ seconds/) - allow(logger).to receive(:log) - - subject._destroy_vm(vm,pool,provider) - end - - it 'should emit a timing metric' do - allow(subject).to receive(:get_vm_usage_labels) - allow(metrics).to receive(:timing) - expect(metrics).to receive(:timing).with("destroy.#{pool}", String) - - subject._destroy_vm(vm,pool,provider) - end - - it 'should dereference the mutex' do - expect(subject).to receive(:dereference_mutex) - - subject._destroy_vm(vm,pool,provider) - end - end - - context 'when the VM destruction raises an eror' do - before(:each) do - # As per base_spec, destroy_vm will return true if the VM does not exist - expect(provider).to receive(:destroy_vm).with(pool,vm).and_raise('MockError') - end - - it 'should not log a message the VM was destroyed' do - expect(logger).to receive(:log).with('s', /\[-\] \[#{pool}\] '#{vm}' destroyed in [0-9.]+ seconds/).exactly(0).times - allow(logger).to receive(:log) - - expect{ subject._destroy_vm(vm,pool,provider) }.to raise_error(/MockError/) - end - - it 'should not emit a timing metric' do - expect(metrics).to receive(:timing).with("destroy.#{pool}", String).exactly(0).times - - expect{ subject._destroy_vm(vm,pool,provider) }.to raise_error(/MockError/) - end - end - - context 'when the VM mutex is locked' do - let(:mutex) { Mutex.new } - before(:each) do - mutex.lock - end - - it 'should return' do - expect(subject).to receive(:vm_mutex).with(vm).and_return(mutex) - - expect(subject._destroy_vm(vm,pool,provider)).to eq(nil) - end - end - end - describe '#purge_unused_vms_and_resources' do let(:config) { YAML.load(<<-EOT --- @@ -4537,120 +4095,6 @@ EOT end end - describe '#create_ondemand_vms' do - context 'when requested does not have corresponding data' do - it 'logs an error' do - redis_connection_pool.with do |redis| - expect(logger).to receive(:log).with('s', "Failed to find odrequest for request_id '1111'") - subject.create_ondemand_vms('1111', redis) - end - end - end - - context 'with a request that has data' do - let(:request_string) { "#{pool}:#{pool}:1" } - before(:each) do - expect(Time).to receive(:now).and_return(current_time).at_least(:once) - redis_connection_pool.with do |redis| - create_ondemand_request_for_test(request_id, current_time.to_i, request_string, redis) - end - end - - it 'creates tasks for instances to be provisioned' do - redis_connection_pool.with do |redis| - allow(redis).to receive(:zadd) - expect(redis).to receive(:zadd).with('vmpooler__odcreate__task', current_time.to_i, "#{request_string}:#{request_id}") - subject.create_ondemand_vms(request_id, redis) - end - end - - it 'adds a member to provisioning__processing' do - redis_connection_pool.with do |redis| - allow(redis).to receive(:zadd) - expect(redis).to receive(:zadd).with('vmpooler__provisioning__processing', current_time.to_i, request_id) - subject.create_ondemand_vms(request_id, redis) - end - end - end - end - - describe '#process_ondemand_vms' do - it 'returns the length of the queue' do - redis_connection_pool.with do |redis| - result = subject.process_ondemand_vms(redis) - expect(result).to eq(0) - end - end - - context 'with a request to create a single vm' do - let(:request_string) { "#{pool}:#{pool}:1" } - let(:pool_alias) { pool } - before(:each) do - config[:config]['ondemand_clone_limit'] = 10 - expect(subject).to receive(:get_provider_for_pool).and_return(provider) - redis_connection_pool.with do |redis| - create_ondemand_creationtask("#{request_string}:#{request_id}", current_time.to_i, redis) - end - end - - it 'creates the vm' do - redis_connection_pool.with do |redis| - expect(subject).to receive(:clone_vm).with(pool, provider, request_id, pool_alias) - subject.process_ondemand_vms(redis) - end - end - end - - context 'with a request to create more instances than the limit' do - let(:request_string) { "#{pool}:#{pool}:5" } - let(:request_string_remaining) { "#{pool}:#{pool}:2" } - let(:pool_alias) { pool } - before(:each) do - config[:config]['ondemand_clone_limit'] = 3 - expect(subject).to receive(:get_provider_for_pool).and_return(provider) - redis_connection_pool.with do |redis| - create_ondemand_creationtask("#{request_string}:#{request_id}", current_time.to_i, redis) - end - end - - it 'should create the maximum number of vms' do - redis_connection_pool.with do |redis| - expect(subject).to receive(:clone_vm).with(pool, provider, request_id, pool_alias).exactly(3).times - subject.process_ondemand_vms(redis) - end - end - - it 'should add the remaining number back as a new create task with the same score' do - redis_connection_pool.with do |redis| - expect(redis).to receive(:zadd).with('vmpooler__odcreate__task', current_time.to_i, "#{request_string_remaining}:#{request_id}") - subject.process_ondemand_vms(redis) - end - end - - it 'should return the number of requests processed' do - redis_connection_pool.with do |redis| - result = subject.process_ondemand_vms(redis) - expect(result).to eq(1) - end - end - end - - context 'when the limit has been reached' do - let(:clone_count) { { 'ondemand_clone_count' => 3 } } - before(:each) do - config[:config]['ondemand_clone_limit'] = 3 - subject.instance_variable_set(:@tasks, clone_count) - end - - it 'does not create any instances' do - redis_connection_pool.with do |redis| - expect(subject).to_not receive(:clone_vm) - subject.process_ondemand_vms(redis) - end - end - end - end - describe '#vms_ready?' do let(:request_string) { "#{pool}:#{pool}:5" } let(:platform_alias) { pool } @@ -4799,106 +4243,6 @@ EOT end end - describe '#request_expired?' do - let(:ondemand_request_ttl) { 5 } - let(:expiration_ttl) { 10 } - before(:each) do - config[:config]['ondemand_request_ttl'] = ondemand_request_ttl - config[:redis]['data_ttl'] = expiration_ttl - end - - context 'with a request that has taken too long to be filled' do - let(:expired_time) { (Time.now - 960).to_i } - before(:each) do - redis_connection_pool.with do |redis| - expect(subject).to receive(:remove_vms_for_failed_request) - create_ondemand_processing(request_id, expired_time, redis) - end - end - - it 'returns true when the request is expired' do - redis_connection_pool.with do |redis| - result = subject.request_expired?(request_id, expired_time, redis) - expect(result).to be true - end - end - - it 'logs a message that the request has expired' do - redis_connection_pool.with do |redis| - expect(logger).to receive(:log).with('s', "Ondemand request for '#{request_id}' failed to provision all instances within the configured ttl '#{ondemand_request_ttl}'") - subject.request_expired?(request_id, expired_time, redis) - end - end - - it 'removes the request from processing requests' do - redis_connection_pool.with do |redis| - expect(redis).to receive(:zrem).with('vmpooler__provisioning__processing', request_id) - subject.request_expired?(request_id, expired_time, redis) - end - end - - it 'sets the status as failed on the request hash' do - redis_connection_pool.with do |redis| - expect(redis).to receive(:hset).with("vmpooler__odrequest__#{request_id}", 'status', 'failed') - subject.request_expired?(request_id, expired_time, redis) - end - end - - it 'marks the request hash for expiration' do - redis_connection_pool.with do |redis| - expect(redis).to receive(:expire).with("vmpooler__odrequest__#{request_id}", expiration_ttl * 60 * 60) - subject.request_expired?(request_id, expired_time, redis) - end - end - end - - context 'with a request that has been made within the ttl' do - before(:each) do - redis_connection_pool.with do |redis| - create_ondemand_processing(request_id, current_time, redis) - end - end - - it 'should return false' do - redis_connection_pool.with do |redis| - result = subject.request_expired?(request_id, current_time, redis) - expect(result).to be false - end - end - end - end - - describe '#remove_vms_for_failed_request)' do - let(:expiration_ttl) { 100 * 60 * 60 } - let(:platform_alias) { pool } - let(:platforms_string) { "#{platform_alias}:#{pool}:3" } - context 'with two vms marked as ready for the request' do - before(:each) do - redis_connection_pool.with do |redis| - create_ondemand_request_for_test(request_id, current_time, platforms_string, redis) - [vm,"#{vm}2"].each do |v| - create_running_vm(pool, v, redis) - redis.sadd("vmpooler__#{request_id}__#{platform_alias}__#{pool}", v) - end - end - end - - it 'should remove the associated vms' do - redis_connection_pool.with do |redis| - expect(subject).to receive(:move_vm_queue).with(pool, String, 'running', 'completed', redis, "moved to completed queue. '#{request_id}' could not be filled in time").twice - subject.remove_vms_for_failed_request(request_id, expiration_ttl, redis) - end - end - - it 'should mark the ready set for expiration' do - redis_connection_pool.with do |redis| - expect(redis).to receive(:expire).with("vmpooler__#{request_id}__#{platform_alias}__#{pool}", expiration_ttl) - subject.remove_vms_for_failed_request(request_id, expiration_ttl, redis) - end - end - end - end - describe 'check_ondemand_requests' do let(:threads) {[]} let(:maxloop) { 0 } diff --git a/vmpooler-provider-vsphere.gemspec b/vmpooler-provider-vsphere.gemspec index 6c7febe..4c66499 100644 --- a/vmpooler-provider-vsphere.gemspec +++ b/vmpooler-provider-vsphere.gemspec @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.require_paths = ["lib"] s.add_dependency 'rbvmomi', '>= 2.1', '< 4.0' - s.add_development_dependency 'vmpooler', '~> 2.1' # renaming done in version 2.1 + s.add_development_dependency 'vmpooler', '~> 2.4' # renaming done in version 2.1 # Testing dependencies s.add_development_dependency 'climate_control', '>= 0.2.0'