keyrack 0.3.0.pre → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +8 -15
  4. data/Guardfile +6 -0
  5. data/LICENSE.txt +4 -2
  6. data/Rakefile +2 -56
  7. data/keyrack.gemspec +22 -104
  8. data/lib/keyrack.rb +9 -1
  9. data/lib/keyrack/database.rb +64 -98
  10. data/lib/keyrack/event.rb +13 -0
  11. data/lib/keyrack/exceptions.rb +4 -0
  12. data/lib/keyrack/group.rb +225 -0
  13. data/lib/keyrack/migrator.rb +45 -0
  14. data/lib/keyrack/runner.rb +98 -44
  15. data/lib/keyrack/site.rb +92 -0
  16. data/lib/keyrack/ui/console.rb +234 -95
  17. data/lib/keyrack/utils.rb +0 -18
  18. data/lib/keyrack/version.rb +3 -0
  19. data/test/fixtures/database-3.dat +0 -0
  20. data/test/helper.rb +11 -1
  21. data/test/integration/test_interactive_console.rb +139 -0
  22. data/test/unit/store/test_filesystem.rb +21 -0
  23. data/test/unit/store/test_ssh.rb +32 -0
  24. data/test/unit/test_database.rb +201 -0
  25. data/test/unit/test_event.rb +41 -0
  26. data/test/unit/test_group.rb +703 -0
  27. data/test/unit/test_migrator.rb +105 -0
  28. data/test/unit/test_runner.rb +407 -0
  29. data/test/unit/test_site.rb +181 -0
  30. data/test/unit/test_store.rb +13 -0
  31. data/test/unit/test_utils.rb +8 -0
  32. data/test/unit/ui/test_console.rb +495 -0
  33. metadata +98 -94
  34. data/Gemfile.lock +0 -45
  35. data/TODO +0 -4
  36. data/VERSION +0 -1
  37. data/features/console.feature +0 -103
  38. data/features/step_definitions/keyrack_steps.rb +0 -61
  39. data/features/support/env.rb +0 -16
  40. data/test/fixtures/aes +0 -0
  41. data/test/fixtures/config.yml +0 -4
  42. data/test/fixtures/id_rsa +0 -54
  43. data/test/keyrack/store/test_filesystem.rb +0 -25
  44. data/test/keyrack/store/test_ssh.rb +0 -36
  45. data/test/keyrack/test_database.rb +0 -111
  46. data/test/keyrack/test_runner.rb +0 -111
  47. data/test/keyrack/test_store.rb +0 -15
  48. data/test/keyrack/test_utils.rb +0 -41
  49. data/test/keyrack/ui/test_console.rb +0 -308
