rouster 0.5

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.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/LICENSE +9 -0
  4. data/README.md +175 -0
  5. data/Rakefile +65 -0
  6. data/Vagrantfile +23 -0
  7. data/examples/bootstrap.rb +113 -0
  8. data/examples/demo.rb +71 -0
  9. data/examples/error.rb +30 -0
  10. data/lib/rouster.rb +737 -0
  11. data/lib/rouster/deltas.rb +481 -0
  12. data/lib/rouster/puppet.rb +398 -0
  13. data/lib/rouster/testing.rb +743 -0
  14. data/lib/rouster/tests.rb +596 -0
  15. data/path_helper.rb +21 -0
  16. data/rouster.gemspec +30 -0
  17. data/test/basic.rb +10 -0
  18. data/test/functional/deltas/test_get_crontab.rb +99 -0
  19. data/test/functional/deltas/test_get_groups.rb +48 -0
  20. data/test/functional/deltas/test_get_packages.rb +71 -0
  21. data/test/functional/deltas/test_get_ports.rb +119 -0
  22. data/test/functional/deltas/test_get_services.rb +43 -0
  23. data/test/functional/deltas/test_get_users.rb +45 -0
  24. data/test/functional/puppet/test_facter.rb +59 -0
  25. data/test/functional/test_caching.rb +124 -0
  26. data/test/functional/test_destroy.rb +51 -0
  27. data/test/functional/test_dirs.rb +88 -0
  28. data/test/functional/test_files.rb +64 -0
  29. data/test/functional/test_get.rb +76 -0
  30. data/test/functional/test_inspect.rb +31 -0
  31. data/test/functional/test_is_dir.rb +118 -0
  32. data/test/functional/test_is_file.rb +119 -0
  33. data/test/functional/test_new.rb +92 -0
  34. data/test/functional/test_put.rb +81 -0
  35. data/test/functional/test_rebuild.rb +49 -0
  36. data/test/functional/test_restart.rb +44 -0
  37. data/test/functional/test_run.rb +77 -0
  38. data/test/functional/test_status.rb +38 -0
  39. data/test/functional/test_suspend.rb +31 -0
  40. data/test/functional/test_up.rb +27 -0
  41. data/test/functional/test_validate_file.rb +30 -0
  42. data/test/puppet/manifests/default.pp +9 -0
  43. data/test/puppet/manifests/hiera.yaml +12 -0
  44. data/test/puppet/manifests/hieradata/common.json +3 -0
  45. data/test/puppet/manifests/hieradata/vagrant.json +3 -0
  46. data/test/puppet/manifests/manifest.pp +78 -0
  47. data/test/puppet/modules/role/manifests/ui.pp +5 -0
  48. data/test/puppet/test_apply.rb +149 -0
  49. data/test/puppet/test_roles.rb +186 -0
  50. data/test/tunnel_vs_scp.rb +41 -0
  51. data/test/unit/puppet/test_get_puppet_star.rb +68 -0
  52. data/test/unit/test_generate_unique_mac.rb +43 -0
  53. data/test/unit/test_new.rb +31 -0
  54. data/test/unit/test_parse_ls_string.rb +334 -0
  55. data/test/unit/test_traverse_up.rb +43 -0
  56. data/test/unit/testing/test_meets_constraint.rb +55 -0
  57. data/test/unit/testing/test_validate_file.rb +112 -0
  58. data/test/unit/testing/test_validate_group.rb +72 -0
  59. data/test/unit/testing/test_validate_package.rb +69 -0
  60. data/test/unit/testing/test_validate_port.rb +98 -0
  61. data/test/unit/testing/test_validate_service.rb +73 -0
  62. data/test/unit/testing/test_validate_user.rb +92 -0
  63. metadata +203 -0
