Use Logger for non-result output

This adds the Logger class for log output, all of which goes to STDERR,
and uses puts to send only the command result to STDOUT.
This commit is contained in:
barriserloth 2020-08-11 10:31:14 -07:00 committed by Austin Blatt
parent 4755343df2
commit 8ec90007ca
7 changed files with 81 additions and 67 deletions

View file

@ -13,10 +13,15 @@ require 'vmfloaty/conf'
require 'vmfloaty/utils'
require 'vmfloaty/service'
require 'vmfloaty/ssh'
require 'vmfloaty/logger'
class Vmfloaty
include Commander::Methods
def self.logger
@logger ||= FloatyLogger.new
end
def run # rubocop:disable Metrics/AbcSize
program :version, Vmfloaty::VERSION
program :description, "A CLI helper tool for Puppet's vmpooler to help you stay afloat"
@ -45,7 +50,7 @@ class Vmfloaty
force = options.force
if args.empty?
STDERR.puts 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.'
logger.error 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.'
exit 1
end
@ -54,13 +59,13 @@ class Vmfloaty
max_pool_request = 5
large_pool_requests = os_types.select { |_, v| v > max_pool_request }
if !large_pool_requests.empty? && !force
STDERR.puts "Requesting vms over #{max_pool_request} requires a --force flag."
STDERR.puts 'Try again with `floaty get --force`'
logger.error "Requesting vms over #{max_pool_request} requires a --force flag."
logger.error 'Try again with `floaty get --force`'
exit 1
end
if os_types.empty?
STDERR.puts 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.'
logger.error 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.'
exit 1
end
@ -71,9 +76,9 @@ class Vmfloaty
hosts = Utils.standardize_hostnames(response)
if options.json || options.ondemand
STDOUT.puts JSON.pretty_generate(hosts)
puts JSON.pretty_generate(hosts)
else
STDOUT.puts Utils.format_host_output(hosts)
puts Utils.format_host_output(hosts)
end
end
end
@ -99,15 +104,15 @@ class Vmfloaty
running_vms = service.list_active(verbose)
host = URI.parse(service.url).host
if running_vms.empty?
STDOUT.puts "You have no running VMs on #{host}"
puts "You have no running VMs on #{host}"
else
STDOUT.puts "Your VMs on #{host}:"
puts "Your VMs on #{host}:"
Utils.pretty_print_hosts(verbose, service, running_vms)
end
else
# list available vms from pooler
os_list = service.list(verbose, filter)
STDOUT.puts os_list
puts os_list
end
end
end
@ -151,7 +156,7 @@ class Vmfloaty
modify_all = options.all
if hostname.nil? && !modify_all
STDERR.puts 'ERROR: Provide a hostname or specify --all.'
logger.error 'ERROR: Provide a hostname or specify --all.'
exit 1
end
running_vms = modify_all ? service.list_active(verbose) : hostname.split(',')
@ -172,17 +177,17 @@ class Vmfloaty
begin
modified_hash[vm] = service.modify(verbose, vm, modify_hash)
rescue ModifyError => e
STDERR.puts e
logger.error e
ok = false
end
end
if ok
if modify_all
STDOUT.puts 'Successfully modified all VMs.'
puts 'Successfully modified all VMs.'
else
STDOUT.puts "Successfully modified VM #{hostname}."
puts "Successfully modified VM #{hostname}."
end
STDOUT.puts 'Use `floaty list --active` to see the results.'
puts 'Use `floaty list --active` to see the results.'
end
end
end
@ -214,11 +219,10 @@ class Vmfloaty
if delete_all
running_vms = service.list_active(verbose)
if running_vms.empty?
STDOUT.puts 'You have no running VMs.'
puts 'You have no running VMs.'
else
Utils.pretty_print_hosts(verbose, service, running_vms, true)
# Confirm deletion
STDERR.puts
confirmed = true
confirmed = agree('Delete all these VMs? [y/N]') unless force
if confirmed
@ -243,23 +247,23 @@ class Vmfloaty
end
end
else
STDERR.puts 'You did not provide any hosts to delete'
logger.info 'You did not provide any hosts to delete'
exit 1
end
unless failures.empty?
STDERR.puts 'Unable to delete the following VMs:'
logger.info 'Unable to delete the following VMs:'
failures.each do |hostname|
STDERR.puts "- #{hostname}"
logger.info "- #{hostname}"
end
STDERR.puts 'Check `floaty list --active`; Do you need to specify a different service?'
logger.info 'Check `floaty list --active`; Do you need to specify a different service?'
end
unless successes.empty?
STDERR.puts unless failures.empty?
STDOUT.puts 'Scheduled the following VMs for deletion:'
logger.info unless failures.empty?
puts 'Scheduled the following VMs for deletion:'
successes.each do |hostname|
STDOUT.puts "- #{hostname}"
puts "- #{hostname}"
end
end
@ -284,11 +288,11 @@ class Vmfloaty
begin
snapshot_req = service.snapshot(verbose, hostname)
rescue TokenError, ModifyError => e
STDERR.puts e
logger.error e
exit 1
end
STDOUT.puts "Snapshot pending. Use `floaty query #{hostname}` to determine when snapshot is valid."
puts "Snapshot pending. Use `floaty query #{hostname}` to determine when snapshot is valid."
pp snapshot_req
end
end
@ -309,12 +313,12 @@ class Vmfloaty
hostname = args[0]
snapshot_sha = args[1] || options.snapshot
STDERR.puts "Two snapshot arguments were given....using snapshot #{snapshot_sha}" if args[1] && options.snapshot
logger.info "Two snapshot arguments were given....using snapshot #{snapshot_sha}" if args[1] && options.snapshot
begin
revert_req = service.revert(verbose, hostname, snapshot_sha)
rescue TokenError, ModifyError => e
STDERR.puts e
logger.error e
exit 1
end
@ -379,24 +383,24 @@ class Vmfloaty
case action
when 'get'
token = service.get_new_token(verbose)
STDOUT.puts token
puts token
when 'delete'
result = service.delete_token(verbose, options.token)
STDOUT.puts result
puts result
when 'status'
token_value = options.token
token_value = args[1] if token_value.nil?
status = service.token_status(verbose, token_value)
STDOUT.puts status
puts status
when nil
STDERR.puts 'No action provided'
logger.error 'No action provided'
exit 1
else
STDERR.puts "Unknown action: #{action}"
logger.error "Unknown action: #{action}"
exit 1
end
rescue TokenError => e
STDERR.puts e
logger.error e
exit 1
end
exit 0
@ -420,13 +424,13 @@ class Vmfloaty
use_token = !options.notoken
if args.empty?
STDERR.puts 'No operating systems provided to obtain. See `floaty ssh --help` for more information on how to get VMs.'
logger.error 'No operating systems provided to obtain. See `floaty ssh --help` for more information on how to get VMs.'
exit 1
end
host_os = args.first
STDERR.puts "Can't ssh to multiple hosts; Using #{host_os} only..." if args.length > 1
logger.info "Can't ssh to multiple hosts; Using #{host_os} only..." if args.length > 1
service.ssh(verbose, host_os, use_token)
exit 0
@ -450,10 +454,10 @@ class Vmfloaty
completion_file = File.expand_path(File.join('..', '..', 'extras', 'completions', "floaty.#{shell}"), __FILE__)
if File.exist?(completion_file)
STDOUT.puts completion_file
puts completion_file
exit 0
else
STDERR.puts "Could not find completion file for '#{shell}': No such file #{completion_file}"
logger.error "Could not find completion file for '#{shell}': No such file #{completion_file}"
exit 1
end
end

