vmfloaty 0.9.2 → 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.
@@ -84,6 +84,26 @@ describe Pooler do
84
84
  expect(vm_req['debian-7-i386']['hostname']).to eq %w[sc0o4xqtodlul5w 4m4dkhqiufnjmxy]
85
85
  expect(vm_req['centos-7-x86_64']['hostname']).to eq 'zb91y9qbrbf6d3q'
86
86
  end
87
+
88
+ context 'with ondemand provisioning' do
89
+ let(:ondemand_response) { '{"ok":true,"request_id":"1234"}' }
90
+ it 'retreives the vm with a token' do
91
+ stub_request(:post, "#{@vmpooler_url}/ondemandvm/debian-7-i386")
92
+ .with(:headers => { 'X-Auth-Token' => 'mytokenfile' })
93
+ .to_return(:status => 200, :body => ondemand_response, :headers => {})
94
+
95
+ stub_request(:get, "#{@vmpooler_url}/ondemandvm/1234")
96
+ .to_return(:status => 200, :body => @retrieve_response_body_single, :headers => {})
97
+
98
+ vm_hash = {}
99
+ vm_hash['debian-7-i386'] = 1
100
+ Pooler.retrieve(false, vm_hash, 'mytokenfile', @vmpooler_url, 'user', {}, true)
101
+ vm_req = Pooler.check_ondemandvm(false, '1234', @vmpooler_url)
102
+ expect(vm_req).to be_an_instance_of Hash
103
+ expect(vm_req['ok']).to equal true
104
+ expect(vm_req['debian-7-i386']['hostname']).to eq 'fq6qlpjlsskycq6'
105
+ end
106
+ end
87
107
  end
88
108
 
89
109
  describe '#modify' do
@@ -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
@@ -77,9 +82,17 @@ describe Utils do
77
82
  expect(Utils.get_service_object).to be Pooler
78
83
  end
79
84
 
85
+ it 'uses abs when told explicitly' do
86
+ expect(Utils.get_service_object('abs')).to be ABS
87
+ end
88
+
80
89
  it 'uses nspooler when told explicitly' do
81
90
  expect(Utils.get_service_object('nspooler')).to be NonstandardPooler
82
91
  end
92
+
93
+ it 'uses vmpooler when told explicitly' do
94
+ expect(Utils.get_service_object('vmpooler')).to be Pooler
95
+ end
83
96
  end
84
97
 
85
98
  describe '#get_service_config' do
@@ -154,97 +167,462 @@ describe Utils do
154
167
  end
155
168
  end
156
169
 
157
- describe '#pretty_print_hosts' do
170
+ describe '#print_fqdn_for_host' do
158
171
  let(:url) { 'http://pooler.example.com' }
159
172
 
160
- it 'prints a vmpooler output with host fqdn, template and duration info' do
161
- hostname = 'mcpy42eqjxli9g2'
162
- response_body = { hostname => {
163
- 'template' => 'ubuntu-1604-x86_64',
164
- 'lifetime' => 12,
165
- 'running' => 9.66,
166
- 'state' => 'running',
167
- 'ip' => '127.0.0.1',
168
- 'domain' => 'delivery.mycompany.net',
169
- } }
170
- output = '- mcpy42eqjxli9g2.delivery.mycompany.net (ubuntu-1604-x86_64, 9.66/12 hours)'
171
-
172
- expect(Utils).to receive(:puts).with(output)
173
-
174
- service = Service.new(MockOptions.new, 'url' => url)
175
- allow(service).to receive(:query)
176
- .with(nil, hostname)
177
- .and_return(response_body)
178
-
179
- Utils.pretty_print_hosts(nil, service, hostname)
173
+ subject { Utils.print_fqdn_for_host(service, hostname, host_data) }
174
+
175
+ describe 'with vmpooler host' do
176
+ let(:service) { Service.new(MockOptions.new, 'url' => url) }
177
+ let(:hostname) { 'mcpy42eqjxli9g2' }
178
+ let(:domain) { 'delivery.mycompany.net' }
179
+ let(:fqdn) { [hostname, domain].join('.') }
180
+
181
+ let(:host_data) do
182
+ {
183
+ 'template' => 'ubuntu-1604-x86_64',
184
+ 'lifetime' => 12,
185
+ 'running' => 9.66,
186
+ 'state' => 'running',
187
+ 'ip' => '127.0.0.1',
188
+ 'domain' => domain,
189
+ }
190
+ end
191
+
192
+ it 'outputs fqdn for host' do
193
+ expect(STDOUT).to receive(:puts).with(fqdn)
194
+
195
+ subject
196
+ end
180
197
  end