@@ -0,0 +1,41 @@
1
+ require 'helper'
2
+
3
+ class TestEvent < Test::Unit::TestCase
4
+ test "initialize with owner and name" do
5
+ obj = stub('object')
6
+ event = Keyrack::Event.new(obj, 'change')
7
+ assert_equal obj, event.owner
8
+ assert_equal 'change', event.name
9
+ end
10
+
11
+ test "initialize with parent event" do
12
+ child = stub('child object')
13
+ event_1 = Keyrack::Event.new(child, 'change')
14
+ assert_nil event_1.parent
15
+
16
+ parent = stub('parent object')
17
+ event_2 = Keyrack::Event.new(parent, 'change', event_1)
18
+ assert_equal event_1, event_2.parent
19
+ end
20
+
21
+ test "attribute details" do
22
+ obj = stub('object')
23
+ event = Keyrack::Event.new(obj, 'change')
24
+ event.attribute_name = "foo"
25
+ assert_equal "foo", event.attribute_name
26
+ event.previous_value = "bar"
27
+ assert_equal "bar", event.previous_value
28
+ event.new_value = "baz"
29
+ assert_equal "baz", event.new_value
30
+ end
31
+
32
+ test "collection details" do
33
+ owner = stub('owner')
34
+ event = Keyrack::Event.new(owner, 'add')
35
+ event.collection_name = "foo"
36
+ assert_equal "foo", event.collection_name
37
+ obj = stub('object')
38
+ event.object = obj
39
+ assert_equal obj, event.object
40
+ end
41
+ end
@@ -0,0 +1,703 @@
1
+ require 'helper'
2
+
3
+ class TestGroup < Test::Unit::TestCase
4
+ def new_group(*args)
5
+ Keyrack::Group.new(*args)
6
+ end
7
+
8
+ def new_site(*args)
9
+ Keyrack::Site.new(*args)
10
+ end
11
+
12
+ test "initialize" do
13
+ group = new_group("Starships")
14
+ assert_equal "Starships", group.name
15
+ assert_equal([], group.sites)
16
+ assert_equal({}, group.groups)
17
+ end
18
+
19
+ test "initializing with no arguments makes read-only (until loaded)" do
20
+ group = Keyrack::Group.new
21
+ assert_raises(RuntimeError) { group.add_site(new_site('Foo')) }
22
+ assert_raises(RuntimeError) { group.remove_site('Foo') }
23
+ assert_raises(RuntimeError) { group.add_group(new_group('Foo')) }
24
+ assert_raises(RuntimeError) { group.remove_group('Foo') }
25
+ end
26
+
27
+ test "change name" do
28
+ group = new_group("Starships")
29
+ assert_equal "Starships", group.name
30
+ group.name = "Galaxy class starships"
31
+ assert_equal "Galaxy class starships", group.name
32
+ end
33
+
34
+ test "add_site" do
35
+ group = new_group("Starships")
36
+ site = new_site("Enterprise", "picard", "livingston")
37
+ group.add_site(site)
38
+ assert_equal([site], group.sites)
39
+ end
40
+
41
+ test "add_site with same name" do
42
+ group = new_group("Starships")
43
+ site_1 = new_site("Enterprise", "picard", "livingston")
44
+ group.add_site(site_1)
45
+ site_2 = new_site("Enterprise", "riker", "trombone")
46
+ group.add_site(site_2)
47
+ assert_equal([site_1, site_2], group.sites)
48
+ end
49
+
50
+ test "adding already existing site raises error" do
51
+ group = new_group("Starships")
52
+ site = new_site("Enterprise", "picard", "livingston")
53
+ group.add_site(site)
54
+ assert_raises(Keyrack::GroupError) do
55
+ group.add_site(site)
56
+ end
57
+ end
58
+
59
+ test "adding invalid site raises error" do
60
+ group = new_group("Starships")
61
+ assert_raises(Keyrack::GroupError) do
62
+ group.add_site("Pegasus")
63
+ end
64
+ end
65
+
66
+ test "remove_site" do
67
+ group = new_group("Starships")
68
+ site = new_site("Enterprise", "picard", "livingston")
69
+ group.add_site(site)
70
+ group.remove_site(site)
71
+ assert_equal([], group.sites)
72
+ end
73
+
74
+ test "removing non-existant site raises error" do
75
+ group = new_group("Starships")
76
+ site = new_site("Enterprise", "picard", "livingston")
77
+ assert_raises(Keyrack::GroupError) do
78
+ group.remove_site(site)
79
+ end
80
+ end
81
+
82
+ test "add_group" do
83
+ group = new_group("Starships")
84
+ subgroup = new_group("Klingon")
85
+ group.add_group(subgroup)
86
+
87
+ expected = {"Klingon" => {'name' => "Klingon", 'sites' => [], 'groups' => {}}}
88
+ assert_equal(expected, group.groups)
89
+ end
90
+
91
+ test "adding already existing group raises error" do
92
+ group = new_group("Starships")
93
+ subgroup = new_group("Klingon")
94
+ group.add_group(subgroup)
95
+ assert_raises(Keyrack::GroupError) do
96
+ group.add_group(subgroup)
97
+ end
98
+ end
99
+
100
+ test "adding invalid group raises error" do
101
+ group = new_group("Starships")
102
+ assert_raises(Keyrack::GroupError) do
103
+ group.add_group("Klingon")
104
+ end
105
+ end
106
+
107
+ test "remove_group" do
108
+ group = new_group("Starships")
109
+ subgroup = new_group("Klingon")
110
+ group.add_group(subgroup)
111
+ group.remove_group("Klingon")
112
+ assert_equal({}, group.groups)
113
+ end
114
+
115
+ test "removing non-existant group raises error" do
116
+ group = new_group("Starships")
117
+ assert_raises(Keyrack::GroupError) do
118
+ group.remove_group("Klingon")
119
+ end
120
+ end
121
+
122
+ test "load group from hash" do
123
+ hash = {
124
+ 'name' => "Starships",
125
+ 'sites' => [
126
+ {
127
+ 'name' => 'Enterprise',
128
+ 'username' => 'picard',
129
+ 'password' => 'livingston'
130
+ }
131
+ ],
132
+ 'groups' => {
133
+ "Klingon" => {
134
+ 'name' => "Klingon",
135
+ 'sites' => [
136
+ {
137
+ 'name' => "Bortas",
138
+ 'username' => "gowron",
139
+ 'password' => "bat'leth"
140
+ }
141
+ ],
142
+ 'groups' => {}
143
+ }
144
+ }
145
+ }
146
+ group = new_group(hash)
147
+ assert_equal "Starships", group.name
148
+ assert_equal hash['sites'], group.sites
149
+ assert_equal hash['groups'], group.groups
150
+
151
+ group = Keyrack::Group.new
152
+ group.load(hash)
153
+ assert_equal "Starships", group.name
154
+ assert_equal hash['sites'], group.sites
155
+ assert_equal hash['groups'], group.groups
156
+ end
157
+
158
+ test "loading group from hash with missing name" do
159
+ hash = {
160
+ 'sites' => [],
161
+ 'groups' => {}
162
+ }
163
+ assert_raises(ArgumentError) do
164
+ group = new_group(hash)
165
+ end
166
+ end
167
+
168
+ test "loading group from hash with non-string name" do
169
+ hash = {
170
+ 'name' => [123],
171
+ 'sites' => [],
172
+ 'groups' => {}
173
+ }
174
+ assert_raises(ArgumentError) do
175
+ group = new_group(hash)
176
+ end
177
+ end
178
+
179
+ test "loading group with missing sites" do
180
+ hash = {
181
+ 'name' => "Starships",
182
+ 'groups' => {}
183
+ }
184
+ assert_raises(ArgumentError) do
185
+ group = new_group(hash)
186
+ end
187
+ end
188
+
189
+ test "loading group with non-array sites" do
190
+ hash = {
191
+ 'name' => "Starships",
192
+ 'sites' => "foo",
193
+ 'groups' => {}
194
+ }
195
+ assert_raises(ArgumentError) do
196
+ group = new_group(hash)
197
+ end
198
+ end
199
+
200
+ test "loading group with non-hash site" do
201
+ hash = {
202
+ 'name' => "Starships",
203
+ 'sites' => [
204
+ "foo"
205
+ ],
206
+ 'groups' => {}
207
+ }
208
+ assert_raises(ArgumentError) do
209
+ group = new_group(hash)
210
+ end
211
+ end
212
+
213
+ test "loading group with invalid site" do
214
+ hash = {
215
+ 'name' => "Starships",
216
+ 'sites' => [
217
+ {"foo" => "bar"}
218
+ ],
219
+ 'groups' => {}
220
+ }
221
+ assert_raises(ArgumentError) do
222
+ group = new_group(hash)
223
+ end
224
+ end
225
+
226
+ test "loading group with missing groups" do
227
+ hash = {
228
+ 'name' => "Starships",
229
+ 'sites' => []
230
+ }
231
+ assert_raises(ArgumentError) do
232
+ group = new_group(hash)
233
+ end
234
+ end
235
+
236
+ test "loading group with non-hash groups" do
237
+ hash = {
238
+ 'name' => "Starships",
239
+ 'sites' => [],
240
+ 'groups' => "foo"
241
+ }
242
+ assert_raises(ArgumentError) do
243
+ group = new_group(hash)
244
+ end
245
+ end
246
+
247
+ test "loading group with non-string group name" do
248
+ hash = {
249
+ 'name' => "Starships",
250
+ 'sites' => [],
251
+ 'groups' => {
252
+ [123] => {
253
+ 'name' => "Klingon",
254
+ 'sites' => [],
255
+ 'groups' => {}
256
+ }
257
+ },
258
+ }
259
+ assert_raises(ArgumentError) do
260
+ group = new_group(hash)
261
+ end
262
+ end
263
+
264
+ test "loading group with non-hash group value" do
265
+ hash = {
266
+ 'name' => "Starships",
267
+ 'sites' => [],
268
+ 'groups' => {
269
+ "foo" => "bar"
270
+ }
271
+ }
272
+ assert_raises(ArgumentError) do
273
+ group = new_group(hash)
274
+ end
275
+ end
276
+
277
+ test "loading group with invalid sub-group" do
278
+ hash = {
279
+ 'name' => "Starships",
280
+ 'sites' => [],
281
+ 'groups' => {
282
+ "foo" => {"foo" => "bar"}
283
+ }
284
+ }
285
+ assert_raises(ArgumentError) do
286
+ group = new_group(hash)
287
+ end
288
+ end
289
+
290
+ test "loading group with mismatched group names" do
291
+ hash = {
292
+ 'name' => "Starships",
293
+ 'sites' => [],
294
+ 'groups' => {
295
+ "Foo" => {
296
+ 'name' => "Klingon",
297
+ 'sites' => [],
298
+ 'groups' => {}
299
+ }
300
+ }
301
+ }
302
+ assert_raises(ArgumentError) do
303
+ group = new_group(hash)
304
+ end
305
+ end
306
+
307
+ test "loading group from hash does not call hooks" do
308
+ hash = {
309
+ 'name' => "Starships",
310
+ 'sites' => [
311
+ {
312
+ 'name' => 'Enterprise',
313
+ 'username' => 'picard',
314
+ 'password' => 'livingston'
315
+ }
316
+ ],
317
+ 'groups' => {
318
+ "Klingon" => {
319
+ 'name' => "Klingon",
320
+ 'sites' => [
321
+ {
322
+ 'name' => "Bortas",
323
+ 'username' => "gowron",
324
+ 'password' => "bat'leth"
325
+ }
326
+ ],
327
+ 'groups' => {}
328
+ }
329
+ }
330
+ }
331
+ group = Keyrack::Group.new
332
+ called = false
333
+ group.after_event { |_| called = true }
334
+ group.load(hash)
335
+ assert !called
336
+ end
337
+
338
+ test "site getter" do
339
+ group = new_group("Starships")
340
+ site = new_site("Enterprise", "picard", "livingston")
341
+ group.add_site(site)
342
+ assert_same site, group.site(0)
343
+ end
344
+
345
+ test "group getter" do
346
+ group = new_group("Starships")
347
+ subgroup = new_group("Klingon")
348
+ group.add_group(subgroup)
349
+ assert_same subgroup, group.group("Klingon")
350
+ end
351
+
352
+ test "group_names" do
353
+ group = new_group("Starships")
354
+ subgroup = new_group("Klingon")
355
+ group.add_group(subgroup)
356
+ assert_equal ["Klingon"], group.group_names
357
+ end
358
+
359
+ test "name changed callback" do
360
+ group = new_group("Starships")
361
+
362
+ called = false
363
+ group.after_event do |event|
364
+ called = true
365
+ assert_same group, event.owner
366
+ assert_equal 'change', event.name
367
+ assert_equal 'name', event.attribute_name
368
+ assert_equal 'Starships', event.previous_value
369
+ assert_equal 'Galaxy class starships', event.new_value
370
+ end
371
+ group.name = 'Galaxy class starships'
372
+ assert called
373
+ end
374
+
375
+ test "name changed callback for subgroup" do
376
+ group = new_group("Starships")
377
+ subgroup = new_group("Galaxy class")
378
+ group.add_group(subgroup)
379
+
380
+ called = false
381
+ group.after_event do |event|
382
+ called = true
383
+ assert_same group, event.owner
384
+ assert_equal 'change', event.name
385
+ assert_not_nil event.parent
386
+ assert_same subgroup, event.parent.owner
387
+ end
388
+ subgroup.name = "Excelsior class"
389
+ assert called
390
+ end
391
+
392
+ test "group updates subgroup names after subgroup's name changes" do
393
+ group = new_group("Starships")
394
+ subgroup = new_group("Galaxy class")
395
+ group.add_group(subgroup)
396
+ assert_equal({'Galaxy class' => subgroup}, group.groups)
397
+ subgroup.name = 'Soyuz class'
398
+ assert_equal({'Soyuz class' => subgroup}, group.groups)
399
+ end
400
+
401
+ test "site added callback" do
402
+ group = new_group("Starships")
403
+ site = new_site("Enterprise", "picard", "livingston")
404
+
405
+ called = false
406
+ group.after_event do |event|
407
+ called = true
408
+ assert_same group, event.owner
409
+ assert_equal 'add', event.name
410
+ assert_equal 'sites', event.collection_name
411
+ assert_same site, event.object
412
+ end
413
+ group.add_site(site)
414
+ assert called
415
+ end
416
+
417
+ test "site added callback for subgroup" do
418
+ group = new_group("Starships")
419
+ subgroup = new_group("Galaxy class")
420
+ group.add_group(subgroup)
421
+ site = new_site("Enterprise", "picard", "livingston")
422
+
423
+ called = false
424
+ group.after_event do |event|
425
+ called = true
426
+ assert_same group, event.owner
427
+ assert_equal 'change', event.name
428
+ assert_not_nil event.parent
429
+ assert_same subgroup, event.parent.owner
430
+ end
431
+ subgroup.add_site(site)
432
+ assert called
433
+ end
434
+
435
+ test "site username changed callback" do
436
+ group = new_group("Starships")
437
+ site = new_site("Enterprise", "picard", "livingston")
438
+ group.add_site(site)
439
+
440
+ called = false
441
+ group.after_event do |event|
442
+ called = true
443
+ assert_same group, event.owner
444
+ assert_equal 'change', event.name
445
+ assert_not_nil event.parent
446
+ assert_same site, event.parent.owner
447
+ end
448
+ site.username = "jean_luc"
449
+ assert called
450
+ end
451
+
452
+ test "site username changed callback for hash-loaded group" do
453
+ group = new_group({
454
+ 'name' => "Starships",
455
+ 'sites' => [
456
+ {
457
+ 'name' => 'Enterprise',
458
+ 'username' => 'picard',
459
+ 'password' => 'livingston'
460
+ }
461
+ ],
462
+ 'groups' => {}
463
+ })
464
+ site = group.site(0)
465
+
466
+ called = false
467
+ group.after_event do |event|
468
+ called = true
469
+ assert_same group, event.owner
470
+ assert_equal 'change', event.name
471
+ assert_not_nil event.parent
472
+ assert_same site, event.parent.owner
473
+ end
474
+ site.username = "jean_luc"
475
+ assert called
476
+ end
477
+
478
+ test "site username changed callback for subgroup" do
479
+ group = new_group("Starships")
480
+ subgroup = new_group("Galaxy class")
481
+ group.add_group(subgroup)
482
+ site = new_site("Enterprise", "picard", "livingston")
483
+ subgroup.add_site(site)
484
+
485
+ called = false
486
+ group.after_event do |event|
487
+ called = true
488
+ assert_same group, event.owner
489
+ assert_equal 'change', event.name
490
+ assert_not_nil event.parent
491
+ assert_same subgroup, event.parent.owner
492
+ assert_not_nil event.parent.parent
493
+ assert_same site, event.parent.parent.owner
494
+ end
495
+ site.username = "jean_luc"
496
+ assert called
497
+ end
498
+
499
+ test "site password changed callback" do
500
+ group = new_group("Starships")
501
+ site = new_site("Enterprise", "picard", "livingston")
502
+ group.add_site(site)
503
+
504
+ called = false
505
+ group.after_event do |event|
506
+ called = true
507
+ assert_same group, event.owner
508
+ assert_equal 'change', event.name
509
+ assert_not_nil event.parent
510
+ assert_same site, event.parent.owner
511
+ end
512
+ site.password = "crusher"
513
+ assert called
514
+ end
515
+
516
+ test "after_password_changed callback for hash-loaded group" do
517
+ group = new_group({
518
+ 'name' => "Starships",
519
+ 'sites' => [
520
+ {
521
+ 'name' => 'Enterprise',
522
+ 'username' => 'picard',
523
+ 'password' => 'livingston'
524
+ }
525
+ ],
526
+ 'groups' => {}
527
+ })
528
+ site = group.site(0)
529
+
530
+ called = false
531
+ group.after_event do |event|
532
+ called = true
533
+ assert_same group, event.owner
534
+ assert_equal 'change', event.name
535
+ assert_not_nil event.parent
536
+ assert_same site, event.parent.owner
537
+ end
538
+ site.password = "crusher"
539
+ assert called
540
+ end
541
+
542
+ test "site password changed callback for subgroup" do
543
+ group = new_group("Starships")
544
+ subgroup = new_group("Galaxy class")
545
+ group.add_group(subgroup)
546
+ site = new_site("Enterprise", "picard", "livingston")
547
+ subgroup.add_site(site)
548
+
549
+ called = false
550
+ group.after_event do |event|
551
+ called = true
552
+ assert_same group, event.owner
553
+ assert_equal 'change', event.name
554
+ assert_not_nil event.parent
555
+ assert_same subgroup, event.parent.owner
556
+ assert_not_nil event.parent.parent
557
+ assert_same site, event.parent.parent.owner
558
+ end
559
+ site.password = "crusher"
560
+ assert called
561
+ end
562
+
563
+ test "site removed callback" do
564
+ group = new_group("Starships")
565
+ site = new_site("Enterprise", "picard", "livingston")
566
+ group.add_site(site)
567
+
568
+ called = false
569
+ group.after_event do |event|
570
+ called = true
571
+ assert_same group, event.owner
572
+ assert_equal 'remove', event.name
573
+ assert_equal 'sites', event.collection_name
574
+ assert_same site, event.object
575
+ end
576
+ group.remove_site(site)
577
+ assert called
578
+ end
579
+
580
+ test "site removed callback for subgroup" do
581
+ group = new_group("Starships")
582
+ subgroup = new_group("Galaxy class")
583
+ group.add_group(subgroup)
584
+ site = new_site("Enterprise", "picard", "livingston")
585
+ subgroup.add_site(site)
586
+
587
+ called = false
588
+ group.after_event do |event|
589
+ called = true
590
+ assert_same group, event.owner
591
+ assert_equal 'change', event.name
592
+ assert_not_nil event.parent
593
+ assert_same subgroup, event.parent.owner
594
+ end
595
+ subgroup.remove_site(site)
596
+ assert called
597
+ end
598
+
599
+ test "group added callback" do
600
+ group = new_group("Starships")
601
+ subgroup = new_group("Klingon")
602
+
603
+ called = false
604
+ group.after_event do |event|
605
+ called = true
606
+ assert_same group, event.owner
607
+ assert_equal 'add', event.name
608
+ assert_equal 'groups', event.collection_name
609
+ assert_same subgroup, event.object
610
+ end
611
+ group.add_group(subgroup)
612
+ assert called
613
+ end
614
+
615
+ test "group added callback for subgroup" do
616
+ group = new_group("Starships")
617
+ subgroup = new_group("Galaxy class")
618
+ group.add_group(subgroup)
619
+ subsubgroup = new_group("Flagships")
620
+
621
+ called = false
622
+ group.after_event do |event|
623
+ called = true
624
+ assert_same group, event.owner
625
+ assert_equal 'change', event.name
626
+ assert_not_nil event.parent
627
+ assert_same subgroup, event.parent.owner
628
+ end
629
+ subgroup.add_group(subsubgroup)
630
+ assert called
631
+ end
632
+
633
+ test "group removed callback" do
634
+ group = new_group("Starships")
635
+ subgroup = new_group("Klingon")
636
+ group.add_group(subgroup)
637
+
638
+ called = false
639
+ group.after_event do |event|
640
+ called = true
641
+ assert_same group, event.owner
642
+ assert_equal 'remove', event.name
643
+ assert_equal 'groups', event.collection_name
644
+ assert_same subgroup, event.object
645
+ end
646
+ group.remove_group("Klingon")
647
+ assert called
648
+ end
649
+
650
+ test "group removed callback for subgroup" do
651
+ group = new_group("Starships")
652
+ subgroup = new_group("Galaxy class")
653
+ group.add_group(subgroup)
654
+ subsubgroup = new_group("Flagships")
655
+ subgroup.add_group(subsubgroup)
656
+
657
+ called = false
658
+ group.after_event do |event|
659
+ called = true
660
+ assert_same group, event.owner
661
+ assert_equal 'change', event.name
662
+ assert_not_nil event.parent
663
+ assert_same subgroup, event.parent.owner
664
+ end
665
+ subgroup.remove_group("Flagships")
666
+ assert called
667
+ end
668
+
669
+ test "to_yaml" do
670
+ group = new_group("Starships")
671
+ site = new_site("Enterprise", "picard", "livingston")
672
+ group.add_site(site)
673
+ subgroup = new_group("Klingon")
674
+ subsite = new_site("Bortas", "gowron", "bat'leth")
675
+ subgroup.add_site(subsite)
676
+ group.add_group(subgroup)
677
+
678
+ expected = {
679
+ 'name' => "Starships",
680
+ 'sites' => [
681
+ {
682
+ 'name' => "Enterprise",
683
+ 'username' => 'picard',
684
+ 'password' => 'livingston'
685
+ }
686
+ ],
687
+ 'groups' => {
688
+ "Klingon" => {
689
+ 'name' => "Klingon",
690
+ 'sites' => [
691
+ {
692
+ 'name' => "Bortas",
693
+ 'username' => 'gowron',
694
+ 'password' => "bat'leth"
695
+ }
696
+ ],
697
+ 'groups' => {}
698
+ }
699
+ }
700
+ }.to_yaml
701
+ assert_equal expected, group.to_yaml
702
+ end
703
+ end