vmfloaty 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4cf673c0a3e005fc4ef5102d232206f3105215de4f19cd76725de335b62937fd
4
- data.tar.gz: e4791593e75d31d42a8f05cfb28b3655e42218ac1a7191ae1c8391ccdad5133b
3
+ metadata.gz: cfd72279e6067194457cfff7e798bffb6c3f7e516a215ab25507836a35918dfa
4
+ data.tar.gz: e5f63b9b99f8969e557cf14993d89063353b2b8d2201e2945204375f4c8599f1
5
5
  SHA512:
6
- metadata.gz: b22ad1332f3a663407a6ce964525606938134925e0b91ccd151a8f9a4abc265cab53cddd9509ce92555abb357dc213f2beef50a02ea72eb501db31c9e3936983
7
- data.tar.gz: 8436c38cc6a99b76c4e65da0dfa653edbbdbe9b7fcefb9607942983cd24014c40ab14f556b06e7d6a449dc57f84740e09df2668e15129cdb5dccbb3b6e746eff
6
+ metadata.gz: 57500a3436d64a3edc4aa8a11bcfc5590a05788268fb7c556d70816a0dede112225298f657a762c8a5eec3b829117f91599e286115237e5e039dfe5554d9d2c2
7
+ data.tar.gz: 288ded1bca5cfe6bff06be880b17264ddd49a10674649a1424515af7a48d646eb0b693123aee0ec353b6bb57424f209ca7cd653e1fd3287831b137593ebfe50b
@@ -2,29 +2,37 @@
2
2
 
3
3
  _vmfloaty()
4
4
  {
5
- local cur prev subcommands template_subcommands hostname_subcommands
5
+ local cur prev commands template_arg_commands hostname_arg_commands service_subcommands
6
+
6
7
  COMPREPLY=()
7
8
  cur="${COMP_WORDS[COMP_CWORD]}"
8
9
  prev="${COMP_WORDS[COMP_CWORD-1]}"
9
10
 
10
- subcommands="delete get help list modify query revert service snapshot ssh status summary token"
11
- template_subcommands="get ssh"
12
- hostname_subcommands="delete modify query revert snapshot"
11
+ commands="delete get help list modify query revert service snapshot ssh status summary token"
12
+ template_arg_commands="get ssh"
13
+ hostname_arg_commands="delete modify query revert snapshot"
14
+ service_subcommands="types examples"
13
15
 
14
16
  if [[ $cur == -* ]] ; then
15
17
  # TODO: option completion
16
18
  COMPREPLY=()
17
- elif [[ $template_subcommands =~ (^| )$prev($| ) ]] ; then
19
+ elif [[ $template_arg_commands =~ (^| )$prev($| ) ]] ; then
18
20
  if [[ -z "$_vmfloaty_avail_templates" ]] ; then
21
+ # TODO: need a --hostnameonly equivalent here because the section headers of
22
+ # `floaty list` are adding some spurious entries (including files in current
23
+ # directory because part of the headers is `**` which is getting expanded)
19
24
  _vmfloaty_avail_templates=$(floaty list 2>/dev/null)
20
25
  fi
21
26
 
22
27
  COMPREPLY=( $(compgen -W "${_vmfloaty_avail_templates}" -- "${cur}") )
23
- elif [[ $hostname_subcommands =~ (^| )$prev($| ) ]] ; then
28
+ elif [[ $hostname_arg_commands =~ (^| )$prev($| ) ]] ; then
24
29
  _vmfloaty_active_hostnames=$(floaty list --active --hostnameonly 2>/dev/null)
25
30
  COMPREPLY=( $(compgen -W "${_vmfloaty_active_hostnames}" -- "${cur}") )
26
- else
27
- COMPREPLY=( $(compgen -W "${subcommands}" -- "${cur}") )
31
+ elif [[ "service" == $prev ]] ; then
32
+ COMPREPLY=( $(compgen -W "${service_subcommands}" -- "${cur}") )
33
+ elif [[ $1 == $prev ]] ; then
34
+ # only show top level commands we are at root
35
+ COMPREPLY=( $(compgen -W "${commands}" -- "${cur}") )
28
36
  fi
29
37
  }