View file

@ -68,7 +68,7 @@ class ABS
ret_val.push(req_hash)
rescue NoMethodError
STDERR.puts "Warning: couldn't parse line returned from abs/status/queue: ".yellow
Vmfloaty.logger.warn "Warning: couldn't parse line returned from abs/status/queue: "
end
end
@ -85,7 +85,7 @@ class ABS
conn = Http.get_conn(verbose, url)
conn.headers['X-AUTH-TOKEN'] = token if token
STDERR.puts "Trying to delete hosts #{hosts}" if verbose
Vmfloaty.logger.info "Trying to delete hosts #{hosts}" if verbose
requests = get_active_requests(verbose, url, user)
jobs_to_delete = []
@ -113,7 +113,7 @@ class ABS
}
jobs_to_delete.push(req_hash)
else
STDERR.puts "When using ABS you must delete all vms that you requested at the same time: Can't delete #{req_hash['request']['job']['id']}: #{hosts} does not include all of #{req_hash['allocated_resources']}"
Vmfloaty.logger.info "When using ABS you must delete all vms that you requested at the same time: Can't delete #{req_hash['request']['job']['id']}: #{hosts} does not include all of #{req_hash['allocated_resources']}"
end
end
end
@ -127,7 +127,7 @@ class ABS
'hosts' => job['allocated_resources'],
}
STDERR.puts "Deleting #{req_obj}" if verbose
Vmfloaty.logger.info "Deleting #{req_obj}" if verbose
return_result = conn.post 'return', req_obj.to_json
req_obj['hosts'].each do |host|
@ -220,11 +220,11 @@ class ABS
end
end
STDERR.puts "Posting to ABS #{req_obj.to_json}" if verbose
Vmfloaty.logger.info "Posting to ABS #{req_obj.to_json}" if verbose
# os_string = os_type.map { |os, num| Array(os) * num }.flatten.join('+')
# raise MissingParamError, 'No operating systems provided to obtain.' if os_string.empty?
STDERR.puts "Requesting VMs with job_id: #{saved_job_id}. Will retry for up to an hour."
Vmfloaty.logger.info "Requesting VMs with job_id: #{saved_job_id}. Will retry for up to an hour."
res = conn.post 'request', req_obj.to_json
retries = 360
@ -237,7 +237,7 @@ class ABS
sleep_seconds = 10 if i >= 10
sleep_seconds = i if i < 10
STDERR.puts "Waiting #{sleep_seconds} seconds to check if ABS request has been filled. Queue Position: #{queue_place}... (x#{i})"
Vmfloaty.logger.info "Waiting #{sleep_seconds} seconds to check if ABS request has been filled. Queue Position: #{queue_place}... (x#{i})"
sleep(sleep_seconds)
end
@ -276,7 +276,7 @@ class ABS
end
def self.snapshot(_verbose, _url, _hostname, _token)
STDERR.puts "Can't snapshot with ABS, use '--service vmpooler' (even for vms checked out with ABS)"
Vmfloaty.logger.info "Can't snapshot with ABS, use '--service vmpooler' (even for vms checked out with ABS)"
end
def self.status(verbose, url)
@ -297,7 +297,7 @@ class ABS
def self.query(verbose, url, hostname)
return @active_hostnames if @active_hostnames
STDERR.puts "For vmpooler/snapshot information, use '--service vmpooler' (even for vms checked out with ABS)"
Vmfloaty.logger.info "For vmpooler/snapshot information, use '--service vmpooler' (even for vms checked out with ABS)"
conn = Http.get_conn(verbose, url)
res = conn.get "host/#{hostname}"

