vmfloaty 1.1.1 → 1.5.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
2
  SHA256:
3
- metadata.gz: cfd72279e6067194457cfff7e798bffb6c3f7e516a215ab25507836a35918dfa
4
- data.tar.gz: e5f63b9b99f8969e557cf14993d89063353b2b8d2201e2945204375f4c8599f1
3
+ metadata.gz: 622a0112e8e8c09fd70d5c2d2b0f31e89032a907db86aebd84ce019238c3e4f5
4
+ data.tar.gz: 38f82e6bbf28d2669219b8f856af7876864ecdcef54e46f44c4d9dab8c09e56d
5
5
  SHA512:
6
- metadata.gz: 57500a3436d64a3edc4aa8a11bcfc5590a05788268fb7c556d70816a0dede112225298f657a762c8a5eec3b829117f91599e286115237e5e039dfe5554d9d2c2
7
- data.tar.gz: 288ded1bca5cfe6bff06be880b17264ddd49a10674649a1424515af7a48d646eb0b693123aee0ec353b6bb57424f209ca7cd653e1fd3287831b137593ebfe50b
6
+ metadata.gz: 47f457eeda161702eedd0246ea1d4e7fd146044d00d98334009746ae1dc3ab7ee1f5b80e27287ba1c4f330ee07ccdd889348362ede637503265b1b68ae3bd5b6
7
+ data.tar.gz: adc9ac4bf7ce2ab2ef4080b7ffc702866aa7a58177c9e6b1ab948d371e51e3deb9e6a0293dda83762633267376db831f0b4eaa036b4a0dc672268ffe51471306
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # vmfloaty
2
2
 
