vmfloaty 0.9.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'vmfloaty/ssh'
5
+
6
+ class ServiceStub
7
+ def retrieve(_verbose, os_types, _use_token)
8
+ if os_types.keys[0] == 'abs_host_string'
9
+ return {
10
+ os_types.keys[0] => { 'hostname' => ['abs-hostname.delivery.puppetlabs.net'] },
11
+ 'ok' => true,
12
+ }
13
+ end
14
+
15
+ {
16
+ os_types.keys[0] => { 'hostname' => 'vmpooler-hostname' },
17
+ 'domain' => 'delivery.puppetlabs.net',
18
+ 'ok' => true,
19
+ }
20
+ end
21
+
22
+ def type
23
+ return 'abs' if os_types == 'abs_host_string'
24
+ return 'vmpooler' if os_types == 'vmpooler_host_string'
25
+ end
26
+ end
27
+
28
+ describe Ssh do
29
+ before :each do
30
+ end
31
+
32
+ it 'gets a hostname string for abs' do
33
+ verbose = false
34
+ service = ServiceStub.new
35
+ host_os = 'abs_host_string'
36
+ use_token = false
37
+ cmd = Ssh.command_string(verbose, service, host_os, use_token)
38
+ expect(cmd).to match(/ssh root@abs-hostname.delivery.puppetlabs.net/)
39
+ end
40
+
41
+ it 'gets a hostname string for vmpooler' do
42
+ verbose = false
43
+ service = ServiceStub.new
44
+ host_os = 'vmpooler_host_string'
45
+ use_token = false
46
+ cmd = Ssh.command_string(verbose, service, host_os, use_token)
47
+ expect(cmd).to match(/ssh root@vmpooler-hostname.delivery.puppetlabs.net/)
48
+ end
49
+ end
@@ -77,9 +77,17 @@ describe Utils do
77
77
  expect(Utils.get_service_object).to be Pooler
78
78
  end
79
79
 
80
+ it 'uses abs when told explicitly' do
81
+ expect(Utils.get_service_object('abs')).to be ABS
82
+ end
83
+
80
84
  it 'uses nspooler when told explicitly' do
81
85
  expect(Utils.get_service_object('nspooler')).to be NonstandardPooler
82
86
  end
87
+
88
+ it 'uses vmpooler when told explicitly' do
89
+ expect(Utils.get_service_object('vmpooler')).to be Pooler
90
+ end
83
91
  end
84
92
 
85
93
  describe '#get_service_config' do
@@ -154,97 +162,452 @@ describe Utils do
154
162
  end
155
163
  end
156
164
 
157
- describe '#pretty_print_hosts' do
165
+ describe '#print_fqdn_for_host' do
158
166
  let(:url) { 'http://pooler.example.com' }
159
167
 
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)
168
+ subject { Utils.print_fqdn_for_host(service, hostname, host_data) }
169
+
170
+ describe 'with vmpooler host' do
171
+ let(:service) { Service.new(MockOptions.new, 'url' => url) }
172
+ let(:hostname) { 'mcpy42eqjxli9g2' }
173
+ let(:domain) { 'delivery.mycompany.net' }
174
+ let(:fqdn) { [hostname, domain].join('.') }
175
+
176
+ let(:host_data) do
177
+ {
178
+ 'template' => 'ubuntu-1604-x86_64',
179
+ 'lifetime' => 12,
180
+ 'running' => 9.66,
181
+ 'state' => 'running',
182
+ 'ip' => '127.0.0.1',
183
+ 'domain' => domain,
184
+ }
185
+ end
186
+
187
+ it 'outputs fqdn for host' do
188
+ expect(STDOUT).to receive(:puts).with(fqdn)
189
+
190
+ subject
191
+ end
180
192
  end