181
198
 
182
- it 'prints a vmpooler output with host fqdn, template, duration info, and tags when supplied' do
183
- hostname = 'aiydvzpg23r415q'
184
- response_body = { hostname => {
185
- 'template' => 'redhat-7-x86_64',
186
- 'lifetime' => 48,
187
- 'running' => 7.67,
188
- 'state' => 'running',
189
- 'tags' => {
190
- 'user' => 'bob',
191
- 'role' => 'agent',
192
- },
193
- 'ip' => '127.0.0.1',
194
- 'domain' => 'delivery.mycompany.net',
195
- } }
196
- output = '- aiydvzpg23r415q.delivery.mycompany.net (redhat-7-x86_64, 7.67/48 hours, user: bob, role: agent)'
199
+ describe 'with nonstandard pooler host' do
200
+ let(:service) { Service.new(MockOptions.new, 'url' => url, 'type' => 'ns') }
201
+ let(:hostname) { 'sol11-9.delivery.mycompany.net' }
202
+ let(:host_data) do
203
+ {
204
+ 'fqdn' => hostname,
205
+ 'os_triple' => 'solaris-11-sparc',
206
+ 'reserved_by_user' => 'first.last',
207
+ 'reserved_for_reason' => '',
208
+ 'hours_left_on_reservation' => 35.89,
209
+ }
210
+ end
211
+ let(:fqdn) { hostname } # for nspooler these are the same
212
+
213
+ it 'outputs fqdn for host' do
214
+ expect(STDOUT).to receive(:puts).with(fqdn)
215
+
216
+ subject
217
+ end
218
+ end
197
219
 
198
- expect(Utils).to receive(:puts).with(output)
220
+ describe 'with ABS host' do
221
+ let(:service) { Service.new(MockOptions.new, 'url' => url, 'type' => 'abs') }
222
+ let(:hostname) { '1597952189390' }
223
+ let(:fqdn) { 'example-noun.delivery.puppetlabs.net' }
224
+ let(:template) { 'ubuntu-1604-x86_64' }
225
+
226
+ # This seems to be the miminal stub response from ABS for the current output
227
+ let(:host_data) do
228
+ {
229
+ 'state' => 'allocated',
230
+ 'allocated_resources' => [
231
+ {
232
+ 'hostname' => fqdn,
233
+ 'type' => template,
234
+ 'enging' => 'vmpooler',
235
+ },
236
+ ],
237
+ 'request' => {
238
+ 'job' => {
239
+ 'id' => hostname,
240
+ }
241
+ },
242
+ }
243
+ end
199
244
 
200
- service = Service.new(MockOptions.new, 'url' => url)
201
- allow(service).to receive(:query)
202
- .with(nil, hostname)
203
- .and_return(response_body)
245
+ it 'outputs fqdn for host' do
246
+ expect(STDOUT).to receive(:puts).with(fqdn)
204
247
 
205
- Utils.pretty_print_hosts(nil, service, hostname)
248
+ subject
249
+ end
206
250
  end
251
+ end
207
252
 