@@ -0,0 +1,45 @@
1
+ require sprintf('%s/../../../path_helper', File.dirname(File.expand_path(__FILE__)))
2
+
3
+ require 'rouster'
4
+ require 'rouster/deltas'
5
+ require 'test/unit'
6
+
7
+ class TestDeltasGetUsers < Test::Unit::TestCase
8
+
9
+ def setup
10
+ assert_nothing_raised do
11
+ @app = Rouster.new(:name => 'app')
12
+ end
13
+
14
+ @app.up()
15
+ end
16
+
17
+ def test_happy_path
18
+ res = nil
19
+
20
+ assert_nothing_raised do
21
+ res = @app.get_users()
22
+ end
23
+
24
+ assert_equal(Hash, res.class)
25
+ assert_not_nil(@app.deltas[:users])
26
+
27
+ res.each_key do |k|
28
+ assert_not_nil(res[k][:shell])
29
+ assert_not_nil(res[k][:uid])
30
+ assert_match(/^\d+$/, res[k][:uid])
31
+ assert_not_nil(res[k][:gid])
32
+ assert_match(/^\d+$/, res[k][:gid])
33
+ assert_not_nil(res[k][:home])
34
+ assert_not_nil(res[k][:home_exists])
35
+ end
36
+
37
+ end
38
+
39
+ # TODO add some caching tests
40
+
41
+ def teardown
42
+ @app = nil
43
+ end
44
+
45
+ end
@@ -0,0 +1,59 @@
1
+ require sprintf('%s/../../../path_helper', File.dirname(File.expand_path(__FILE__)))
2
+
3
+ require 'rouster'
4
+ require 'rouster/puppet'
5
+ require 'test/unit'
6
+
7
+ class TestFacter < Test::Unit::TestCase
8
+
9
+ def setup
10
+ assert_nothing_raised do
11
+ @app = Rouster.new(:name => 'app')
12
+ end
13
+
14
+ @app.up()
15
+ end
16
+
17
+ def test_happy_path
18
+
19
+ facts = nil
20
+
21
+ assert_nothing_raised do
22
+ facts = @app.facter()
23
+ end
24
+
25
+ assert_equal(true, facts.class.eql?(Hash))
26
+ assert_equal(facts, @app.facts)
27
+ end
28
+
29
+ def test_negative_caching
30
+
31
+ facts = nil
32
+
33
+ assert_nothing_raised do
34
+ facts = @app.facter(false)
35
+ end
36
+
37
+ assert_equal(true, facts.class.eql?(Hash))
38
+ assert_equal(nil, @app.facts)
39
+ end
40
+
41
+ def test_custom_facts
42
+
43
+ facts = nil
44
+
45
+ assert_nothing_raised do
46
+ facts = @app.facter(false, false)
47
+ end
48
+
49
+ assert_equal(true, facts.class.eql?(Hash))
50
+
51
+ # need to come up with definitive test to not include custom facts, unsure how exactly we should do this
52
+
53
+ end
54
+
55
+ def teardown
56
+ # noop
57
+ end
58
+
59
+ end
@@ -0,0 +1,124 @@
1
+ require sprintf('%s/../../path_helper', File.dirname(File.expand_path(__FILE__)))
2
+
3
+ require 'rouster'
4
+ require 'test/unit'
5
+
6
+ class TestCaching < Test::Unit::TestCase
7
+
8
+ def setup
9
+ # expose private methods
10
+ Rouster.send(:public, *Rouster.protected_instance_methods)
11
+ end
12
+
13
+ def test_status_caching
14
+ timeout = 5
15
+ app = Rouster.new(:name => 'app', :cache_timeout => timeout)
16
+
17
+ assert_equal(app.cache_timeout, timeout)
18
+
19
+ status_orig = app.status()
20
+
21
+ assert_not_nil(app.cache[:status])
22
+ status_orig_time = app.cache[:status][:time]
23
+
24
+ assert_equal(status_orig, app.cache[:status][:status])
25
+
26
+ status_new = app.status()
27
+ status_new_time = app.cache[:status][:time]
28
+
29
+ assert_equal(status_orig, status_new)
30
+ assert_equal(status_orig_time, status_new_time)
31
+
32
+ app.status()
33
+ status_orig_time = app.cache[:status][:time]
34
+ sleep(timeout + 1)
35
+
36
+ app.status()
37
+ status_new_time = app.cache[:status][:time]
38
+
39
+ assert_not_equal(status_orig_time, status_new_time)
40
+
41
+ end
42
+
43
+ def test_status_caching_functional
44
+ timeout = 5
45
+ app = Rouster.new(:name => 'app', :cache_timeout => timeout)
46
+
47
+ status_orig = app.status()
48
+ status_orig_time = app.cache[:status][:time]
49
+
50
+ if status_orig.eql?('running')
51
+ app.suspend()
52
+ elsif status_orig.eql?('not created')
53
+ app.up()
54
+ else
55
+ # should just be suspended/saved
56
+ app.destroy()
57
+ end
58
+
59
+ sleep(timeout) # this is almost certainly unnecessary, given the amount of time the above operations take, but just being safe
60
+
61
+ status_new = app.status()
62
+ status_new_time = app.cache[:status][:time]
63
+
64
+ assert_not_equal(status_orig, status_new)
65
+ assert_not_equal(status_orig_time, status_new_time)
66
+
67
+ end
68
+
69
+ def test_status_caching_negative
70
+ app = Rouster.new(:name => 'app')
71
+
72
+ app.status()
73
+ assert_nil(app.cache[:status])
74
+ end
75
+
76
+ def test_ssh_caching
77
+
78
+ skip('see comments in rouster.rb line ~84')
79
+
80
+ timeout = 100
81
+ app = Rouster.new(:name => 'app', :sshtunnel => true, :cache_timeout => timeout)
82
+ app.up()
83
+
84
+ assert_equal(app.cache_timeout, timeout)
85
+
86
+ avail_orig = app.is_available_via_ssh?
87
+ assert_not_nil(app.cache[:is_available_via_ssh?])
88
+
89
+ avail_orig_time = app.cache[:is_available_via_ssh?][:time]
90
+ assert_equal(avail_orig, app.cache[:is_available_via_ssh?][:status])
91
+
92
+ avail_new = app.is_available_via_ssh?
93
+ avail_new_time = app.cache[:is_available_via_ssh?][:time]
94
+
95
+ assert_equal(avail_orig, avail_new)
96
+ assert_equal(avail_new_time, avail_orig_time)
97
+
98
+ app.is_available_via_ssh?
99
+ avail_orig_time = app.cache[:is_available_via_ssh?][:time]
100
+
101
+ sleep(timeout + 1)
102
+
103
+ app.is_available_via_ssh?
104
+ avail_new_time = app.cache[:is_available_via_ssh?][:time]
105
+
106
+ assert_not_equal(avail_orig_time, avail_new_time)
107
+ end
108
+
109
+ def test_ssh_caching_functional
110
+ # noop
111
+ end
112
+
113
+ def test_ssh_caching_negative
114
+ app = Rouster.new(:name => 'app')
115
+
116
+ app.is_available_via_ssh?()
117
+ assert_nil(app.cache[:is_available_via_ssh?])
118
+ end
119
+
120
+ def teardown
121
+ # noop
122
+ end
123
+
124
+ end
@@ -0,0 +1,51 @@
1
+ require sprintf('%s/../../path_helper', File.dirname(File.expand_path(__FILE__)))
2
+
3
+ require 'rouster'
4
+ require 'test/unit'
5
+
6
+ class TestDestroy < Test::Unit::TestCase
7
+
8
+ def setup
9
+ assert_nothing_raised do
10
+ @app = Rouster.new(:name => 'app')
11
+ end
12
+
13
+ @app.up()
14
+ assert_equal(@app.is_available_via_ssh?(), true)
15
+ end
16
+
17
+ def test_happy_path
18
+
19
+ assert_equal(@app.status(), 'running')
20
+
21
+ assert_nothing_raised do
22
+ @app.destroy()
23
+ end
24
+
25
+ assert_equal(false, @app.is_available_via_ssh?)
26
+ assert_equal('not created', @app.status())
27
+ end
28
+
29
+ def test_thats_what_we_call_overkill
30
+ assert_equal(@app.status(), 'running')
31
+
32
+ assert_nothing_raised do
33
+ @app.destroy()
34
+ end
35
+
36
+ assert_equal(false, @app.is_available_via_ssh?)
37
+ assert_equal('not created', @app.status())
38
+
39
+ assert_nothing_raised do
40
+ @app.destroy()
41
+ end
42
+
43
+ assert_equal('not created', @app.status())
44
+
45
+ end
46
+
47
+ def teardown
48
+ @app = nil
49
+ end
50
+
51
+ end
@@ -0,0 +1,88 @@
1
+ require sprintf('%s/../../path_helper', File.dirname(File.expand_path(__FILE__)))
2
+
3
+ require 'rouster'
4
+ require 'rouster/tests'
5
+ require 'test/unit'
6
+
7
+ class TestDirs < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @app = Rouster.new(:name => 'app', :verbose => 1)
11
+ @app.up()
12
+
13
+ @dir = sprintf('/tmp/rouster.dirs.%s/', Time.now.to_i)
14
+ end
15
+
16
+ def test_happy
17
+ dirs_expected = ['foo', 'bar', 'baz']
18
+
19
+ dirs_expected.each do |dir|
20
+ @app.run(sprintf('mkdir -p %s/%s', @dir, dir))
21
+ end
22
+
23
+ dirs_actual = @app.dirs(@dir)
24
+
25
+ # could totally use an is_deeply here..
26
+ dirs_actual.each do |dir|
27
+ dir = dir.gsub(/#{@dir}/, '') # remove the path prefix
28
+ assert(dirs_expected.member?(dir))
29
+ end
30
+
31
+ end
32
+
33
+ def test_happy_filter
34
+
35
+ dirs_to_create = ['foo', 'bar', 'baz']
36
+ dirs_expected = ['bar', 'baz']
37
+
38
+ dirs_to_create.each do |dir|
39
+ @app.run(sprintf('mkdir -p %s/%s', @dir, dir))
40
+ end
41
+
42
+ dirs_actual = @app.dirs(@dir, 'b*')
43
+
44
+ # would like to do some negative testing here
45
+ dirs_actual.each do |dir|
46
+ dir = dir.gsub(/#{@dir}/, '') # remove the path prefix
47
+ assert(dirs_expected.member?(dir))
48
+ end
49
+
50
+
51
+ end
52
+
53
+ def no_test_happy_recurse
54
+
55
+ raise NotImplementedError.new()
56
+
57
+ end
58
+
59
+ def test_case_sensitvity
60
+ dirs_to_create = ['Fizz', 'foo', 'baz']
61
+ dirs_expected_sensitive = ['foo']
62
+ dirs_expected_insensitive = ['Fizz', 'foo']
63
+
64
+ dirs_to_create.each do |dir|
65
+ @app.run(sprintf('mkdir -p %s/%s', @dir, dir))
66
+ end
67
+
68
+ dirs_actual_sensitive = @app.dirs(@dir, 'f*', false)
69
+
70
+ dirs_actual_sensitive.each do |dir|
71
+ dir = dir.gsub(/#{@dir}/, '')
72
+ assert(dirs_expected_sensitive.member?(dir))
73
+ end
74
+
75
+ dirs_actual_insensitive = @app.dirs(@dir, 'f*', true)
76
+
77
+ dirs_actual_insensitive.each do |dir|
78
+ dir = dir.gsub(/#{@dir}/, '')
79
+ assert(dirs_expected_insensitive.member?(dir))
80
+ end
81
+
82
+ end
83
+
84
+ def teardown
85
+ @app.run(sprintf('rm -rf %s', @dir))
86
+ end
87
+
88
+ end
@@ -0,0 +1,64 @@
1
+ require sprintf('%s/../../path_helper', File.dirname(File.expand_path(__FILE__)))
2
+
3
+ require 'rouster'
4
+ require 'rouster/tests'
5
+ require 'test/unit'
6
+
7
+ class TestFiles < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @app = Rouster.new(:name => 'app')
11
+ @app.up()
12
+
13
+ @dir = sprintf('/tmp/rouster.files.%s/', Time.now.to_i)
14
+ @app.run(sprintf('mkdir %s', @dir))
15
+ end
16
+
17
+ def test_happy
18
+ files_expected = ['foo', 'bar', 'baz']
19
+
20
+ files_expected.each do |file|
21
+ @app.run(sprintf('touch %s/%s', @dir, file))
22
+ end
23
+
24
+ files_actual = @app.files(@dir)
25
+
26
+ # could totally use an is_deeply here..
27
+ files_actual.each do |file|
28
+ file = file.gsub(/#{@dir}/, '') # remove the path prefix
29
+ assert(files_expected.member?(file))
30
+ end
31
+
32
+ end
33
+
34
+ def test_happy_filter
35
+
36
+ files_to_create = ['foo', 'bar', 'baz']
37
+ files_expected = ['bar', 'baz']
38
+
39
+ files_to_create.each do |file|
40
+ @app.run(sprintf('touch %s/%s', @dir, file))
41
+ end
42
+
43
+ files_actual = @app.files(@dir, 'b*')
44
+
45
+ # would like to do some negative testing here
46
+ files_actual.each do |file|
47
+ file = file.gsub(/#{@dir}/, '') # remove the path prefix
48
+ assert(files_expected.member?(file))
49
+ end
50
+
51
+ end
52
+
53
+ def no_test_happy_recurse
54
+
55
+ raise NotImplementedError.new()
56
+
57
+ end
58
+
59
+ def teardown
60
+ # noop
61
+ @app.run(sprintf('rm -r %s', @dir))
62
+ end
63
+
64
+ end
@@ -0,0 +1,76 @@
1
+ require sprintf('%s/../../path_helper', File.dirname(File.expand_path(__FILE__)))
2
+
3
+ require 'rouster'
4
+ require 'rouster/tests'
5
+ require 'test/unit'
6
+
7
+ class TestGet < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @app = Rouster.new(:name => 'app')
11
+
12
+ @app.up()
13
+
14
+ @kg_local_location = sprintf('/tmp/rouster-test_get_local.%s.%s', $$, Time.now.to_i)
15
+ @kg_local_location.freeze
16
+ @kg_remote_location = '/etc/hosts'
17
+ @kb_dne_location = '/tmp/this-doesnt_exist/and/never/will.txt'
18
+
19
+ File.delete(@kg_local_location) if File.file?(@kg_local_location).true?
20
+
21
+ assert_equal(@app.is_available_via_ssh?, true, 'app is available via SSH')
22
+ assert_equal(File.file?(@kg_local_location), false, 'test KG file not present')
23
+ end
24
+
25
+ def test_happy_path
26
+
27
+ assert_nothing_raised do
28
+ @app.get(@kg_remote_location, @kg_local_location)
29
+ end
30
+
31
+ assert(File.file?(@kg_local_location), 'downloaded file exists')
32
+ end
33
+
34
+ def test_local_path_dne
35
+
36
+ assert_raise Rouster::FileTransferError do
37
+ @app.get(@kg_remote_location, @kb_dne_location)
38
+
39
+ # TODO how can we check the contents of the expception message?
40
+ end
41
+
42
+ assert_equal(false, File.file?(@kg_local_location), 'known bad local path DNE')
43
+ end
44
+
45
+ def test_remote_path_dne
46
+
47
+ assert_raise Rouster::FileTransferError do
48
+ res = @app.get(@kb_dne_location, @kg_local_location)
49
+ assert_equal(false, res)
50
+ end
51
+
52
+ assert_equal(false, File.file?(@kg_local_location), 'known bad remote file path DNE')
53
+ end
54
+
55
+ def test_with_suspended_machine
56
+ @app.suspend()
57
+
58
+ #assert_raise Rouster::SSHConnectionError do <-- this is what we want when the connection is bad, as opposed to permission/disk space issues
59
+ assert_raise Rouster::FileTransferError do
60
+ @app.get(@kg_remote_location, @kg_local_location)
61
+ end
62
+
63
+ assert_equal(false, File.file?(@kg_local_location), 'when machine is suspended, unable to get from it')
64
+ end
65
+
66
+ def teardown
67
+ File.delete(@kg_local_location) if File.file?(@kg_local_location).true?
68
+ end
69
+
70
+ def self.shutdown
71
+ # TODO we should suspend instead if any test failed for triage
72
+ #@app.suspend()
73
+ #@ppm.suspend()
74
+ end
75
+
76
+ end