diff --git a/lib/vmpooler/api/v1.rb b/lib/vmpooler/api/v1.rb index c11b2cc..e0fe848 100644 --- a/lib/vmpooler/api/v1.rb +++ b/lib/vmpooler/api/v1.rb @@ -36,6 +36,23 @@ module Vmpooler Vmpooler::API.settings.config[:pool_names].include?(template) end + def provider_exists?(provider_name) + return false if Vmpooler::API.settings.config[:providers].nil? + return true if Vmpooler::API.settings.config[:providers]&.key?(provider_name) + Vmpooler::API.settings.config[:providers].each_key { |k| return true if Vmpooler::API.settings.config[:providers][k]['provider_class'] == provider_name } + false + end + + def provider_config(provider_name, pool_name) + return Vmpooler::API.settings.config[:providers][provider_name] if Vmpooler::API.settings.config[:providers][provider_name] + pools.each do |pool| + if pool['name'] == pool_name + return Vmpooler::API.settings.config[:providers][pool['provider']] if Vmpooler::API.settings.config[:providers][pool['provider']] + end + end + return nil + end + def need_auth! validate_auth(backend) end @@ -150,7 +167,13 @@ module Vmpooler next if vms.empty? vms.reverse.each do |vm| - ready = vm_ready?(vm, config['domain']) + # do one last check that the VM is reachable before handing it over. Unfortunately the provider context does + # not exist here, so it needs to infer the domain here + if provider_exists?('gce') + domain = provider_config('gce', template_backend)['dns_zone'] if provider_config('gce', template_backend) && provider_config('gce', template_backend)['dns_zone'] + end + + ready = vm_ready?(vm, domain || config['domain']) if ready smoved = backend.smove("vmpooler__ready__#{template_backend}", "vmpooler__running__#{template_backend}", vm) if smoved diff --git a/spec/integration/api/v1/vm_spec.rb b/spec/integration/api/v1/vm_spec.rb index 0d06585..2907b17 100644 --- a/spec/integration/api/v1/vm_spec.rb +++ b/spec/integration/api/v1/vm_spec.rb @@ -67,6 +67,54 @@ describe Vmpooler::API::V1 do end describe 'POST /vm' do + context 'has a gce provider config' do + it 'get the dsn_zone as domain when gce provider' do + create_ready_vm 'pool1', vmname, redis + # change running config + app.settings.set :config, providers: { 'gce' => { 'dns_zone' => 'example.com' } } + expect_any_instance_of(Vmpooler::API::Helpers).to receive(:open_socket).with(vmname, "example.com") + post "#{prefix}/vm", '{"pool1":"1"}' + end + + it 'get the dsn_zone as domain when foo provider has provider_class set to gce' do + create_ready_vm 'pool1', vmname, redis + # change running config + app.settings.set :config, providers: { 'foo' => { 'dns_zone' => 'example.com', 'provider_class' => 'gce' } } + app.settings.set :config, pools: [ {'name' => 'pool1', 'size' => 5, 'provider' => 'foo'} ] + expect_any_instance_of(Vmpooler::API::Helpers).to receive(:open_socket).with(vmname, "example.com") + post "#{prefix}/vm", '{"pool1":"1"}' + end + + it 'skips when dsn_zone is not available' do + create_ready_vm 'pool1', vmname, redis + # change running config + app.settings.set :config, providers: { 'foo' => { 'dns_zone' => 'example.com', 'provider_class' => 'gce' }, + 'bar' => { 'provider_class' => 'gce' } } + app.settings.set :config, pools: [ {'name' => 'pool1', 'size' => 5, 'provider' => 'bar'} ] + expect_any_instance_of(Vmpooler::API::Helpers).to receive(:open_socket).with(vmname, nil) + post "#{prefix}/vm", '{"pool1":"1"}' + end + + it 'skips when it is another provider that does not exist' do + create_ready_vm 'pool1', vmname, redis + # change running config + app.settings.set :config, providers: { 'foo' => { 'dns_zone' => 'example.com', 'provider_class' => 'gce' }, + 'bar' => { 'provider_class' => 'another' } } + app.settings.set :config, pools: [ {'name' => 'pool1', 'size' => 5, 'provider' => 'not_set'} ] + expect_any_instance_of(Vmpooler::API::Helpers).to receive(:open_socket).with(vmname, nil) + post "#{prefix}/vm", '{"pool1":"1"}' + end + + it 'skips when it is another provider' do + create_ready_vm 'pool1', vmname, redis + # change running config + app.settings.set :config, providers: { 'foo' => { 'dns_zone' => 'example.com', 'provider_class' => 'gce' }, + 'bar' => { 'provider_class' => 'another' } } + app.settings.set :config, pools: [ {'name' => 'pool1', 'size' => 5, 'provider' => 'bar'} ] + expect_any_instance_of(Vmpooler::API::Helpers).to receive(:open_socket).with(vmname, nil) + post "#{prefix}/vm", '{"pool1":"1"}' + end + end let(:socket) { double('socket') } it 'returns a single VM' do