View file

@ -8,7 +8,7 @@ class Conf
begin
conf = YAML.load_file("#{Dir.home}/.vmfloaty.yml")
rescue StandardError
STDERR.puts "WARNING: There was no config file at #{Dir.home}/.vmfloaty.yml"
Vmfloaty.logger.warn "WARNING: There was no config file at #{Dir.home}/.vmfloaty.yml"
end
conf
end

11
lib/vmfloaty/logger.rb Normal file
View file

@ -0,0 +1,11 @@
require 'logger'
class FloatyLogger < ::Logger
def initialize
super(STDERR)
self.level = ::Logger::INFO
self.formatter = proc do |severity, datetime, progname, msg|
"#{msg}\n"
end
end
end

View file

@ -60,10 +60,10 @@ class Pooler
while check_ondemandvm(verbose, request_id, url) == false
return false if (Time.now - start_time).to_i > timeout
STDOUT.puts "waiting for request #{request_id} to be fulfilled"
Vmfloaty.logger.info "waiting for request #{request_id} to be fulfilled"
sleep 5
end
STDOUT.puts "The request has been fulfilled"
Vmfloaty.logger.info "The request has been fulfilled"
check_ondemandvm(verbose, request_id, url)
end

View file

@ -36,7 +36,7 @@ class Service
def user
unless @config['user']
STDERR.puts "Enter your #{@config['url']} service username:"
Vmfloaty.logger.info "Enter your #{@config['url']} service username:"
@config['user'] = STDIN.gets.chomp
end
@config['user']
@ -44,7 +44,7 @@ class Service
def token
unless @config['token']
STDERR.puts 'No token found. Retrieving a token...'
Vmfloaty.logger.info 'No token found. Retrieving a token...'
@config['token'] = get_new_token(nil)
end
@config['token']
@ -76,7 +76,7 @@ class Service
end
def retrieve(verbose, os_types, use_token = true, ondemand = nil)
STDERR.puts 'Requesting a vm without a token...' unless use_token
Vmfloaty.logger.info 'Requesting a vm without a token...' unless use_token
token_value = use_token ? token : nil
@service_object.retrieve verbose, os_types, token_value, url, user, @config, ondemand
end
@ -91,8 +91,8 @@ class Service
begin
token_value = token || get_new_token(verbose)
rescue TokenError => e
STDERR.puts e
STDERR.puts 'Could not get token... requesting vm without a token anyway...'
Vmfloaty.logger.error e
Vmfloaty.logger.info 'Could not get token... requesting vm without a token anyway...'
end
end
Ssh.ssh(verbose, self, host_os, token_value)

