From 667dacbcea90d956e73ad2181b271ab5761db34c Mon Sep 17 00:00:00 2001 From: Jake Spain Date: Mon, 4 Apr 2022 08:57:23 -0400 Subject: [PATCH] Add ondemand flag and api v2 support to `floaty ssh` --- lib/vmfloaty.rb | 2 +- lib/vmfloaty/service.rb | 4 +- lib/vmfloaty/ssh.rb | 36 +++++++++---- spec/vmfloaty/ssh_spec.rb | 107 ++++++++++++++++++++++++++++++-------- 4 files changed, 115 insertions(+), 34 deletions(-) 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 @@ class Vmfloaty 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 @@ class Service @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 @@ class Service 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 @@ class Ssh 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/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 'spec_helper' 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 @@ describe Ssh do 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