30
38
  complete -F _vmfloaty floaty
@@ -1,26 +1,32 @@
1
1
  _floaty()
2
2
  {
3
- local line subcommands template_subcommands hostname_subcommands
3
+ local line commands template_arg_commands hostname_arg_commands service_subcommands
4
4
 
5
- subcommands="delete get help list modify query revert snapshot ssh status summary token"
5
+ commands="delete get help list modify query revert service snapshot ssh status summary token"
6
6
 
7
- template_subcommands=("get" "ssh")
8
- hostname_subcommands=("delete" "modify" "query" "revert" "snapshot")
7
+ template_arg_commands=("get" "ssh")
8
+ hostname_arg_commands=("delete" "modify" "query" "revert" "snapshot")
9
+ service_subcommands=("types" "examples")
9
10
 
10
11
  _arguments -C \
11
- "1: :(${subcommands})" \
12
+ "1: :(${commands})" \
12
13
  "*::arg:->args"
13
14
 
14
- if ((template_subcommands[(Ie)$line[1]])); then
15
+ if ((template_arg_commands[(Ie)$line[1]])); then
15
16
  _floaty_template_sub
16
- elif ((hostname_subcommands[(Ie)$line[1]])); then
17
+ elif ((hostname_arg_commands[(Ie)$line[1]])); then
17
18
  _floaty_hostname_sub
19
+ elif [[ "service" == $line[1] ]]; then
20
+ _arguments "1: :(${service_subcommands})"
18
21
  fi
19
22
  }
20
23
 
21
24
  _floaty_template_sub()
22
25
  {
23
26
  if [[ -z "$_vmfloaty_avail_templates" ]] ; then
27
+ # TODO: need a --hostnameonly equivalent here because the section headers of
28
+ # `floaty list` are adding some spurious entries (including files in current
29
+ # directory because part of the headers is `**` which is getting expanded)
24
30
  _vmfloaty_avail_templates=$(floaty list 2>/dev/null)
25
31
  fi
26
32
 
@@ -64,7 +64,7 @@ class ABS
64
64
  end
65
65
 
66
66
  def self.get_active_requests(verbose, url, user)
67
- conn = Http.get_conn(verbose, url)
67
+ conn = Http.get_conn(verbose, supported_abs_url(url))
68
68
  res = conn.get 'status/queue'
69
69
  if valid_json?(res.body)
70
70
  requests = JSON.parse(res.body)
@@ -105,7 +105,7 @@ class ABS
105
105
 
106
106
  def self.delete(verbose, url, hosts, token, user)
107
107
  # In ABS terms, this is a "returned" host.
108
- conn = Http.get_conn(verbose, url)
108
+ conn = Http.get_conn(verbose, supported_abs_url(url))
109
109
  conn.headers['X-AUTH-TOKEN'] = token if token
110
110
 
111
111
  FloatyLogger.info "Trying to delete hosts #{hosts}" if verbose
@@ -163,7 +163,7 @@ class ABS
163
163
 
164
164
  # List available VMs in ABS
165
165
  def self.list(verbose, url, os_filter = nil)
166
- conn = Http.get_conn(verbose, url)
166
+ conn = Http.get_conn(verbose, supported_abs_url(url))
167
167
 
168
168
  os_list = []
169
169
 
@@ -245,11 +245,10 @@ class ABS
245
245
  # }
246
246
  # }
247
247
 
248
- conn = Http.get_conn(verbose, url)
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 = DateTime.now.strftime('%Q')
252
- vmpooler_config = Utils.get_vmpooler_service_config(config['vmpooler_fallback'])
251
+ saved_job_id = user + "-" + DateTime.now.strftime('%Q')
253
252
  req_obj = {
254
253
  :resources => os_types,
255
254
  :job => {
@@ -258,9 +257,14 @@ class ABS
258
257
  :user => user,
259
258
  },
260
259
  },
261
- :vm_token => vmpooler_config['token'] # request with this token, on behalf of this user
262
260
  }
