vmfloaty 0.8.2 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 04b7261aa013260aba635e266b003d845e4a2c58
4
- data.tar.gz: 83bbc1c12ace45c6a1ea288121762f13d3b841ae
2
+ SHA256:
3
+ metadata.gz: 248dd5c9a8890b8990a7dad8dd7a21f52c8a8c2b65112c55449a5b5d3ac818af
4
+ data.tar.gz: 22cf2070b571a0feded3967308e6b11d42b5ea296d94be7c434a73454611f6df
5
5
  SHA512:
6
- metadata.gz: 4e38aedb270708b75d9464744b73b507a6dfdab100567a079287b6b06aa0ac57fabaa03e0e18761c5d1b21e2921f15fbd36ab5beeddcbf3266cac2981d90931c
7
- data.tar.gz: 04ddaf46164b38bf84df47ee8d5a0e96d87b6be5d64941ee72a075e5264511c7556b8fdd85a2875fadfea37820cfbc307adc6dd46eb32621c1cb552d70cbec94
6
+ metadata.gz: 8cd836baeb4a37720024616f1ce113046fc6291cc73694edbaf74ee727648c1339ada9e004ba0d630822a315948d69bb9e6c67da1ec04df3ae079bf207a432c7
7
+ data.tar.gz: 46e15ff3d3d1cecd68cb92ed3fcd5d8240f68f45f704dff9fbf1e87007cae7b95b2d6f9d4b08753979b2c82fa6f412534a93e3bb17b96fb052003e821b31cf94
data/README.md CHANGED
@@ -1,40 +1,64 @@
1
- vmfloaty
2
- ========
3
-
4
- [![Gem Version](https://badge.fury.io/rb/vmfloaty.svg)](https://badge.fury.io/rb/vmfloaty) [![Build Status](https://travis-ci.org/briancain/vmfloaty.svg?branch=master)](https://travis-ci.org/briancain/vmfloaty)
5
-
6
- A CLI helper tool for [Puppet Labs vmpooler](https://github.com/puppetlabs/vmpooler) to help you stay afloat.
7
-
8
- <img src="http://i.imgur.com/xGcGwuH.jpg" width=200 height=200>
9
-
10
- This project is still supported by @briancain and @demophoon. Ping either of us if you'd like something merged and released.
1
+ # vmfloaty
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/vmfloaty.svg)](https://badge.fury.io/rb/vmfloaty)
4
+ [![Build Status](https://travis-ci.com/puppetlabs/vmfloaty.svg?branch=master)](https://travis-ci.com/puppetlabs/vmfloaty)
5
+ [![Coverage Status](https://coveralls.io/repos/github/puppetlabs/vmfloaty/badge.svg?branch=master)](https://coveralls.io/github/puppetlabs/vmfloaty?branch=master)
6
+ [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=puppetlabs/vmfloaty)](https://dependabot.com)
7
+
8
+ A CLI helper tool for [Puppet's vmpooler](https://github.com/puppetlabs/vmpooler) to help you stay afloat.
9
+
10
+ ![float image](float.jpg)
11
+
12
+ - [Install](#install)
13
+ - [Usage](#usage)
14
+ - [Example workflow](#example-workflow)
15
+ - [vmfloaty dotfile](#vmfloaty-dotfile)
16
+ - [Basic configuration](#basic-configuration)
17
+ - [Default to Puppet's ABS instead of vmpooler](#default-to-puppets-abs-instead-of-vmpooler)
18
+ - [Configuring multiple services](#configuring-multiple-services)
19
+ - [Using a Nonstandard Pooler service](#using-a-nonstandard-pooler-service)
20
+ - [Valid config keys](#valid-config-keys)
21
+ - [Tab Completion](#tab-completion)
22
+ - [vmpooler API](#vmpooler-api)
23
+ - [Using the Pooler class](#using-the-pooler-class)
24
+ - [Example Projects](#example-projects)
25
+ - [Special thanks](#special-thanks)
11
26
 
12
27
  ## Install
13
28
 
14
29
  Grab the latest from ruby gems...
15
30
 
16
- ```
17
- $ gem install vmfloaty
18
- ...
19
- ...
20
- $ floaty --help
31
+ ```bash
32
+ gem install vmfloaty
21
33
  ```
22
34
 
23
35
  ## Usage
24
36
 
25
- ```
26
- delete Schedules the deletion of a host or hosts
27
- get Gets a vm or vms based on the os argument
28
- help Display global or [command] help documentation
29
- list Shows a list of available vms from the pooler or vms obtained with a token
30
- modify Modify a vms tags, time to live, and disk space
31
- query Get information about a given vm
32
- revert Reverts a vm to a specified snapshot
33
- snapshot Takes a snapshot of a given vm
34
- ssh Grabs a single vm and sshs into it
35
- status Prints the status of pools in vmpooler
36
- summary Prints a summary of vmpooler
37
- token Retrieves or deletes a token or checks token status
37
+ ```plain
38
+ $ floaty --help
39
+ NAME:
40
+
41
+ floaty
42
+
43
+ DESCRIPTION:
44
+
45
+ A CLI helper tool for Puppet's vmpooler to help you stay afloat
46
+
47
+ COMMANDS:
48
+
49
+ completion Outputs path to completion script
50
+ delete Schedules the deletion of a host or hosts
51
+ get Gets a vm or vms based on the os argument
52
+ help Display global or [command] help documentation
53
+ list Shows a list of available vms from the pooler or vms obtained with a token
54
+ modify Modify a VM's tags, time to live, disk space, or reservation reason
55
+ query Get information about a given vm
56
+ revert Reverts a vm to a specified snapshot
57
+ snapshot Takes a snapshot of a given vm
58
+ ssh Grabs a single vm and sshs into it
59
+ status Prints the status of pools in the pooler service
60
+ summary Prints a summary of a pooler service
61
+ token Retrieves or deletes a token or checks token status
38
62
 
39
63
  GLOBAL OPTIONS:
40
64
 
@@ -52,33 +76,43 @@ $ floaty --help
52
76
 
53
77
  Grabbing a token for authenticated pooler requests:
54
78
 
55
- ```
56
- floaty token get --user username --url https://vmpooler.mycompany.net/api/v1
79
+ ```bash
80
+ floaty token get --user username --url https://vmpooler.example.net/api/v1
57
81
  ```
58
82
 
59
83
  This command will then ask you to log in. If successful, it will return a token that you can save either in a dotfile or use with other cli commands.
60
84
 
61
85
  Grabbing vms:
62
86
 
63
- ```
64
- floaty get centos-7-x86_64=2 debian-7-x86_64 windows-10=3 --token mytokenstring --url https://vmpooler.mycompany.net/api/v1
87
+ ```bash
88
+ floaty get centos-7-x86_64=2 debian-7-x86_64 windows-10=3 --token mytokenstring --url https://vmpooler.example.net/api/v1
65
89
  ```
66
90
 
67
91
  ### vmfloaty dotfile
68
92
 
69
- If you do not wish to continuely specify various config options with the cli, you can have a dotfile in your home directory for some defaults. For example:
93
+ If you do not wish to continually specify various config options with the cli, you can have a dotfile in your home directory for some defaults. For example:
70
94
 
71
95
  #### Basic configuration
72
96
 
73
97
  ```yaml
74
- # file at /Users/me/.vmfloaty.yml
75
- url: 'https://vmpooler.mycompany.net/api/v1'
98
+ # file at ~/.vmfloaty.yml
99
+ url: 'https://vmpooler.example.net/api/v1'
76
100
  user: 'brian'
77
101
  token: 'tokenstring'
78
102
  ```
79
103
 
80
104
  Now vmfloaty will use those config files if no flag was specified.
81
105
 
106
+ #### Default to Puppet's ABS instead of vmpooler
107
+
108
+ ```yaml
109
+ # file at ~/.vmfloaty.yml
110
+ url: 'https://abs.example.net'
111
+ user: 'brian'
112
+ token: 'tokenstring'
113
+ type: 'abs'
114
+ ```
115
+
82
116
  #### Configuring multiple services
83
117
 
84
118
  Most commands allow you to specify a `--service <servicename>` option to allow the use of multiple vmpooler instances. This can be useful when you'd rather not specify a `--url` or `--token` by hand for alternate services.
@@ -90,10 +124,10 @@ To configure multiple services, you can set up your `~/.vmfloaty.yml` config fil
90
124
  user: 'brian'
91
125
  services:
92
126
  main:
93
- url: 'https://vmpooler.mycompany.net/api/v1'
127
+ url: 'https://vmpooler.example.net/api/v1'
94
128
  token: 'tokenstring'
95
129
  alternate:
96
- url: 'https://vmpooler.alternate.net/api/v1'
130
+ url: 'https://vmpooler.example.com/api/v1'
97
131
  token: 'alternate-tokenstring'
98
132
  ```
99
133
 
@@ -105,14 +139,16 @@ services:
105
139
  Examples using the above configuration:
106
140
 
107
141
  List available vm types from our main vmpooler instance:
108
- ```sh
142
+
143
+ ```bash
109
144
  floaty list --service main
110
145
  # or, since the first configured service is used by default:
111
146
  floaty list
112
147
  ```
113
148
 
114
149
  List available vm types from our alternate vmpooler instance:
115
- ```sh
150
+
151
+ ```bash
116
152
  floaty list --service alternate
117
153
  ```
118
154
 
@@ -125,17 +161,22 @@ vmfloaty is capable of working with Puppet's [nonstandard pooler](https://github
125
161
  user: 'brian'
126
162
  services:
127
163
  vm:
128
- url: 'https://vmpooler.mycompany.net/api/v1'
164
+ url: 'https://vmpooler.example.net/api/v1'
129
165
  token: 'tokenstring'
130
166
  ns:
131
- url: 'https://nspooler.mycompany.net/api/v1'
167
+ url: 'https://nspooler.example.net/api/v1'
132
168
  token: 'nspooler-tokenstring'
133
169
  type: 'nonstandard' # <-- 'type' is necessary for any non-vmpooler service
170
+ abs:
171
+ url: 'https://abs.example.net/'
172
+ token: 'abs-tokenstring'
173
+ type: 'abs' # <-- 'type' is necessary for any non-vmpooler service
174
+
134
175
  ```
135
176
 
136
177
  With this configuration, you could list available OS types from nspooler like this:
137
178
 
138
- ```sh
179
+ ```bash
139
180
  floaty list --service ns
140
181
  ```
141
182
 
@@ -143,20 +184,16 @@ floaty list --service ns
143
184
 
144
185
  Here are the keys that vmfloaty currently supports:
145
186
 
146
- - verbose
147
- + Boolean
148
- - token
149
- + String
150
- - user
151
- + String
152
- - url
153
- + String
154
- - services
155
- + Map
187
+ - verbose (Boolean)
188
+ - token (String)
189
+ - user (String)
190
+ - url (String)
191
+ - services (String)
192
+ - type (String)
156
193
 
157
194
  ### Tab Completion
158
195
 
159
- There is a basic completion script for Bash (and possibly other shells) included with the gem in the [extras/completions](https://github.com/briancain/vmfloaty/blob/master/extras/completions) folder. To activate, that file simply needs to be sourced somehow in your shell profile.
196
+ There is a basic completion script for Bash (and possibly other shells) included with the gem in the [extras/completions](https://github.com/puppetlabs/vmfloaty/blob/master/extras/completions) folder. To activate, that file simply needs to be sourced somehow in your shell profile.
160
197
 
161
198
  For convenience, the path to the completion script for the currently active version of the gem can be found with the `floaty completion` subcommand. This makes it easy to add the completion script to your profile like so:
162
199
 
@@ -181,6 +218,10 @@ vmfloaty providers a `Pooler` class that gives users the ability to make request
181
218
  ### Example Projects
182
219
 
183
220
  - [John McCabe: vmpooler-bitbar](https://github.com/johnmccabe/vmpooler-bitbar/)
184
- + vmpooler status and management in your menubar with bitbar
221
+ - vmpooler status and management in your menubar with bitbar
185
222
  - [Brian Cain: vagrant-vmpooler](https://github.com/briancain/vagrant-vmpooler)
186
- + Use Vagrant to manage your vmpooler instances
223
+ - Use Vagrant to manage your vmpooler instances
224
+
225
+ ## Special thanks
226
+
227
+ Special thanks to [Brian Cain](https://github.com/briancain) as he is the original author of vmfloaty! Vast amounts of this code exist thanks to his efforts.
data/bin/floaty CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
4
+ $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
4
5
 
5
6
  require 'vmfloaty'
6
7
 
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'rubygems'
4
4
  require 'commander'
@@ -13,13 +13,14 @@ require 'vmfloaty/conf'
13
13
  require 'vmfloaty/utils'
14
14
  require 'vmfloaty/service'
15
15
  require 'vmfloaty/ssh'
16
+ require 'vmfloaty/logger'
16
17
 
17
18
  class Vmfloaty
18
19
  include Commander::Methods
19
20
 
20
- def run
21
+ def run # rubocop:disable Metrics/AbcSize
21
22
  program :version, Vmfloaty::VERSION
22
- program :description, 'A CLI helper tool for Puppet Labs VM poolers to help you stay afloat'
23
+ program :description, "A CLI helper tool for Puppet's vmpooler to help you stay afloat"
23
24
 
24
25
  config = Conf.read_config
25
26
 
@@ -33,9 +34,11 @@ class Vmfloaty
33
34
  c.option '--user STRING', String, 'User to authenticate with'
34
35
  c.option '--url STRING', String, 'URL of pooler service'
35
36
  c.option '--token STRING', String, 'Token for pooler service'
37
+ c.option '--priority STRING', 'Priority for supported backends(ABS) (High(1), Medium(2), Low(3))'
36
38
  c.option '--notoken', 'Makes a request without a token'
37
39
  c.option '--force', 'Forces vmfloaty to get requested vms'
38
40
  c.option '--json', 'Prints retrieved vms in JSON format'
41
+ c.option '--ondemand', 'Requested vms are provisioned upon receival of the request, tracked by a request ID'
39
42
  c.action do |args, options|
40
43
  verbose = options.verbose || config['verbose']
41
44
  service = Service.new(options, config)
@@ -43,28 +46,32 @@ class Vmfloaty
43
46
  force = options.force
44
47
 
45
48
  if args.empty?
46
- STDERR.puts "No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs."
49
+ FloatyLogger.error 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.'
47
50
  exit 1
48
51
  end
49
52
 
50
53
  os_types = Utils.generate_os_hash(args)
51
54
 
52
55
  max_pool_request = 5
53
- large_pool_requests = os_types.select{|_,v| v > max_pool_request}
54
- if ! large_pool_requests.empty? and ! force
55
- STDERR.puts "Requesting vms over #{max_pool_request} requires a --force flag."
56
- STDERR.puts "Try again with `floaty get --force`"
56
+ large_pool_requests = os_types.select { |_, v| v > max_pool_request }
57
+ if !large_pool_requests.empty? && !force
58
+ FloatyLogger.error "Requesting vms over #{max_pool_request} requires a --force flag."
59
+ FloatyLogger.error 'Try again with `floaty get --force`'
57
60
  exit 1
58
61
  end
59
62
 
60
63
  if os_types.empty?
61
- STDERR.puts "No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs."
64
+ FloatyLogger.error 'No operating systems provided to obtain. See `floaty get --help` for more information on how to get VMs.'
62
65
  exit 1
63
66
  end
64
67
 
65
- response = service.retrieve(verbose, os_types, use_token)
68
+ response = service.retrieve(verbose, os_types, use_token, options.ondemand)
69
+ request_id = response['request_id'] if options.ondemand
70
+ response = service.wait_for_request(verbose, request_id) if options.ondemand
71
+
66
72
  hosts = Utils.standardize_hostnames(response)
67
- if options.json
73
+
74
+ if options.json || options.ondemand
68
75
  puts JSON.pretty_generate(hosts)
69
76
  else
70
77
  puts Utils.format_host_output(hosts)
@@ -84,6 +91,7 @@ class Vmfloaty
84
91
  c.option '--url STRING', String, 'URL of pooler service'
85
92
  c.action do |args, options|
86
93
  verbose = options.verbose || config['verbose']
94
+
87
95
  service = Service.new(options, config)
88
96
  filter = args[0]
89
97
 
@@ -143,18 +151,18 @@ class Vmfloaty
143
151
  hostname = args[0]
144
152
  modify_all = options.all
145
153
 
146
- if hostname.nil? and !modify_all
147
- STDERR.puts "ERROR: Provide a hostname or specify --all."
154
+ if hostname.nil? && !modify_all
155
+ FloatyLogger.error 'ERROR: Provide a hostname or specify --all.'
148
156
  exit 1
149
157
  end
150
- running_vms = modify_all ? service.list_active(verbose) : hostname.split(",")
158
+ running_vms = modify_all ? service.list_active(verbose) : hostname.split(',')
151
159
 
152
160
  tags = options.tags ? JSON.parse(options.tags) : nil
153
161
  modify_hash = {
154
- lifetime: options.lifetime,
155
- disk: options.disk,
156
- tags: tags,
157
- reason: options.reason
162
+ :lifetime => options.lifetime,
163
+ :disk => options.disk,
164
+ :tags => tags,
165
+ :reason => options.reason,
158
166
  }
159
167
  modify_hash.delete_if { |_, value| value.nil? }
160
168
 
@@ -165,17 +173,17 @@ class Vmfloaty
165
173
  begin
166
174
  modified_hash[vm] = service.modify(verbose, vm, modify_hash)
167
175
  rescue ModifyError => e
168
- STDERR.puts e
176
+ FloatyLogger.error e
169
177
  ok = false
170
178
  end
171
179
  end
172
180
  if ok
173
181
  if modify_all
174
- puts "Successfully modified all VMs."
182
+ puts 'Successfully modified all VMs.'
175
183
  else
176
184
  puts "Successfully modified VM #{hostname}."
177
185
  end
178
- puts "Use `floaty list --active` to see the results."
186
+ puts 'Use `floaty list --active` to see the results.'
179
187
  end
180
188
  end
181
189
  end
@@ -183,9 +191,11 @@ class Vmfloaty
183
191
 
184
192
  command :delete do |c|
185
193
  c.syntax = 'floaty delete hostname,hostname2 [options]'
194
+ c.syntax += "\n floaty delete job1,job2 [options] (only supported with ABS)"
186
195
  c.summary = 'Schedules the deletion of a host or hosts'
187
- c.description = 'Given a comma separated list of hostnames, or --all for all vms, vmfloaty makes a request to the pooler service to schedule the deletion of those vms.'
196
+ c.description = 'Given a comma separated list of hostnames, or --all for all vms, vmfloaty makes a request to the pooler service to schedule the deletion of those vms. If you are using the ABS service, you can also pass in JobIDs here. Note that passing in a Job ID will delete *all* of the hosts in the job.' # rubocop:disable Layout/LineLength
188
197
  c.example 'Schedules the deletion of a host or hosts', 'floaty delete myhost1,myhost2 --url http://vmpooler.example.com'
198
+ c.example 'Schedules the deletion of a JobID or JobIDs', 'floaty delete 1579300120799,1579300120800 --url http://abs.example.com'
189
199
  c.option '--verbose', 'Enables verbose output'
190
200
  c.option '--service STRING', String, 'Configured pooler service name'
191
201
  c.option '--all', 'Deletes all vms acquired by a token'
@@ -205,15 +215,12 @@ class Vmfloaty
205
215
  if delete_all
206
216
  running_vms = service.list_active(verbose)
207
217
  if running_vms.empty?
208
- STDERR.puts "You have no running VMs."
218
+ puts 'You have no running VMs.'
209
219
  else
210
- Utils.pretty_print_hosts(verbose, service, running_vms)
220
+ Utils.pretty_print_hosts(verbose, service, running_vms, true)
211
221
  # Confirm deletion
212
- puts
213
222
  confirmed = true
214
- unless force
215
- confirmed = agree('Delete all these VMs? [y/N]')
216
- end
223
+ confirmed = agree('Delete all these VMs? [y/N]') unless force
217
224
  if confirmed
218
225
  response = service.delete(verbose, running_vms)
219
226
  response.each do |hostname, result|
@@ -236,20 +243,20 @@ class Vmfloaty
236
243
  end
237
244
  end
238
245
  else
239
- STDERR.puts "You did not provide any hosts to delete"
246
+ FloatyLogger.info 'You did not provide any hosts to delete'
240
247
  exit 1
241
248
  end
242
249
 
243
250
  unless failures.empty?
244
- STDERR.puts 'Unable to delete the following VMs:'
251
+ FloatyLogger.info 'Unable to delete the following VMs:'
245
252
  failures.each do |hostname|
246
- STDERR.puts "- #{hostname}"
253
+ FloatyLogger.info "- #{hostname}"
247
254
  end
248
- STDERR.puts 'Check `floaty list --active`; Do you need to specify a different service?'
255
+ FloatyLogger.info 'Check `floaty list --active`; Do you need to specify a different service?'
249
256
  end
250
257
 
251
258
  unless successes.empty?
252
- puts unless failures.empty?
259
+ FloatyLogger.info unless failures.empty?
253
260
  puts 'Scheduled the following VMs for deletion:'
254
261
  successes.each do |hostname|
255
262
  puts "- #{hostname}"
@@ -277,7 +284,7 @@ class Vmfloaty
277
284
  begin
278
285
  snapshot_req = service.snapshot(verbose, hostname)
279
286
  rescue TokenError, ModifyError => e
280
- STDERR.puts e
287
+ FloatyLogger.error e
281
288
  exit 1
282
289
  end
283
290
 
@@ -302,14 +309,12 @@ class Vmfloaty
302
309
  hostname = args[0]
303
310
  snapshot_sha = args[1] || options.snapshot
304
311
 
305
- if args[1] && options.snapshot
306
- STDERR.puts "Two snapshot arguments were given....using snapshot #{snapshot_sha}"
307
- end
312
+ FloatyLogger.info "Two snapshot arguments were given....using snapshot #{snapshot_sha}" if args[1] && options.snapshot
308
313
 
309
314
  begin
310
315
  revert_req = service.revert(verbose, hostname, snapshot_sha)
311
316
  rescue TokenError, ModifyError => e
312
- STDERR.puts e
317
+ FloatyLogger.error e
313
318
  exit 1
314
319
  end
315
320
 
@@ -372,28 +377,26 @@ class Vmfloaty
372
377
 
373
378
  begin
374
379
  case action
375
- when 'get'
376
- token = service.get_new_token(verbose)
377
- puts token
378
- when 'delete'
379
- result = service.delete_token(verbose, options.token)
380
- puts result
381
- when 'status'
382
- token_value = options.token
383
- if token_value.nil?
384
- token_value = args[1]
385
- end
386
- status = service.token_status(verbose, token_value)
387
- puts status
388
- when nil
389
- STDERR.puts 'No action provided'
390
- exit 1
391
- else
392
- STDERR.puts "Unknown action: #{action}"
393
- exit 1
380
+ when 'get'
381
+ token = service.get_new_token(verbose)
382
+ puts token
383
+ when 'delete'
384
+ result = service.delete_token(verbose, options.token)
385
+ puts result
386
+ when 'status'
387
+ token_value = options.token
388
+ token_value = args[1] if token_value.nil?
389
+ status = service.token_status(verbose, token_value)
390
+ puts status
391
+ when nil
392
+ FloatyLogger.error 'No action provided'
393
+ exit 1
394
+ else
395
+ FloatyLogger.error "Unknown action: #{action}"
396
+ exit 1
394
397
  end
395
398
  rescue TokenError => e
396
- STDERR.puts e
399
+ FloatyLogger.error e
397
400
  exit 1
398
401
  end
399
402
  exit 0
@@ -417,15 +420,13 @@ class Vmfloaty
417
420
  use_token = !options.notoken
418
421
 
419
422
  if args.empty?
420
- STDERR.puts "No operating systems provided to obtain. See `floaty ssh --help` for more information on how to get VMs."
423
+ FloatyLogger.error 'No operating systems provided to obtain. See `floaty ssh --help` for more information on how to get VMs.'
421
424
  exit 1
422
425
  end
423
426
 
424
427
  host_os = args.first
425
428
 
426
- if args.length > 1
427
- STDERR.puts "Can't ssh to multiple hosts; Using #{host_os} only..."
428
- end
429
+ FloatyLogger.info "Can't ssh to multiple hosts; Using #{host_os} only..." if args.length > 1
429
430
 
430
431
  service.ssh(verbose, host_os, use_token)
431
432
  exit 0
@@ -435,13 +436,13 @@ class Vmfloaty
435
436
  command :completion do |c|
436
437
  c.syntax = 'floaty completion [options]'
437
438
  c.summary = 'Outputs path to completion script'
438
- c.description = Utils.strip_heredoc(<<-EOF)
439
+ c.description = Utils.strip_heredoc(<<-DESCRIPTION)
439
440
  Outputs path to a completion script for the specified shell (or 'bash' if not specified). This makes it easy to add the completion script to your profile:
440
441
 
441
442
  source $(floaty completion --shell bash)
442
443
 
443
444
  This subcommand will exit non-zero with an error message if no completion script is available for the requested shell.
444
- EOF
445
+ DESCRIPTION
445
446
  c.example 'Gets path to bash tab completion script', 'floaty completion --shell bash'
446
447
  c.option '--shell STRING', String, 'Shell to request completion script for'
447
448
  c.action do |_, options|
@@ -452,7 +453,7 @@ class Vmfloaty
452
453
  puts completion_file
453
454
  exit 0
454
455
  else
455
- STDERR.puts "Could not find completion file for '#{shell}': No such file #{completion_file}"
456
+ FloatyLogger.error "Could not find completion file for '#{shell}': No such file #{completion_file}"
456
457
  exit 1
457
458
  end
458
459
  end