3
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)
4
+ [![Build Status](https://github.com/puppetlabs/vmfloaty/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/puppetlabs/vmfloaty/actions/workflows/ci.yml)
5
+ [![Coverage Status](https://github.com/puppetlabs/vmfloaty/badge.svg?branch=main)](https://coveralls.io/github/puppetlabs/vmfloaty?branch=main)
6
6
  [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=puppetlabs/vmfloaty)](https://dependabot.com)
7
7
 
8
8
  A CLI helper tool for [Puppet's vmpooler](https://github.com/puppetlabs/vmpooler) to help you stay afloat.
data/lib/vmfloaty/abs.rb CHANGED
@@ -53,10 +53,10 @@ class ABS
53
53
  def self.list_active(verbose, url, _token, user)
54
54
  hosts = []
55
55
  get_active_requests(verbose, url, user).each do |req_hash|
56
- if req_hash.key?('allocated_resources')
57
- req_hash['allocated_resources'].each do |onehost|
58
- hosts.push(onehost['hostname'])
59
- end
56
+ next unless req_hash.key?('allocated_resources')
57
+
58
+ req_hash['allocated_resources'].each do |onehost|
59
+ hosts.push(onehost['hostname'])
60
60
  end
61
61
  end
62
62
 
@@ -116,7 +116,7 @@ class ABS
116
116
  ret_status = {}
117
117
  hosts.each do |host|
118
118
  ret_status[host] = {
119
- 'ok' => false,
119
+ 'ok' => false
120
120
  }
121
121
  end
122
122
 
@@ -132,7 +132,7 @@ class ABS
132
132
  if hosts.include? vm_name['hostname']
133
133
  if all_job_resources_accounted_for(req_hash['allocated_resources'], hosts)
134
134
  ret_status[vm_name['hostname']] = {
135
- 'ok' => true,
135
+ 'ok' => true
136
136
  }
137
137
  jobs_to_delete.push(req_hash)
138
138
  else
@@ -147,7 +147,7 @@ class ABS
147
147
  jobs_to_delete.each do |job|
148
148
  req_obj = {
149
149
  'job_id' => job['request']['job']['id'],
150
- 'hosts' => job['allocated_resources'],
150
+ 'hosts' => job['allocated_resources']
151
151
  }
152
152
 
153
153
  FloatyLogger.info "Deleting #{req_obj}" if verbose
@@ -172,11 +172,11 @@ class ABS
172
172
  res_body = JSON.parse(res.body)
173
173
  if res_body.key?('vmpooler_platforms')
174
174
  os_list << '*** VMPOOLER Pools ***'
175
- if res_body['vmpooler_platforms'].is_a?(String)
176
- os_list += JSON.parse(res_body['vmpooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
177
- else
178
- os_list += res_body['vmpooler_platforms']
179
- end
175
+ os_list += if res_body['vmpooler_platforms'].is_a?(String)
176
+ JSON.parse(res_body['vmpooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
177
+ else
178
+ res_body['vmpooler_platforms']
179
+ end
180
180
  end
181
181
  end
182
182
 
@@ -200,11 +200,11 @@ class ABS
200
200
  if res_body.key?('nspooler_platforms')
201
201
  os_list << ''
202
202
  os_list << '*** NSPOOLER Pools ***'
203
- if res_body['nspooler_platforms'].is_a?(String)
204
- os_list += JSON.parse(res_body['nspooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
205
- else
206
- os_list += res_body['nspooler_platforms']
207
- end
203
+ os_list += if res_body['nspooler_platforms'].is_a?(String)
204
+ JSON.parse(res_body['nspooler_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
205
+ else
206
+ res_body['nspooler_platforms']
207
+ end
208
208
  end
209
209
  end
210
210
 
@@ -214,11 +214,11 @@ class ABS
214
214
  if res_body.key?('aws_platforms')
215
215
  os_list << ''
216
216
  os_list << '*** AWS Pools ***'
217
- if res_body['aws_platforms'].is_a?(String)
218
- os_list += JSON.parse(res_body['aws_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
219
- else
220
- os_list += res_body['aws_platforms']
221
- end
217
+ os_list += if res_body['aws_platforms'].is_a?(String)
218
+ JSON.parse(res_body['aws_platforms']) # legacy ABS had another JSON string always-be-scheduling/pull/306
219
+ else
220
+ res_body['aws_platforms']
221
+ end
222
222
  end
223
223
  end
224
224
 
@@ -228,7 +228,7 @@ class ABS
228
228
  end
229
229
 
230
230
  # Retrieve an OS from ABS.
231
- def self.retrieve(verbose, os_types, token, url, user, config, _ondemand = nil)
231
+ def self.retrieve(verbose, os_types, token, url, user, config, _ondemand = nil, continue = nil)
232
232
  #
233
233
  # Contents of post must be like:
234
234
  #
@@ -248,15 +248,20 @@ class ABS
248
248
  conn = Http.get_conn(verbose, supported_abs_url(url))
249
249
  conn.headers['X-AUTH-TOKEN'] = token if token
250
250
 
251
- saved_job_id = user + "-" + DateTime.now.strftime('%Q')
251
+ saved_job_id = if continue.nil?
252
+ "#{user}-#{DateTime.now.strftime('%Q')}"
253
+ else
254
+ continue
255
+ end
256
+
252
257
  req_obj = {
253
- :resources => os_types,
254
- :job => {
255
- :id => saved_job_id,
256
- :tags => {
257
- :user => user,
258
- },
259
- },
258
+ resources: os_types,
259
+ job: {
260
+ id: saved_job_id,
261
+ tags: {
262
+ user: user
263
+ }
264
+ }
260
265
  }
261
266
 
262
267
  if config['vmpooler_fallback'] # optional and not available as cli flag
@@ -266,11 +271,12 @@ class ABS
266
271
  end
267
272
 
268
273
  if config['priority']
269
- req_obj[:priority] = if config['priority'] == 'high'
274
+ req_obj[:priority] = case config['priority']
275
+ when 'high'
270
276
  1
271
- elsif config['priority'] == 'medium'
277
+ when 'medium'
272
278
  2
273
- elsif config['priority'] == 'low'
279
+ when 'low'
274
280
  3
275
281
  else
276
282
  config['priority'].to_i
@@ -281,26 +287,26 @@ class ABS
281
287
 
282
288
  # os_string = os_type.map { |os, num| Array(os) * num }.flatten.join('+')
283
289
  # raise MissingParamError, 'No operating systems provided to obtain.' if os_string.empty?
284
- FloatyLogger.info "Requesting VMs with job_id: #{saved_job_id}. Will retry for up to an hour."
290
+ FloatyLogger.info "Requesting VMs with job_id: #{saved_job_id} Will retry for up to an hour."
285
291
  res = conn.post 'request', req_obj.to_json
286
292
 
287
293
  retries = 360
288
294
 
289
- validate_queue_status_response(res.status, res.body, "Initial request", verbose)
295
+ status = validate_queue_status_response(res.status, res.body, 'Initial request', verbose)
290
296
 
291
297
  begin
292
298
  (1..retries).each do |i|
293
- queue_place, res_body = check_queue(conn, saved_job_id, req_obj, verbose)
294
- return translated(res_body, saved_job_id) if res_body
299
+ res_body = check_queue(conn, saved_job_id, req_obj, verbose)
300
+ return translated(res_body, saved_job_id) if res_body.is_a?(Array) # when we get a response with hostnames
295
301
 
296
302
  sleep_seconds = 10 if i >= 10
297
303
  sleep_seconds = i if i < 10
298
- FloatyLogger.info "Waiting #{sleep_seconds} seconds to check if ABS request has been filled. Queue Position: #{queue_place}... (x#{i})"
304
+ FloatyLogger.info "Waiting #{sleep_seconds}s (x#{i}) #{res_body.strip}"
299
305
 
300
306
  sleep(sleep_seconds)
301
307
  end
302
308
  rescue SystemExit, Interrupt
303
- FloatyLogger.info "\n\nFloaty interrupted, you can query the state of your request via\n1) `floaty query #{saved_job_id}` or delete it via\n2) `floaty delete #{saved_job_id}`"
309
+ FloatyLogger.info "\n\nFloaty interrupted, you can resume polling with\n1) `floaty get [same arguments] and adding the flag --continue #{saved_job_id}` or query the state of the queue via\n2) `floaty query #{saved_job_id}` or delete it via\n3) `floaty delete #{saved_job_id}`"
304
310
  exit 1
305
311
  end
306
312
  nil
@@ -310,10 +316,10 @@ class ABS
310
316
  # We should fix the ABS API to be more like the vmpooler or nspooler api, but for now
311
317
  #
312
318
  def self.translated(res_body, job_id)
313
- vmpooler_formatted_body = {'job_id' => job_id}
319
+ vmpooler_formatted_body = { 'job_id' => job_id }
314
320
 
315
321
  res_body.each do |host|
316
- if vmpooler_formatted_body[host['type']] && vmpooler_formatted_body[host['type']]['hostname'].class == Array
322
+ if vmpooler_formatted_body[host['type']] && vmpooler_formatted_body[host['type']]['hostname'].instance_of?(Array)
317
323
  vmpooler_formatted_body[host['type']]['hostname'] << host['hostname']
318
324
  else
319
325
  vmpooler_formatted_body[host['type']] = { 'hostname' => [host['hostname']] }
@@ -324,23 +330,14 @@ class ABS
324
330
  vmpooler_formatted_body
325
331
  end
326
332
 
327
- def self.check_queue(conn, job_id, req_obj, verbose)
328
- queue_info_res = conn.get "status/queue/info/#{job_id}"
329
- if valid_json?(queue_info_res.body)
330
- queue_info = JSON.parse(queue_info_res.body)
331
- else
332
- FloatyLogger.warn "Could not parse the status/queue/info/#{job_id}"
333
- return [nil, nil]
334
- end
335
-
333
+ def self.check_queue(conn, _job_id, req_obj, verbose)
336
334
  res = conn.post 'request', req_obj.to_json
337
- validate_queue_status_response(res.status, res.body, "Check queue request", verbose)
338
-
335
+ status = validate_queue_status_response(res.status, res.body, 'Check queue request', verbose)
339
336
  unless res.body.empty? || !valid_json?(res.body)
340
337
  res_body = JSON.parse(res.body)
341
- return queue_info['queue_place'], res_body
338
+ return res_body
342
339
  end
343
- [queue_info['queue_place'], nil]
340
+ res.body
344
341
  end
345
342
 
346
343
  def self.snapshot(_verbose, _url, _hostname, _token)
@@ -355,7 +352,7 @@ class ABS
355
352
  res.body == 'OK'
356
353
  end
357
354
 
358
- def self.summary(verbose, url)
355
+ def self.summary(_verbose, _url)
359
356
  raise NoMethodError, 'summary is not defined for ABS'
360
357
  end
361
358
 
@@ -407,17 +404,17 @@ class ABS
407
404
 
408
405
  def self.valid_json?(json)
409
406
  JSON.parse(json)
410
- return true
407
+ true
411
408
  rescue TypeError, JSON::ParserError => e
412
- return false
409
+ false
413
410
  end
414
411
 
415
412
  # when missing, adds the required api/v2 in the url
416
413
  def self.supported_abs_url(url)
417
- expected_ending = "api/v2"
418
- if !url.include?(expected_ending)
414
+ expected_ending = 'api/v2'
415
+ unless url.include?(expected_ending)
419
416
  # add a slash if missing
420
- expected_ending = "/#{expected_ending}" if url[-1] != "/"
417
+ expected_ending = "/#{expected_ending}" if url[-1] != '/'
421
418
  url = "#{url}#{expected_ending}"
422
419
  end
423
420
  url
data/lib/vmfloaty/http.rb CHANGED
@@ -21,13 +21,11 @@ class Http
21
21
 
22
22
  url = "https://#{url}" unless url?(url)
23
23
 
24
- conn = Faraday.new(:url => url, :ssl => { :verify => false }) do |faraday|
24
+ Faraday.new(url: url, ssl: { verify: false }) do |faraday|
25
25
  faraday.request :url_encoded
26
26
  faraday.response :logger if verbose
27
27
  faraday.adapter Faraday.default_adapter
28
28
  end
29
-
30
- conn
31
29
  end
32
30
 
33
31
  def self.get_conn_with_auth(verbose, url, user, password)
@@ -37,13 +35,11 @@ class Http
37
35
 
38
36
  url = "https://#{url}" unless url?(url)
39
37
 
40
- conn = Faraday.new(:url => url, :ssl => { :verify => false }) do |faraday|
38
+ Faraday.new(url: url, ssl: { verify: false }) do |faraday|
41
39
  faraday.request :url_encoded
42
40
  faraday.request :basic_auth, user, password
43
41
  faraday.response :logger if verbose
44
42
  faraday.adapter Faraday.default_adapter
45
43
  end
46
-
47
- conn
48
44
  end
49
45
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'logger'
2
4
 
3
5
  class FloatyLogger < ::Logger
@@ -17,11 +19,25 @@ class FloatyLogger < ::Logger
17
19
  FloatyLogger.logger.error msg
18
20
  end
19
21
 
22
+ def self.setlevel=(level)
23
+ level = level.downcase
24
+ case level
25
+ when 'debug'
26
+ logger.level = ::Logger::DEBUG
27
+ when 'info'
28
+ logger.level = ::Logger::INFO
29
+ when 'error'
30
+ logger.level = ::Logger::ERROR
31
+ else
32
+ error('set loglevel to debug, info or error')
33
+ end
34
+ end
35
+
20
36
  def initialize
21
- super(STDERR)
37
+ super($stderr)
22
38
  self.level = ::Logger::INFO
23
- self.formatter = proc do |severity, datetime, progname, msg|
24
- "#{msg}\n"
39
+ self.formatter = proc do |_severity, _datetime, _progname, msg|
40
+ "#{msg}\n"
25
41
  end
26
42
  end
27
43
  end
@@ -22,7 +22,7 @@ class NonstandardPooler
22
22
  status['reserved_hosts'] || []
23
23
  end
24
24
 
25
- def self.retrieve(verbose, os_type, token, url, _user, _options, ondemand = nil)
25
+ def self.retrieve(verbose, os_type, token, url, _user, _options, _ondemand = nil, _continue = nil)
26
26
  conn = Http.get_conn(verbose, url)
27
27
  conn.headers['X-AUTH-TOKEN'] = token if token
28
28
 
@@ -46,7 +46,8 @@ class NonstandardPooler
46
46
  raise TokenError, 'Token provided was nil; Request cannot be made to modify VM' if token.nil?
47
47
 
48
48
  modify_hash.each do |key, _value|
49
- raise ModifyError, "Configured service type does not support modification of #{key}" unless %i[reason reserved_for_reason].include? key
49
+ raise ModifyError, "Configured service type does not support modification of #{key}" unless %i[reason
50
+ reserved_for_reason].include? key
50
51
  end
51
52
 
52
53
  if modify_hash[:reason]
@@ -12,13 +12,11 @@ class Pooler
12
12
  response = conn.get 'vm'
13
13
  response_body = JSON.parse(response.body)
14
14
 
15
- hosts = if os_filter
16
- response_body.select { |i| i[/#{os_filter}/] }
17
- else
18
- response_body
19
- end
20
-
21
- hosts
15
+ if os_filter
16
+ response_body.select { |i| i[/#{os_filter}/] }
17
+ else
18
+ response_body
19
+ end
22
20
  end
23
21
 
24
22
  def self.list_active(verbose, url, token, _user)
@@ -28,7 +26,7 @@ class Pooler
28
26
  vms
29
27
  end
30
28
 
31
- def self.retrieve(verbose, os_type, token, url, _user, _options, ondemand = nil)
29
+ def self.retrieve(verbose, os_type, token, url, _user, _options, ondemand = nil, _continue = nil)
32
30
  # NOTE:
33
31
  # Developers can use `Utils.generate_os_hash` to
34
32
  # generate the os_type param.
@@ -50,7 +48,10 @@ class Pooler
50
48
  elsif response.status == 403
51
49
  raise "HTTP #{response.status}: Failed to obtain VMs from the pooler at #{url}/vm/#{os_string}. Request exceeds the configured per pool maximum. #{res_body}"
52
50
  else
53
- raise "HTTP #{response.status}: Failed to obtain VMs from the pooler at #{url}/vm/#{os_string}. #{res_body}" unless ondemand
51
+ unless ondemand
52
+ raise "HTTP #{response.status}: Failed to obtain VMs from the pooler at #{url}/vm/#{os_string}. #{res_body}"
53
+ end
54
+
54
55
  raise "HTTP #{response.status}: Failed to obtain VMs from the pooler at #{url}/ondemandvm/#{os_string}. #{res_body}"
55
56
  end
56
57
  end
@@ -63,7 +64,7 @@ class Pooler
63
64
  FloatyLogger.info "waiting for request #{request_id} to be fulfilled"
64
65
  sleep 5
65
66
  end
66
- FloatyLogger.info "The request has been fulfilled"
67
+ FloatyLogger.info 'The request has been fulfilled'
67
68
  check_ondemandvm(verbose, request_id, url)
68
69
  end
69
70
 
@@ -84,8 +85,9 @@ class Pooler
84
85
  def self.modify(verbose, url, hostname, token, modify_hash)
85
86
  raise TokenError, 'Token provided was nil. Request cannot be made to modify vm' if token.nil?
86
87
 
87
- modify_hash.keys.each do |key|
88
- raise ModifyError, "Configured service type does not support modification of #{key}." unless %i[tags lifetime disk].include? key
88
+ modify_hash.each_key do |key|
89
+ raise ModifyError, "Configured service type does not support modification of #{key}." unless %i[tags lifetime
90
+ disk].include? key
89
91
  end
90
92
 
91
93
  conn = Http.get_conn(verbose, url)
@@ -120,8 +122,7 @@ class Pooler
120
122
 
121
123
  response = conn.post "vm/#{hostname}/disk/#{disk}"
122
124
 
123
- res_body = JSON.parse(response.body)
124
- res_body
125
+ JSON.parse(response.body)
125
126
  end
126
127
 
127
128
  def self.delete(verbose, url, hosts, token, _user)
@@ -146,25 +147,21 @@ class Pooler
146
147
  conn = Http.get_conn(verbose, url)
147
148
 
148
149
  response = conn.get '/status'
149
- res_body = JSON.parse(response.body)
150
- res_body
150
+ JSON.parse(response.body)
151
151
  end
152
152
 
153
153
  def self.summary(verbose, url)
154
154
  conn = Http.get_conn(verbose, url)
155
155
 
156
156
  response = conn.get '/summary'
157
- res_body = JSON.parse(response.body)
158
- res_body
157
+ JSON.parse(response.body)
159
158
  end
160
159
 
161
160
  def self.query(verbose, url, hostname)
162
161
  conn = Http.get_conn(verbose, url)
163
162
 
164
163
  response = conn.get "vm/#{hostname}"
165
- res_body = JSON.parse(response.body)
166
-
167
- res_body
164
+ JSON.parse(response.body)
168
165
  end
169
166
 
170
167
  def self.snapshot(verbose, url, hostname, token)
@@ -174,8 +171,7 @@ class Pooler
174
171
  conn.headers['X-AUTH-TOKEN'] = token
175
172
 
176
173
  response = conn.post "vm/#{hostname}/snapshot"
177
- res_body = JSON.parse(response.body)
178
- res_body
174
+ JSON.parse(response.body)
179
175
  end
180
176
 
181
177
  def self.revert(verbose, url, hostname, token, snapshot_sha)
@@ -187,7 +183,6 @@ class Pooler
187
183
  raise "Snapshot SHA provided was nil, could not revert #{hostname}" if snapshot_sha.nil?
188
184
 
189
185
  response = conn.post "vm/#{hostname}/snapshot/#{snapshot_sha}"
190
- res_body = JSON.parse(response.body)
191
- res_body
186
+ JSON.parse(response.body)
192
187
  end
193
188
  end
@@ -39,7 +39,7 @@ class Service
39
39
  def user
40
40
  unless @config['user']
41
41
  FloatyLogger.info "Enter your #{@config['url']} service username:"
42
- @config['user'] = STDIN.gets.chomp
42
+ @config['user'] = $stdin.gets.chomp
43
43
  end
44
44
  @config['user']
45
45
  end
@@ -77,10 +77,10 @@ class Service
77
77
  @service_object.list_active verbose, url, token, user
78
78
  end
79
79
 
80
- def retrieve(verbose, os_types, use_token = true, ondemand = nil)
80
+ def retrieve(verbose, os_types, use_token = true, ondemand = nil, continue = nil)
81
81
  FloatyLogger.info 'Requesting a vm without a token...' unless use_token
82
82
  token_value = use_token ? token : nil
83
- @service_object.retrieve verbose, os_types, token_value, url, user, @config, ondemand
83
+ @service_object.retrieve verbose, os_types, token_value, url, user, @config, ondemand, continue
84
84
  end
85
85
 
86
86
  def wait_for_request(verbose, requestid)
@@ -140,8 +140,8 @@ class Service
140
140
  # some methods do not exist for ABS, and if possible should target the Pooler service
141
141
  def maybe_use_vmpooler
142
142
  if @service_object == ABS # this is not an instance
143
- if !self.silent
144
- FloatyLogger.info "The service in use is ABS, but the requested method should run against vmpooler directly, using fallback_vmpooler config from ~/.vmfloaty.yml"
143
+ unless silent
144
+ FloatyLogger.info 'The service in use is ABS, but the requested method should run against vmpooler directly, using fallback_vmpooler config from ~/.vmfloaty.yml'
145
145
  self.silent = true
146
146
  end
147
147