181
193
 
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)'
194
+ describe 'with nonstandard pooler host' do
195
+ let(:service) { Service.new(MockOptions.new, 'url' => url, 'type' => 'ns') }
196
+ let(:hostname) { 'sol11-9.delivery.mycompany.net' }
197
+ let(:host_data) do
198
+ {
199
+ 'fqdn' => hostname,
200
+ 'os_triple' => 'solaris-11-sparc',
201
+ 'reserved_by_user' => 'first.last',
202
+ 'reserved_for_reason' => '',
203
+ 'hours_left_on_reservation' => 35.89,
204
+ }
205
+ end
206
+ let(:fqdn) { hostname } # for nspooler these are the same
207
+
208
+ it 'outputs fqdn for host' do
209
+ expect(STDOUT).to receive(:puts).with(fqdn)
210
+
211
+ subject
212
+ end
213
+ end
197
214
 
198
- expect(Utils).to receive(:puts).with(output)
215
+ describe 'with ABS host' do
216
+ let(:service) { Service.new(MockOptions.new, 'url' => url, 'type' => 'abs') }
217
+ let(:hostname) { '1597952189390' }
218
+ let(:fqdn) { 'example-noun.delivery.puppetlabs.net' }
219
+ let(:template) { 'ubuntu-1604-x86_64' }
220
+
221
+ # This seems to be the miminal stub response from ABS for the current output
222
+ let(:host_data) do
223
+ {
224
+ 'state' => 'allocated',
225
+ 'allocated_resources' => [
226
+ {
227
+ 'hostname' => fqdn,
228
+ 'type' => template,
229
+ 'enging' => 'vmpooler',
230
+ },
231
+ ],
232
+ 'request' => {
233
+ 'job' => {
234
+ 'id' => hostname,
235
+ }
236
+ },
237
+ }
238
+ end
199
239
 
200
- service = Service.new(MockOptions.new, 'url' => url)
201
- allow(service).to receive(:query)
202
- .with(nil, hostname)
203
- .and_return(response_body)
240
+ it 'outputs fqdn for host' do
241
+ expect(STDOUT).to receive(:puts).with(fqdn)
204
242
 
205
- Utils.pretty_print_hosts(nil, service, hostname)
243
+ subject
244
+ end
206
245
  end
246
+ end
207
247
 
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)
248
+ describe '#pretty_print_hosts' do
249
+ let(:url) { 'http://pooler.example.com' }
250
+ let(:verbose) { nil }
251
+ let(:print_to_stderr) { false }
220
252
 
221
- service = Service.new(MockOptions.new, 'url' => url, 'type' => 'ns')
253
+ before(:each) do
222
254
  allow(service).to receive(:query)
223
- .with(nil, hostname)
255
+ .with(anything, hostname)
224
256
  .and_return(response_body)
257
+ end
225
258
 
226
- Utils.pretty_print_hosts(nil, service, hostname)
259
+ subject { Utils.pretty_print_hosts(verbose, service, hostname, print_to_stderr) }
260
+
261
+ describe 'with vmpooler service' do
262
+ let(:service) { Service.new(MockOptions.new, 'url' => url) }
263
+
264
+ let(:hostname) { 'mcpy42eqjxli9g2' }
265
+ let(:domain) { 'delivery.mycompany.net' }
266
+ let(:fqdn) { [hostname, domain].join('.') }
267
+
268
+ let(:response_body) do
269
+ {
270
+ hostname => {
271
+ 'template' => 'ubuntu-1604-x86_64',
272
+ 'lifetime' => 12,
273
+ 'running' => 9.66,
274
+ 'state' => 'running',
275
+ 'ip' => '127.0.0.1',
276
+ 'domain' => domain,
277
+ }
278
+ }
279
+ end
280
+
281
+ let(:default_output) { "- #{fqdn} (ubuntu-1604-x86_64, 9.66/12 hours)" }
282
+
283
+ it 'prints output with host fqdn, template and duration info' do
284
+ expect(STDOUT).to receive(:puts).with(default_output)
285
+
286
+ subject
287
+ end
288
+
289
+ context 'when tags are supplied' do
290
+ let(:hostname) { 'aiydvzpg23r415q' }
291
+ let(:response_body) do
292
+ {
293
+ hostname => {
294
+ 'template' => 'redhat-7-x86_64',
295
+ 'lifetime' => 48,
296
+ 'running' => 7.67,
297
+ 'state' => 'running',
298
+ 'tags' => {
299
+ 'user' => 'bob',
300
+ 'role' => 'agent',
301
+ },
302
+ 'ip' => '127.0.0.1',
303
+ 'domain' => domain,
304
+ }
305
+ }
306
+ end
307
+
308
+ it 'prints output with host fqdn, template, duration info, and tags' do
309
+ output = "- #{fqdn} (redhat-7-x86_64, 7.67/48 hours, user: bob, role: agent)"
310
+
311
+ expect(STDOUT).to receive(:puts).with(output)
312
+
313
+ subject
314
+ end
315
+ end
316
+
317
+ context 'when print_to_stderr option is true' do
318
+ let(:print_to_stderr) { true }
319
+
320
+ it 'outputs to stderr instead of stdout' do
321
+ expect(STDERR).to receive(:puts).with(default_output)
322
+
323
+ subject
324
+ end
325
+ end
227
326
  end
