diff --git a/lib/vmfloaty.rb b/lib/vmfloaty.rb index 237632b..3c6bbec 100644 --- a/lib/vmfloaty.rb +++ b/lib/vmfloaty.rb @@ -484,7 +484,7 @@ def run # rubocop:disable Metrics/AbcSize FloatyLogger.info "Can't ssh to multiple hosts; Using #{host_os} only..." if args.length > 1 - service.ssh(verbose, host_os, use_token) + service.ssh(verbose, host_os, use_token, options.ondemand) exit 0 end end diff --git a/lib/vmfloaty/service.rb b/lib/vmfloaty/service.rb index 05904a1..a9e59ba 100644 --- a/lib/vmfloaty/service.rb +++ b/lib/vmfloaty/service.rb @@ -87,7 +87,7 @@ def wait_for_request(verbose, requestid) @service_object.wait_for_request verbose, requestid, url end - def ssh(verbose, host_os, use_token = true) + def ssh(verbose, host_os, use_token = true, ondemand = nil) token_value = nil if use_token begin @@ -97,7 +97,7 @@ def ssh(verbose, host_os, use_token = true) FloatyLogger.info 'Could not get token... requesting vm without a token anyway...' end end - Ssh.ssh(verbose, self, host_os, token_value) + Ssh.ssh(verbose, self, host_os, token_value, ondemand) end def query(verbose, hostname) diff --git a/lib/vmfloaty/ssh.rb b/lib/vmfloaty/ssh.rb index f100b8b..582adea 100644 --- a/lib/vmfloaty/ssh.rb +++ b/lib/vmfloaty/ssh.rb @@ -14,27 +14,45 @@ def self.which(cmd) nil end - def self.command_string(verbose, service, host_os, use_token) + def self.command_string(verbose, service, host_os, use_token, ondemand = nil) ssh_path = which('ssh') raise 'Could not determine path to ssh' unless ssh_path - - os_types = {} + os_types = Utils.generate_os_hash([host_os]) os_types[host_os] = 1 - response = service.retrieve(verbose, os_types, use_token) + response = service.retrieve(verbose, os_types, use_token, ondemand) raise "Could not get vm from #{service.type}:\n #{response}" unless response['ok'] user = /win/.match?(host_os) ? 'Administrator' : 'root' - hostname = response[host_os]['hostname'] - hostname = response[host_os]['hostname'][0] if response[host_os]['hostname'].is_a?(Array) - hostname = "#{hostname}.#{response['domain']}" unless hostname.end_with?('puppetlabs.net') + if ondemand + requestid = response['request_id'] + service.wait_for_request(verbose, requestid) + hosts = service.check_ondemandvm(verbose, requestid, service.url) + if hosts['domain'].nil? + hostname = hosts[host_os]['hostname'] + hostname = hosts[host_os]['hostname'][0] if hosts[host_os]['hostname'].is_a?(Array) + else + # Provides backwards compatibility with VMPooler API v1 + hostname = "#{hosts[host_os]['hostname']}.#{hosts['domain']}" + hostname = "#{hosts[host_os]['hostname'][0]}.#{hosts['domain']}" if hosts[host_os]['hostname'].is_a?(Array) + end + else + if response['domain'].nil? + hostname = response[host_os]['hostname'] + hostname = response[host_os]['hostname'][0] if response[host_os]['hostname'].is_a?(Array) + else + # Provides backwards compatibility with VMPooler API v1 + hostname = "#{response[host_os]['hostname']}.#{response['domain']}" + hostname = "#{response[host_os]['hostname'][0]}.#{response['domain']}" if response[host_os]['hostname'].is_a?(Array) + end + end "#{ssh_path} #{user}@#{hostname}" end - def self.ssh(verbose, service, host_os, use_token) - cmd = command_string(verbose, service, host_os, use_token) + def self.ssh(verbose, service, host_os, use_token, ondemand) + cmd = command_string(verbose, service, host_os, use_token, ondemand) # TODO: Should this respect more ssh settings? Can it be configured # by users ssh config and does this respect those settings? Kernel.exec(cmd) diff --git a/lib/vmfloaty/utils.rb b/lib/vmfloaty/utils.rb index 8470921..39c97a3 100644 --- a/lib/vmfloaty/utils.rb +++ b/lib/vmfloaty/utils.rb @@ -9,7 +9,7 @@ class Utils # TODO: Takes the json response body from an HTTP GET # request and "pretty prints" it def self.standardize_hostnames(response_body) - # vmpooler response body example when `floaty get` arguments are `ubuntu-1610-x86_64=2 centos-7-x86_64`: + # vmpooler api v1 response body example when `floaty get` arguments are `ubuntu-1610-x86_64=2 centos-7-x86_64`: # { # "ok": true, # "domain": "delivery.mycompany.net", @@ -21,6 +21,17 @@ def self.standardize_hostnames(response_body) # } # } + # vmpooler api v2 response body example when `floaty get` arguments are `ubuntu-1610-x86_64=2 centos-7-x86_64`: + # { + # "ok": true, + # "ubuntu-1610-x86_64": { + # "hostname": ["gdoy8q3nckuob0i.pooler.example.com", "ctnktsd0u11p9tm.pooler.example.com"] + # }, + # "centos-7-x86_64": { + # "hostname": "dlgietfmgeegry2.pooler.example.com" + # } + # } + # nonstandard pooler response body example when `floaty get` arguments are `solaris-11-sparc=2 ubuntu-16.04-power8`: # { # "ok": true, @@ -98,7 +109,11 @@ def self.print_fqdn_for_host(service, hostname, host_data) puts abs_hostnames.join("\n") when 'Pooler' - puts "#{hostname}.#{host_data['domain']}" + if host_data['domain'].nil? + puts hostname + else + puts "#{hostname}.#{host_data['domain']}" + end when 'NonstandardPooler' puts host_data['fqdn'] else diff --git a/spec/vmfloaty/ssh_spec.rb b/spec/vmfloaty/ssh_spec.rb index c16bb30..ec5fd4e 100644 --- a/spec/vmfloaty/ssh_spec.rb +++ b/spec/vmfloaty/ssh_spec.rb @@ -4,24 +4,35 @@ require 'vmfloaty/ssh' class ServiceStub - def retrieve(_verbose, os_types, _use_token) + def retrieve(_verbose, os_types, _use_token, ondemand) if os_types.keys[0] == 'abs_host_string' return { os_types.keys[0] => { 'hostname' => ['abs-hostname.delivery.puppetlabs.net'] }, 'ok' => true } - end - { - os_types.keys[0] => { 'hostname' => 'vmpooler-hostname' }, - 'domain' => 'delivery.puppetlabs.net', - 'ok' => true - } + elsif os_types.keys[0] == 'vmpooler_api_v2_host_string' + return { + os_types.keys[0] => { 'hostname' => ['vmpooler-v2-hostname.delivery.puppetlabs.net'] }, + 'ok' => true + } + + else + return { + os_types.keys[0] => { 'hostname' => 'vmpooler-v1-hostname' }, + 'domain' => 'delivery.puppetlabs.net', + 'ok' => true + } + end end def type return 'abs' if os_types == 'abs_host_string' - return 'vmpooler' if os_types == 'vmpooler_host_string' + return 'vmpooler' if os_types == 'vmpooler_api_v1_host_string' || os_types == 'vmpooler_api_v2_host_string' + end + + def wait_for_request(verbose, requestid) + return true end end @@ -29,21 +40,73 @@ def type before :each do end - it 'gets a hostname string for abs' do - verbose = false - service = ServiceStub.new - host_os = 'abs_host_string' - use_token = false - cmd = Ssh.command_string(verbose, service, host_os, use_token) - expect(cmd).to match(/ssh root@abs-hostname.delivery.puppetlabs.net/) + context "for pooled requests" do + it 'gets a hostname string for abs' do + verbose = false + service = ServiceStub.new + host_os = 'abs_host_string' + use_token = false + cmd = Ssh.command_string(verbose, service, host_os, use_token) + expect(cmd).to match(/ssh root@abs-hostname.delivery.puppetlabs.net/) + end + + it 'gets a hostname string for vmpooler api v1' do + verbose = true + service = ServiceStub.new + host_os = 'vmpooler_api_v1_host_string' + use_token = false + cmd = Ssh.command_string(verbose, service, host_os, use_token) + expect(cmd).to match(/ssh root@vmpooler-v1-hostname.delivery.puppetlabs.net/) + end + + it 'gets a hostname string for vmpooler api v2' do + verbose = false + service = ServiceStub.new + host_os = 'vmpooler_api_v2_host_string' + use_token = false + cmd = Ssh.command_string(verbose, service, host_os, use_token) + expect(cmd).to match(/ssh root@vmpooler-v2-hostname.delivery.puppetlabs.net/) + end end - it 'gets a hostname string for vmpooler' do - verbose = false - service = ServiceStub.new - host_os = 'vmpooler_host_string' - use_token = false - cmd = Ssh.command_string(verbose, service, host_os, use_token) - expect(cmd).to match(/ssh root@vmpooler-hostname.delivery.puppetlabs.net/) + context "for ondemand requests" do + let(:service) { ServiceStub.new } + let(:url) { 'http://pooler.example.com' } + + it 'gets a hostname string for abs' do + verbose = false + host_os = 'abs_host_string' + use_token = false + ondemand = true + response = {'abs_host_string' => { 'hostname' => ['abs-hostname.delivery.puppetlabs.net']}} + allow(service).to receive(:url) + allow(service).to receive(:check_ondemandvm).and_return(response) + cmd = Ssh.command_string(verbose, service, host_os, use_token, ondemand) + expect(cmd).to match(/ssh root@abs-hostname.delivery.puppetlabs.net/) + end + + it 'gets a hostname string for abs' do + verbose = false + host_os = 'vmpooler_api_v1_host_string' + use_token = false + ondemand = true + response = {'vmpooler_api_v1_host_string' => { 'hostname' => ['vmpooler_api_v1_host_string.delivery.puppetlabs.net']}} + allow(service).to receive(:url) + allow(service).to receive(:check_ondemandvm).and_return(response) + cmd = Ssh.command_string(verbose, service, host_os, use_token, ondemand) + expect(cmd).to match(/ssh root@vmpooler_api_v1_host_string.delivery.puppetlabs.net/) + end + + it 'gets a hostname string for abs' do + verbose = false + host_os = 'vmpooler_api_v2_host_string' + use_token = false + ondemand = true + response = {'vmpooler_api_v2_host_string' => { 'hostname' => ['vmpooler_api_v2_host_string.delivery.puppetlabs.net']}} + allow(service).to receive(:url) + allow(service).to receive(:check_ondemandvm).and_return(response) + cmd = Ssh.command_string(verbose, service, host_os, use_token, ondemand) + expect(cmd).to match(/ssh root@vmpooler_api_v2_host_string.delivery.puppetlabs.net/) + end end end diff --git a/spec/vmfloaty/utils_spec.rb b/spec/vmfloaty/utils_spec.rb index a567b0c..0994107 100644 --- a/spec/vmfloaty/utils_spec.rb +++ b/spec/vmfloaty/utils_spec.rb @@ -13,7 +13,7 @@ class Service describe Utils do describe '#standardize_hostnames' do before :each do - @vmpooler_response_body = '{ + @vmpooler_api_v1_response_body = '{ "ok": true, "domain": "delivery.mycompany.net", "ubuntu-1610-x86_64": { @@ -23,6 +23,15 @@ class Service "hostname": "dlgietfmgeegry2" } }' + @vmpooler_api_v2_response_body = '{ + "ok": true, + "ubuntu-1610-x86_64": { + "hostname": ["gdoy8q3nckuob0i.delivery.mycompany.net", "ctnktsd0u11p9tm.delivery.mycompany.net"] + }, + "centos-7-x86_64": { + "hostname": "dlgietfmgeegry2.delivery.mycompany.net" + } + }' @nonstandard_response_body = '{ "ok": true, "solaris-10-sparc": { @@ -34,8 +43,15 @@ class Service }' end - it 'formats a result from vmpooler into a hash of os to hostnames' do - result = Utils.standardize_hostnames(JSON.parse(@vmpooler_response_body)) + it 'formats a result from vmpooler v1 api into a hash of os to hostnames' do + result = Utils.standardize_hostnames(JSON.parse(@vmpooler_api_v1_response_body)) + expect(result).to eq('centos-7-x86_64' => ['dlgietfmgeegry2.delivery.mycompany.net'], + 'ubuntu-1610-x86_64' => ['gdoy8q3nckuob0i.delivery.mycompany.net', + 'ctnktsd0u11p9tm.delivery.mycompany.net']) + end + + it 'formats a result from vmpooler v2 api into a hash of os to hostnames' do + result = Utils.standardize_hostnames(JSON.parse(@vmpooler_api_v2_response_body)) expect(result).to eq('centos-7-x86_64' => ['dlgietfmgeegry2.delivery.mycompany.net'], 'ubuntu-1610-x86_64' => ['gdoy8q3nckuob0i.delivery.mycompany.net', 'ctnktsd0u11p9tm.delivery.mycompany.net'])