263
261
 
262
+ if config['vmpooler_fallback'] # optional and not available as cli flag
263
+ vmpooler_config = Utils.get_vmpooler_service_config(config['vmpooler_fallback'])
264
+ # request with this token, on behalf of this user
265
+ req_obj[:vm_token] = vmpooler_config['token']
266
+ end
267
+
264
268
  if config['priority']
265
269
  req_obj[:priority] = if config['priority'] == 'high'
266
270
  1
@@ -284,15 +288,20 @@ class ABS
284
288
 
285
289
  validate_queue_status_response(res.status, res.body, "Initial request", verbose)
286
290
 
287
- (1..retries).each do |i|
288
- queue_place, res_body = check_queue(conn, saved_job_id, req_obj, verbose)
289
- return translated(res_body, saved_job_id) if res_body
291
+ begin
292
+ (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
290
295
 
291
- sleep_seconds = 10 if i >= 10
292
- sleep_seconds = i if i < 10
293
- FloatyLogger.info "Waiting #{sleep_seconds} seconds to check if ABS request has been filled. Queue Position: #{queue_place}... (x#{i})"
296
+ sleep_seconds = 10 if i >= 10
297
+ 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})"
294
299
 
295
- sleep(sleep_seconds)
300
+ sleep(sleep_seconds)
301
+ end
302
+ 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}`"
304
+ exit 1
296
305
  end
297
306
  nil
298
307
  end
@@ -339,7 +348,7 @@ class ABS
339
348
  end
340
349
 
341
350
  def self.status(verbose, url)
342
- conn = Http.get_conn(verbose, url)
351
+ conn = Http.get_conn(verbose, supported_abs_url(url))
343
352
 
344
353
  res = conn.get 'status'
345
354
 
@@ -357,7 +366,7 @@ class ABS
357
366
  return @active_hostnames if @active_hostnames && !@active_hostnames.empty?
358
367
 
359
368
  # If using the cli query job_id
360
- conn = Http.get_conn(verbose, url)
369
+ conn = Http.get_conn(verbose, supported_abs_url(url))
361
370
  queue_info_res = conn.get "status/queue/info/#{job_id}"
362
371
  if valid_json?(queue_info_res.body)
363
372
  queue_info = JSON.parse(queue_info_res.body)
@@ -402,4 +411,15 @@ class ABS
402
411
  rescue TypeError, JSON::ParserError => e
403
412
  return false
404
413
  end
414
+
415
+ # when missing, adds the required api/v2 in the url
416
+ def self.supported_abs_url(url)
417
+ expected_ending = "api/v2"
418
+ if !url.include?(expected_ending)
419
+ # add a slash if missing
420
+ expected_ending = "/#{expected_ending}" if url[-1] != "/"
421
+ url = "#{url}#{expected_ending}"
422
+ end
423
+ url
424
+ end
405
425
  end
@@ -139,7 +139,7 @@ class Service
139
139
 
140
140
  # some methods do not exist for ABS, and if possible should target the Pooler service
141
141
  def maybe_use_vmpooler
142
- if @service_object.is_a?(ABS.class)
142
+ if @service_object == ABS # this is not an instance
143
143
  if !self.silent
144
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
@@ -116,7 +116,7 @@ class Utils
116
116
 
117
117
  output_target.puts "- [JobID:#{host_data['request']['job']['id']}] <#{host_data['state']}>"
118
118
  host_data['allocated_resources'].each do |allocated_resources, _i|
119
- if allocated_resources['engine'] == "vmpooler"
119
+ if allocated_resources['engine'] == "vmpooler" && service.config["vmpooler_fallback"]
120
120
  vmpooler_service = service.clone
121
121
  vmpooler_service.silent = true
122
122
  vmpooler_service.maybe_use_vmpooler
@@ -254,6 +254,7 @@ class Utils
254
254
  'url' => config['url'],
255
255
  'user' => config['user'],
256
256
  'token' => config['token'],
257
+ 'vmpooler_fallback' => config['vmpooler_fallback'],
257
258
  'type' => config['type'] || 'vmpooler',
258
259
  }
259
260
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Vmfloaty
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.1'
5
5
  end
6
6
 
@@ -11,11 +11,11 @@ describe ABS do
11
11
 
12
12
  describe '#list' do
13
13
  it 'skips empty platforms and lists aws' do
14
- stub_request(:get, "http://foo/status/platforms/vmpooler").
14
+ stub_request(:get, "http://foo/api/v2/status/platforms/vmpooler").
15
15
  to_return(:status => 200, :body => "", :headers => {})
16
- stub_request(:get, "http://foo/status/platforms/ondemand_vmpooler").
16
+ stub_request(:get, "http://foo/api/v2/status/platforms/ondemand_vmpooler").
17
17
  to_return(:status => 200, :body => "", :headers => {})
18
- stub_request(:get, "http://foo/status/platforms/nspooler").
18
+ stub_request(:get, "http://foo/api/v2/status/platforms/nspooler").
19
19
  to_return(:status => 200, :body => "", :headers => {})
20
20
  body = '{
21
21
  "aws_platforms": [
@@ -26,7 +26,7 @@ describe ABS do
26
26
  "redhat-8-arm64"
27
27
  ]
28
28
  }'
29
- stub_request(:get, "http://foo/status/platforms/aws").
29
+ stub_request(:get, "http://foo/api/v2/status/platforms/aws").
30
30
  to_return(:status => 200, :body => body, :headers => {})
31
31
 
32
32
 
@@ -35,16 +35,16 @@ describe ABS do
35
35
  expect(results).to include("amazon-6-x86_64", "amazon-7-x86_64", "amazon-7-arm64", "centos-7-x86-64-west", "redhat-8-arm64")
36
36
  end
37
37
  it 'legacy JSON string, prior to PR 306' do
38
- stub_request(:get, "http://foo/status/platforms/vmpooler").
38
+ stub_request(:get, "http://foo/api/v2/status/platforms/vmpooler").
39
39
  to_return(:status => 200, :body => "", :headers => {})
40
- stub_request(:get, "http://foo/status/platforms/ondemand_vmpooler").
40
+ stub_request(:get, "http://foo/api/v2/status/platforms/ondemand_vmpooler").
41
41
  to_return(:status => 200, :body => "", :headers => {})
42
- stub_request(:get, "http://foo/status/platforms/nspooler").
42
+ stub_request(:get, "http://foo/api/v2/status/platforms/nspooler").
43
43
  to_return(:status => 200, :body => "", :headers => {})
44
44
  body = '{
45
45
  "aws_platforms": "[\"amazon-6-x86_64\",\"amazon-7-x86_64\",\"amazon-7-arm64\",\"centos-7-x86-64-west\",\"redhat-8-arm64\"]"
46
46
  }'
47
- stub_request(:get, "http://foo/status/platforms/aws").
47
+ stub_request(:get, "http://foo/api/v2/status/platforms/aws").
48
48
  to_return(:status => 200, :body => body, :headers => {})
49
49
 
50
50
  results = ABS.list(false, "http://foo")
@@ -125,7 +125,7 @@ describe ABS do
125
125
  end
126
126
 
127
127
  it 'will skip a line with a null value returned from abs' do
128
- stub_request(:get, 'https://abs.example.com/status/queue')
128
+ stub_request(:get, 'https://abs.example.com/api/v2/status/queue')
129
129
  .to_return(:status => 200, :body => @active_requests_response, :headers => {})
130
130
 
131
131
  ret = ABS.get_active_requests(false, @abs_url, @test_user)
@@ -156,9 +156,9 @@ describe ABS do
156
156
  end
157
157
 
158
158
  it 'will delete the whole job' do
159
- stub_request(:get, 'https://abs.example.com/status/queue')
159
+ stub_request(:get, 'https://abs.example.com/api/v2/status/queue')
160
160
  .to_return(:status => 200, :body => @active_requests_response, :headers => {})
161
- stub_request(:post, 'https://abs.example.com/return')
161
+ stub_request(:post, 'https://abs.example.com/api/v2/return')
162
162
  .with(:body => @return_request)
163
163
  .to_return(:status => 200, :body => 'OK', :headers => {})
164
164
 
@@ -5,6 +5,11 @@ require 'json'
5
5
  require 'commander/command'
6
6
  require_relative '../../lib/vmfloaty/utils'
7
7
 
8
+ # allow changing config in service for tests
9
+ class Service
10
+ attr_writer :config
11
+ end
12
+
8
13
  describe Utils do
9
14
  describe '#standardize_hostnames' do
10
15
  before :each do
@@ -441,7 +446,7 @@ describe Utils do
441
446
  end
442
447
 
443
448
  let(:default_output_first_line) { "- [JobID:#{hostname}] <allocated>" }
444
- let(:default_output_second_line) { " - #{fqdn} (#{template}, 7.67/48 hours, user: bob, role: agent)" }
449
+ let(:default_output_second_line) { " - #{fqdn} (#{template})" }
445
450
 
446
451
  it 'prints output with job id, host, and template' do
447
452
  expect(STDOUT).to receive(:puts).with(default_output_first_line)
@@ -450,6 +455,16 @@ describe Utils do
450
455
  subject
451
456
  end
452
457
 
458
+ it 'prints more information when vmpooler_fallback is set output with job id, host, template, lifetime, user and role' do
459
+ fallback = {'vmpooler_fallback' => 'vmpooler'}
460
+ service.config.merge! fallback
461
+ default_output_second_line=" - #{fqdn} (#{template}, 7.67/48 hours, user: bob, role: agent)"
462
+ expect(STDOUT).to receive(:puts).with(default_output_first_line)
463
+ expect(STDOUT).to receive(:puts).with(default_output_second_line)
464
+
465
+ subject
466
+ end
467
+
453
468
  context 'when print_to_stderr option is true' do
454
469
  let(:print_to_stderr) { true }
455
470
 
@@ -529,7 +544,7 @@ describe Utils do
529
544
  end
530
545
 
531
546
  let(:default_output_first_line) { "- [JobID:#{hostname}] <allocated>" }
532
- let(:default_output_second_line) { " - #{fqdn} (#{template}, 7.67/48 hours, user: bob, role: agent)" }
547
+ let(:default_output_second_line) { " - #{fqdn} (#{template})" }
533
548
  let(:default_output_third_line) { " - #{fqdn_ns} (#{template_ns})" }
534
549
 
535
550
  it 'prints output with job id, host, and template' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vmfloaty
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Cain
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-09-22 00:00:00.000000000 Z
12
+ date: 2020-10-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: colorize
@@ -115,18 +115,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
115
  - !ruby/object:Gem::Version
116
116
  version: '0'
117
117
  requirements: []
118
- rubygems_version: 3.0.3
118
+ rubygems_version: 3.1.2
119
119
  signing_key:
120
120
  specification_version: 4
121
121
  summary: CLI application to interface with vmpooler
122
122
  test_files:
123
- - spec/spec_helper.rb
123
+ - spec/vmfloaty/vmfloaty_services_spec.rb
124
+ - spec/vmfloaty/utils_spec.rb
125
+ - spec/vmfloaty/abs/auth_spec.rb
126
+ - spec/vmfloaty/abs_spec.rb
127
+ - spec/vmfloaty/pooler_spec.rb
124
128
  - spec/vmfloaty/ssh_spec.rb
125
- - spec/vmfloaty/auth_spec.rb
126
129
  - spec/vmfloaty/service_spec.rb
127
- - spec/vmfloaty/abs/auth_spec.rb
128
130
  - spec/vmfloaty/nonstandard_pooler_spec.rb
129
- - spec/vmfloaty/pooler_spec.rb
130
- - spec/vmfloaty/abs_spec.rb
131
- - spec/vmfloaty/utils_spec.rb
132
- - spec/vmfloaty/vmfloaty_services_spec.rb
131
+ - spec/vmfloaty/auth_spec.rb
132
+ - spec/spec_helper.rb