208
- it 'prints a nonstandard pooler output with host, template, and time remaining' do
209
- hostname = 'sol11-9.delivery.mycompany.net'
210
- response_body = { hostname => {
211
- 'fqdn' => hostname,
212
- 'os_triple' => 'solaris-11-sparc',
213
- 'reserved_by_user' => 'first.last',
214
- 'reserved_for_reason' => '',
215
- 'hours_left_on_reservation' => 35.89,
216
- } }
217
- output = '- sol11-9.delivery.mycompany.net (solaris-11-sparc, 35.89h remaining)'
218
-
219
- expect(Utils).to receive(:puts).with(output)
253
+ describe '#pretty_print_hosts' do
254
+ let(:url) { 'http://pooler.example.com' }
255
+ let(:verbose) { nil }
256
+ let(:print_to_stderr) { false }
220
257
 
221
- service = Service.new(MockOptions.new, 'url' => url, 'type' => 'ns')
258
+ before(:each) do
222
259
  allow(service).to receive(:query)
223
- .with(nil, hostname)
260
+ .with(anything, hostname)
224
261
  .and_return(response_body)
262
+ end
225
263
 
226
- Utils.pretty_print_hosts(nil, service, hostname)
264
+ subject { Utils.pretty_print_hosts(verbose, service, hostname, print_to_stderr) }
265
+
266
+ describe 'with vmpooler service' do
267
+ let(:service) { Service.new(MockOptions.new, 'url' => url) }
268
+
269
+ let(:hostname) { 'mcpy42eqjxli9g2' }
270
+ let(:domain) { 'delivery.mycompany.net' }
271
+ let(:fqdn) { [hostname, domain].join('.') }
272
+
273
+ let(:response_body) do
274
+ {
275
+ hostname => {
276
+ 'template' => 'ubuntu-1604-x86_64',
277
+ 'lifetime' => 12,
278
+ 'running' => 9.66,
279
+ 'state' => 'running',
280
+ 'ip' => '127.0.0.1',
281
+ 'domain' => domain,
282
+ }
283
+ }
284
+ end
285
+
286
+ let(:default_output) { "- #{fqdn} (ubuntu-1604-x86_64, 9.66/12 hours)" }
287
+
288
+ it 'prints output with host fqdn, template and duration info' do
289
+ expect(STDOUT).to receive(:puts).with(default_output)
290
+
291
+ subject
292
+ end
293
+
294
+ context 'when tags are supplied' do
295
+ let(:hostname) { 'aiydvzpg23r415q' }
296
+ let(:response_body) do
297
+ {
298
+ hostname => {
299
+ 'template' => 'redhat-7-x86_64',
300
+ 'lifetime' => 48,
301
+ 'running' => 7.67,
302
+ 'state' => 'running',
303
+ 'tags' => {
304
+ 'user' => 'bob',
305
+ 'role' => 'agent',
306
+ },
307
+ 'ip' => '127.0.0.1',
308
+ 'domain' => domain,
309
+ }
310
+ }
311
+ end
312
+
313
+ it 'prints output with host fqdn, template, duration info, and tags' do
314
+ output = "- #{fqdn} (redhat-7-x86_64, 7.67/48 hours, user: bob, role: agent)"
315
+
316
+ expect(STDOUT).to receive(:puts).with(output)
317
+
318
+ subject
319
+ end
320
+ end
321
+
322
+ context 'when print_to_stderr option is true' do
323
+ let(:print_to_stderr) { true }
324
+
325
+ it 'outputs to stderr instead of stdout' do
326
+ expect(STDERR).to receive(:puts).with(default_output)
327
+
328
+ subject
329
+ end
330
+ end
227
331
  end
228
332
 