228
327
 
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)'
328
+ describe 'with nonstandard pooler service' do
329
+ let(:service) { Service.new(MockOptions.new, 'url' => url, 'type' => 'ns') }
330
+
331
+ let(:hostname) { 'sol11-9.delivery.mycompany.net' }
332
+ let(:response_body) do
333
+ {
334
+ hostname => {
335
+ 'fqdn' => hostname,
336
+ 'os_triple' => 'solaris-11-sparc',
337
+ 'reserved_by_user' => 'first.last',
338
+ 'reserved_for_reason' => '',
339
+ 'hours_left_on_reservation' => 35.89,
340
+ }
341
+ }
342
+ end
343
+
344
+ let(:default_output) { "- #{hostname} (solaris-11-sparc, 35.89h remaining)" }
345
+
346
+ it 'prints output with host, template, and time remaining' do
347
+ expect(STDOUT).to receive(:puts).with(default_output)
348
+
349
+ subject
350
+ end
351
+
352
+ context 'when reason is supplied' do
353
+ let(:response_body) do
354
+ {
355
+ hostname => {
356
+ 'fqdn' => hostname,
357
+ 'os_triple' => 'solaris-11-sparc',
358
+ 'reserved_by_user' => 'first.last',
359
+ 'reserved_for_reason' => 'testing',
360
+ 'hours_left_on_reservation' => 35.89,
361
+ }
362
+ }
363
+ end
364
+
365
+ it 'prints output with host, template, time remaining, and reason' do
366
+ output = '- sol11-9.delivery.mycompany.net (solaris-11-sparc, 35.89h remaining, reason: testing)'
367
+
368
+ expect(STDOUT).to receive(:puts).with(output)
369
+
370
+ subject
371
+ end
372
+ end
373
+
374
+ context 'when print_to_stderr option is true' do
375
+ let(:print_to_stderr) { true }
376
+
377
+ it 'outputs to stderr instead of stdout' do
378
+ expect(STDERR).to receive(:puts).with(default_output)
379
+
380
+ subject
381
+ end
382
+ end
383
+ end
239
384
 