View file

@ -45,7 +45,6 @@ class Utils
result = {}
STDERR.puts "response body is #{response_body}"
filtered_response_body = response_body.reject { |key, _| key == 'request_id' || key == 'ready' }
filtered_response_body.each do |os, value|
hostnames = Array(value['hostname'])
@ -91,7 +90,7 @@ class Utils
# For ABS, 'hostname' variable is the jobID
if host_data['state'] == 'allocated' || host_data['state'] == 'filled'
host_data['allocated_resources'].each do |vm_name, _i|
STDOUT.puts "- [JobID:#{host_data['request']['job']['id']}] #{vm_name['hostname']} (#{vm_name['type']}) <#{host_data['state']}>"
puts "- [JobID:#{host_data['request']['job']['id']}] #{vm_name['hostname']} (#{vm_name['type']}) <#{host_data['state']}>"
end
end
when 'Pooler'
@ -99,19 +98,19 @@ class Utils
tag_pairs = host_data['tags'].map { |key, value| "#{key}: #{value}" } unless host_data['tags'].nil?
duration = "#{host_data['running']}/#{host_data['lifetime']} hours"
metadata = [host_data['template'], duration, *tag_pairs]
STDOUT.puts "- #{hostname}.#{host_data['domain']} (#{metadata.join(', ')})"
puts "- #{hostname}.#{host_data['domain']} (#{metadata.join(', ')})"
when 'NonstandardPooler'
line = "- #{host_data['fqdn']} (#{host_data['os_triple']}"
line += ", #{host_data['hours_left_on_reservation']}h remaining"
line += ", reason: #{host_data['reserved_for_reason']}" unless host_data['reserved_for_reason'].empty?
line += ')'
STDOUT.puts line
puts line
else
raise "Invalid service type #{service.type}"
end
rescue StandardError => e
STDERR.puts("Something went wrong while trying to gather information on #{hostname}:")
STDERR.puts(e)
Vmfloaty.logger.error("Something went wrong while trying to gather information on #{hostname}:")
Vmfloaty.logger.error(e)
end
end
end
@ -133,12 +132,12 @@ class Utils
pending = pool['pending']
missing = max - ready - pending
char = 'o'
STDOUT.puts "#{name.ljust(width)} #{(char * ready).green}#{(char * pending).yellow}#{(char * missing).red}"
puts "#{name.ljust(width)} #{(char * ready).green}#{(char * pending).yellow}#{(char * missing).red}"
rescue StandardError => e
STDERR.puts "#{name.ljust(width)} #{e.red}"
Vmfloaty.logger.error "#{name.ljust(width)} #{e.red}"
end
end
STDOUT.puts message.colorize(status_response['status']['ok'] ? :default : :red)
puts message.colorize(status_response['status']['ok'] ? :default : :red)
when 'NonstandardPooler'
pools = status_response
pools.delete 'ok'
@ -152,14 +151,14 @@ class Utils
pending = pool['pending'] || 0 # not available for nspooler
missing = max - ready - pending
char = 'o'
STDOUT.puts "#{name.ljust(width)} #{(char * ready).green}#{(char * pending).yellow}#{(char * missing).red}"
puts "#{name.ljust(width)} #{(char * ready).green}#{(char * pending).yellow}#{(char * missing).red}"
rescue StandardError => e
STDERR.puts "#{name.ljust(width)} #{e.red}"
Vmfloaty.logger.error "#{name.ljust(width)} #{e.red}"
end
end
when 'ABS'
STDERR.puts 'ABS Not OK'.red unless status_response
STDOUT.puts 'ABS is OK'.green if status_response
Vmfloaty.logger.error 'ABS Not OK' unless status_response
puts 'ABS is OK'.green if status_response
else
raise "Invalid service type #{service.type}"
end