229
- it 'prints a nonstandard pooler output with host, template, time remaining, and reason' do
230
- hostname = 'sol11-9.delivery.mycompany.net'
231
- response_body = { hostname => {
232
- 'fqdn' => hostname,
233
- 'os_triple' => 'solaris-11-sparc',
234
- 'reserved_by_user' => 'first.last',
235
- 'reserved_for_reason' => 'testing',
236
- 'hours_left_on_reservation' => 35.89,
237
- } }
238
- output = '- sol11-9.delivery.mycompany.net (solaris-11-sparc, 35.89h remaining, reason: testing)'
333
+ describe 'with nonstandard pooler service' do
334
+ let(:service) { Service.new(MockOptions.new, 'url' => url, 'type' => 'ns') }
335
+
336
+ let(:hostname) { 'sol11-9.delivery.mycompany.net' }
337
+ let(:response_body) do
338
+ {
339
+ hostname => {
340
+ 'fqdn' => hostname,
341
+ 'os_triple' => 'solaris-11-sparc',
342
+ 'reserved_by_user' => 'first.last',
343
+ 'reserved_for_reason' => '',
344
+ 'hours_left_on_reservation' => 35.89,
345
+ }
346
+ }
347
+ end
348
+
349
+ let(:default_output) { "- #{hostname} (solaris-11-sparc, 35.89h remaining)" }
350
+
351
+ it 'prints output with host, template, and time remaining' do
352
+ expect(STDOUT).to receive(:puts).with(default_output)
353
+
354
+ subject
355
+ end
356
+
357
+ context 'when reason is supplied' do
358
+ let(:response_body) do
359
+ {
360
+ hostname => {
361
+ 'fqdn' => hostname,
362
+ 'os_triple' => 'solaris-11-sparc',
363
+ 'reserved_by_user' => 'first.last',
364
+ 'reserved_for_reason' => 'testing',
365
+ 'hours_left_on_reservation' => 35.89,
366
+ }
367
+ }
368
+ end
369
+
370
+ it 'prints output with host, template, time remaining, and reason' do
371
+ output = '- sol11-9.delivery.mycompany.net (solaris-11-sparc, 35.89h remaining, reason: testing)'
372
+
373
+ expect(STDOUT).to receive(:puts).with(output)
374
+
375
+ subject
376
+ end
377
+ end
378
+
379
+ context 'when print_to_stderr option is true' do
380
+ let(:print_to_stderr) { true }
381
+
382
+ it 'outputs to stderr instead of stdout' do
383
+ expect(STDERR).to receive(:puts).with(default_output)
384
+
385
+ subject
386
+ end
387
+ end
388
+ end
239
389
 
240
- expect(Utils).to receive(:puts).with(output)
390
+ describe 'with ABS service' do
391
+ let(:service) { Service.new(MockOptions.new, 'url' => url, 'type' => 'abs') }
392
+
393
+ let(:hostname) { '1597952189390' }
394
+ let(:fqdn) { 'example-noun.delivery.mycompany.net' }
395
+ let(:fqdn_hostname) {'example-noun'}
396
+ let(:template) { 'ubuntu-1604-x86_64' }
397
+
398
+ # This seems to be the miminal stub response from ABS for the current output
399
+ let(:response_body) do
400
+ {
401
+ hostname => {
402
+ 'state' => 'allocated',
403
+ 'allocated_resources' => [
404
+ {
405
+ 'hostname' => fqdn,
406
+ 'type' => template,
407
+ 'engine' => 'vmpooler',
408
+ },
409
+ ],
410
+ 'request' => {
411
+ 'job' => {
412
+ 'id' => hostname,
413
+ }
414
+ },
415
+ }
416
+ }
417
+ end
418
+
419
+ # The vmpooler response contains metadata that is printed
420
+ let(:domain) { 'delivery.mycompany.net' }
421
+ let(:response_body_vmpooler) do
422
+ {
423
+ fqdn_hostname => {
424
+ 'template' => template,
425
+ 'lifetime' => 48,
426
+ 'running' => 7.67,
427
+ 'state' => 'running',
428
+ 'tags' => {
429
+ 'user' => 'bob',
430
+ 'role' => 'agent',
431
+ },
432
+ 'ip' => '127.0.0.1',
433
+ 'domain' => domain,
434
+ }
435
+ }
436
+ end
437
+
438
+ before(:each) do
439
+ allow(Utils).to receive(:get_vmpooler_service_config).and_return({
440
+ 'url' => 'http://vmpooler.example.com',
441
+ 'token' => 'krypto-knight'
442
+ })
443
+ allow(service).to receive(:query)
444
+ .with(anything, fqdn_hostname)
445
+ .and_return(response_body_vmpooler)
446
+ end
447
+
448
+ let(:default_output_first_line) { "- [JobID:#{hostname}] <allocated>" }
449
+ let(:default_output_second_line) { " - #{fqdn} (#{template})" }
450
+
451
+ it 'prints output with job id, host, and template' do
452
+ expect(STDOUT).to receive(:puts).with(default_output_first_line)
453
+ expect(STDOUT).to receive(:puts).with(default_output_second_line)
454
+
455
+ subject
456
+ end
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
+
468
+ context 'when print_to_stderr option is true' do
469
+ let(:print_to_stderr) { true }
470
+
471
+ it 'outputs to stderr instead of stdout' do
472
+ expect(STDERR).to receive(:puts).with(default_output_first_line)
473
+ expect(STDERR).to receive(:puts).with(default_output_second_line)
474
+
475
+ subject
476
+ end
477
+ end
478
+ end
241
479
 