240
- expect(Utils).to receive(:puts).with(output)
385
+ describe 'with ABS service' do
386
+ let(:service) { Service.new(MockOptions.new, 'url' => url, 'type' => 'abs') }
387
+
388
+ let(:hostname) { '1597952189390' }
389
+ let(:fqdn) { 'example-noun.delivery.mycompany.net' }
390
+ let(:fqdn_hostname) {'example-noun'}
391
+ let(:template) { 'ubuntu-1604-x86_64' }
392
+
393
+ # This seems to be the miminal stub response from ABS for the current output
394
+ let(:response_body) do
395
+ {
396
+ hostname => {
397
+ 'state' => 'allocated',
398
+ 'allocated_resources' => [
399
+ {
400
+ 'hostname' => fqdn,
401
+ 'type' => template,
402
+ 'engine' => 'vmpooler',
403
+ },
404
+ ],
405
+ 'request' => {
406
+ 'job' => {
407
+ 'id' => hostname,
408
+ }
409
+ },
410
+ }
411
+ }
412
+ end
413
+
414
+ # The vmpooler response contains metadata that is printed
415
+ let(:domain) { 'delivery.mycompany.net' }
416
+ let(:response_body_vmpooler) do
417
+ {
418
+ fqdn_hostname => {
419
+ 'template' => template,
420
+ 'lifetime' => 48,
421
+ 'running' => 7.67,
422
+ 'state' => 'running',
423
+ 'tags' => {
424
+ 'user' => 'bob',
425
+ 'role' => 'agent',
426
+ },
427
+ 'ip' => '127.0.0.1',
428
+ 'domain' => domain,
429
+ }
430
+ }
431
+ end
432
+
433
+ before(:each) do
434
+ allow(Utils).to receive(:get_vmpooler_service_config).and_return({
435
+ 'url' => 'http://vmpooler.example.com',
436
+ 'token' => 'krypto-knight'
437
+ })
438
+ allow(service).to receive(:query)
439
+ .with(anything, fqdn_hostname)
440
+ .and_return(response_body_vmpooler)
441
+ end
442
+
443
+ let(:default_output_first_line) { "- [JobID:#{hostname}] <allocated>" }
444
+ let(:default_output_second_line) { " - #{fqdn} (#{template}, 7.67/48 hours, user: bob, role: agent)" }
445
+
446
+ it 'prints output with job id, host, and template' do
447
+ expect(STDOUT).to receive(:puts).with(default_output_first_line)
448
+ expect(STDOUT).to receive(:puts).with(default_output_second_line)
449
+
450
+ subject
451
+ end
452
+
453
+ context 'when print_to_stderr option is true' do
454
+ let(:print_to_stderr) { true }
455
+
456
+ it 'outputs to stderr instead of stdout' do
457
+ expect(STDERR).to receive(:puts).with(default_output_first_line)
458
+ expect(STDERR).to receive(:puts).with(default_output_second_line)
459
+
460
+ subject
461
+ end
462
+ end
463
+ end
241
464
 
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)
465
+ describe 'with ABS service returning vmpooler and nspooler resources' do
466
+ let(:service) { Service.new(MockOptions.new, 'url' => url, 'type' => 'abs') }
467
+
468
+ let(:hostname) { '1597952189390' }
469
+ let(:fqdn) { 'this-noun.delivery.mycompany.net' }
470
+ let(:fqdn_ns) { 'that-noun.delivery.mycompany.net' }
471
+ let(:fqdn_hostname) {'this-noun'}
472
+ let(:fqdn_ns_hostname) {'that-noun'}
473
+ let(:template) { 'ubuntu-1604-x86_64' }
474
+ let(:template_ns) { 'solaris-10-sparc' }
475
+
476
+ # This seems to be the miminal stub response from ABS for the current output
477
+ let(:response_body) do
478
+ {
479
+ hostname => {
480
+ 'state' => 'allocated',
481
+ 'allocated_resources' => [
482
+ {
483
+ 'hostname' => fqdn,
484
+ 'type' => template,
485
+ 'engine' => 'vmpooler',
486
+ },
487
+ {
488
+ 'hostname' => fqdn_ns,
489
+ 'type' => template_ns,
490
+ 'engine' => 'nspooler',
491
+ },
492
+ ],
493
+ 'request' => {
494
+ 'job' => {
495
+ 'id' => hostname,
496
+ }
497
+ },
498
+ }
499
+ }
500
+ end
501
+
502
+ # The vmpooler response contains metadata that is printed
503
+ let(:domain) { 'delivery.mycompany.net' }
504
+ let(:response_body_vmpooler) do
505
+ {
506
+ fqdn_hostname => {
507
+ 'template' => template,
508
+ 'lifetime' => 48,
509
+ 'running' => 7.67,
510
+ 'state' => 'running',
511
+ 'tags' => {
512
+ 'user' => 'bob',
513
+ 'role' => 'agent',
514
+ },
515
+ 'ip' => '127.0.0.1',
516
+ 'domain' => domain,
517
+ }
518
+ }
519
+ end
520
+
521
+ before(:each) do
522
+ allow(Utils).to receive(:get_vmpooler_service_config).and_return({
523
+ 'url' => 'http://vmpooler.example.com',
524
+ 'token' => 'krypto-knight'
525
+ })
526
+ allow(service).to receive(:query)
527
+ .with(anything, fqdn_hostname)
528
+ .and_return(response_body_vmpooler)
529
+ end
530
+
531
+ let(:default_output_first_line) { "- [JobID:#{hostname}] <allocated>" }
532
+ let(:default_output_second_line) { " - #{fqdn} (#{template}, 7.67/48 hours, user: bob, role: agent)" }
533
+ let(:default_output_third_line) { " - #{fqdn_ns} (#{template_ns})" }
534
+
535
+ it 'prints output with job id, host, and template' do
536
+ expect(STDOUT).to receive(:puts).with(default_output_first_line)
537
+ expect(STDOUT).to receive(:puts).with(default_output_second_line)
538
+ expect(STDOUT).to receive(:puts).with(default_output_third_line)
539
+
540
+ subject
541
+ end
542
+
543
+ context 'when print_to_stderr option is true' do
544
+ let(:print_to_stderr) { true }
545
+
546
+ it 'outputs to stderr instead of stdout' do
547
+ expect(STDERR).to receive(:puts).with(default_output_first_line)
548
+ expect(STDERR).to receive(:puts).with(default_output_second_line)
549
+ expect(STDERR).to receive(:puts).with(default_output_third_line)
550
+
551
+ subject
552
+ end
553
+ end
554
+ end
555
+ end
246
556
 
247
- Utils.pretty_print_hosts(nil, service, hostname)
557
+ describe '#get_vmpooler_service_config' do
558
+ let(:Conf) { double }
559
+ it 'returns an error if the vmpooler_fallback is not setup' do
560
+ config = {
561
+ 'user' => 'foo',
562
+ 'services' => {
563
+ 'myabs' => {
564
+ 'url' => 'http://abs.com',
565
+ 'token' => 'krypto-night',
566
+ 'type' => 'abs'
567
+ }
568
+ }
569
+ }
570
+ allow(Conf).to receive(:read_config).and_return(config)
571
+ expect{Utils.get_vmpooler_service_config(config['services']['myabs']['vmpooler_fallback'])}.to raise_error(ArgumentError)
572
+ end
573
+ it 'returns an error if the vmpooler_fallback is setup but cannot be found' do
574
+ config = {
575
+ 'user' => 'foo',
576
+ 'services' => {
577
+ 'myabs' => {
578
+ 'url' => 'http://abs.com',
579
+ 'token' => 'krypto-night',
580
+ 'type' => 'abs',
581
+ 'vmpooler_fallback' => 'myvmpooler'
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, /myvmpooler/)
587
+ end
588
+ it 'returns the vmpooler_fallback config' 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
+ 'myvmpooler' => {
599
+ 'url' => 'http://vmpooler.com',
600
+ 'token' => 'krypto-knight'
601
+ }
602
+ }
603
+ }
604
+ allow(Conf).to receive(:read_config).and_return(config)
605
+ expect(Utils.get_vmpooler_service_config(config['services']['myabs']['vmpooler_fallback'])).to include({
606
+ 'url' => 'http://vmpooler.com',
607
+ 'token' => 'krypto-knight',
608
+ 'user' => 'foo',
609
+ 'type' => 'vmpooler'
610
+ })
248
611
  end
249
612
  end
250
613
  end