242
- service = Service.new(MockOptions.new, 'url' => url, 'type' => 'ns')
243
- allow(service).to receive(:query)
244
- .with(nil, hostname)
245
- .and_return(response_body)
480
+ describe 'with ABS service returning vmpooler and nspooler resources' do
481
+ let(:service) { Service.new(MockOptions.new, 'url' => url, 'type' => 'abs') }
482
+
483
+ let(:hostname) { '1597952189390' }
484
+ let(:fqdn) { 'this-noun.delivery.mycompany.net' }
485
+ let(:fqdn_ns) { 'that-noun.delivery.mycompany.net' }
486
+ let(:fqdn_hostname) {'this-noun'}
487
+ let(:fqdn_ns_hostname) {'that-noun'}
488
+ let(:template) { 'ubuntu-1604-x86_64' }
489
+ let(:template_ns) { 'solaris-10-sparc' }
490
+
491
+ # This seems to be the miminal stub response from ABS for the current output
492
+ let(:response_body) do
493
+ {
494
+ hostname => {
495
+ 'state' => 'allocated',
496
+ 'allocated_resources' => [
497
+ {
498
+ 'hostname' => fqdn,
499
+ 'type' => template,
500
+ 'engine' => 'vmpooler',
501
+ },
502
+ {
503
+ 'hostname' => fqdn_ns,
504
+ 'type' => template_ns,
505
+ 'engine' => 'nspooler',
506
+ },
507
+ ],
508
+ 'request' => {
509
+ 'job' => {
510
+ 'id' => hostname,
511
+ }
512
+ },
513
+ }
514
+ }
515
+ end
516
+
517
+ # The vmpooler response contains metadata that is printed
518
+ let(:domain) { 'delivery.mycompany.net' }
519
+ let(:response_body_vmpooler) do
520
+ {
521
+ fqdn_hostname => {
522
+ 'template' => template,
523
+ 'lifetime' => 48,
524
+ 'running' => 7.67,
525
+ 'state' => 'running',
526
+ 'tags' => {
527
+ 'user' => 'bob',
528
+ 'role' => 'agent',
529
+ },
530
+ 'ip' => '127.0.0.1',
531
+ 'domain' => domain,
532
+ }
533
+ }
534
+ end
535
+
536
+ before(:each) do
537
+ allow(Utils).to receive(:get_vmpooler_service_config).and_return({
538
+ 'url' => 'http://vmpooler.example.com',
539
+ 'token' => 'krypto-knight'
540
+ })
541
+ allow(service).to receive(:query)
542
+ .with(anything, fqdn_hostname)
543
+ .and_return(response_body_vmpooler)
544
+ end
545
+
546
+ let(:default_output_first_line) { "- [JobID:#{hostname}] <allocated>" }
547
+ let(:default_output_second_line) { " - #{fqdn} (#{template})" }
548
+ let(:default_output_third_line) { " - #{fqdn_ns} (#{template_ns})" }
549
+
550
+ it 'prints output with job id, host, and template' do
551
+ expect(STDOUT).to receive(:puts).with(default_output_first_line)
552
+ expect(STDOUT).to receive(:puts).with(default_output_second_line)
553
+ expect(STDOUT).to receive(:puts).with(default_output_third_line)
554
+
555
+ subject
556
+ end
557
+
558
+ context 'when print_to_stderr option is true' do
559
+ let(:print_to_stderr) { true }
560
+
561
+ it 'outputs to stderr instead of stdout' do
562
+ expect(STDERR).to receive(:puts).with(default_output_first_line)
563
+ expect(STDERR).to receive(:puts).with(default_output_second_line)
564
+ expect(STDERR).to receive(:puts).with(default_output_third_line)
565
+
566
+ subject
567
+ end
568
+ end
569
+ end
570
+ end
246
571
 
247
- Utils.pretty_print_hosts(nil, service, hostname)
572
+ describe '#get_vmpooler_service_config' do
573
+ let(:Conf) { double }
574
+ it 'returns an error if the vmpooler_fallback is not setup' do
575
+ config = {
576
+ 'user' => 'foo',
577
+ 'services' => {
578
+ 'myabs' => {
579
+ 'url' => 'http://abs.com',
580
+ 'token' => 'krypto-night',
581
+ 'type' => 'abs'
582
+ }
583
+ }
584
+ }
585
+ allow(Conf).to receive(:read_config).and_return(config)
586
+ expect{Utils.get_vmpooler_service_config(config['services']['myabs']['vmpooler_fallback'])}.to raise_error(ArgumentError)
587
+ end
588
+ it 'returns an error if the vmpooler_fallback is setup but cannot be found' do
589
+ config = {
590
+ 'user' => 'foo',
591
+ 'services' => {
592
+ 'myabs' => {
593
+ 'url' => 'http://abs.com',
594
+ 'token' => 'krypto-night',
595
+ 'type' => 'abs',
596
+ 'vmpooler_fallback' => 'myvmpooler'
597
+ }
598
+ }
599
+ }
600
+ allow(Conf).to receive(:read_config).and_return(config)
601
+ expect{Utils.get_vmpooler_service_config(config['services']['myabs']['vmpooler_fallback'])}.to raise_error(ArgumentError, /myvmpooler/)
602
+ end
603
+ it 'returns the vmpooler_fallback config' do
604
+ config = {
605
+ 'user' => 'foo',
606
+ 'services' => {
607
+ 'myabs' => {
608
+ 'url' => 'http://abs.com',
609
+ 'token' => 'krypto-night',
610
+ 'type' => 'abs',
611
+ 'vmpooler_fallback' => 'myvmpooler'
612
+ },
613
+ 'myvmpooler' => {
614
+ 'url' => 'http://vmpooler.com',
615
+ 'token' => 'krypto-knight'
616
+ }
617
+ }
618
+ }
619
+ allow(Conf).to receive(:read_config).and_return(config)
620
+ expect(Utils.get_vmpooler_service_config(config['services']['myabs']['vmpooler_fallback'])).to include({
621
+ 'url' => 'http://vmpooler.com',
622
+ 'token' => 'krypto-knight',
623
+ 'user' => 'foo',
624
+ 'type' => 'vmpooler'
625
+ })
248
626
  end
249
627
  end
250
628
  end