rouster 0.5 → 0.7

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -1
  3. data/.reek +63 -0
  4. data/.travis.yml +11 -0
  5. data/Gemfile +17 -0
  6. data/Gemfile.lock +102 -0
  7. data/README.md +233 -7
  8. data/Rakefile +52 -34
  9. data/Vagrantfile +26 -8
  10. data/examples/aws.rb +85 -0
  11. data/examples/openstack.rb +61 -0
  12. data/examples/passthrough.rb +71 -0
  13. data/lib/rouster.rb +380 -262
  14. data/lib/rouster/deltas.rb +470 -138
  15. data/lib/rouster/puppet.rb +155 -26
  16. data/lib/rouster/testing.rb +205 -46
  17. data/lib/rouster/tests.rb +40 -11
  18. data/lib/rouster/vagrant.rb +311 -0
  19. data/path_helper.rb +3 -4
  20. data/plugins/aws.rb +347 -0
  21. data/plugins/openstack.rb +136 -0
  22. data/test/basic.rb +4 -1
  23. data/test/functional/deltas/test_get_crontab.rb +64 -2
  24. data/test/functional/deltas/test_get_groups.rb +74 -2
  25. data/test/functional/deltas/test_get_os.rb +68 -0
  26. data/test/functional/deltas/test_get_packages.rb +73 -6
  27. data/test/functional/deltas/test_get_ports.rb +26 -1
  28. data/test/functional/deltas/test_get_services.rb +43 -5
  29. data/test/functional/deltas/test_get_users.rb +35 -2
  30. data/test/functional/puppet/test_facter.rb +41 -1
  31. data/test/functional/test_caching.rb +2 -2
  32. data/test/functional/test_inspect.rb +1 -1
  33. data/test/functional/test_is_file.rb +17 -1
  34. data/test/functional/test_is_in_file.rb +40 -0
  35. data/test/functional/test_new.rb +233 -22
  36. data/test/functional/test_passthroughs.rb +94 -0
  37. data/test/functional/test_put.rb +2 -2
  38. data/test/functional/test_validate_file.rb +104 -3
  39. data/test/puppet/test_apply.rb +8 -6
  40. data/test/unit/puppet/resources/puppet_run_with_failed_exec +59 -0
  41. data/test/unit/puppet/resources/puppet_run_with_successful_exec +61 -0
  42. data/test/unit/puppet/test_get_puppet_star.rb +27 -4
  43. data/test/unit/puppet/test_puppet_parsing.rb +44 -0
  44. data/test/unit/test_new.rb +88 -0
  45. data/test/unit/test_parse_ls_string.rb +67 -0
  46. data/test/unit/testing/resources/osx-launchd +285 -0
  47. data/test/unit/testing/resources/rhel-systemd +46 -0
  48. data/test/unit/testing/resources/rhel-systemv +41 -0
  49. data/test/unit/testing/resources/rhel-upstart +20 -0
  50. data/test/unit/testing/test_get_services.rb +178 -0
  51. data/test/unit/testing/test_validate_cron.rb +78 -0
  52. data/test/unit/testing/test_validate_package.rb +36 -10
  53. data/test/unit/testing/test_validate_port.rb +5 -0
  54. metadata +42 -21
  55. data/test/puppet/test_roles.rb +0 -186
@@ -5,6 +5,9 @@ require 'rouster/puppet'
5
5
  require 'rouster/testing'
6
6
  require 'rouster/tests'
7
7
 
8
- p = Rouster.new(:name => 'app', :verbosity => 0)
8
+ #a = Rouster.new(:name => 'app', :verbosity => 1, :vagrantfile => '../piab/Vagrantfile', :retries => 3)
9
+ #p = Rouster.new(:name => 'ppm', :verbosity => 1, :vagrantfile => '../piab/Vagrantfile')
10
+ #r = Rouster.new(:name => 'app', :verbosity => 1, :vagrantfile => 'Vagrantfile')
11
+ l = Rouster.new(:name => 'local', :passthrough => { :type => :local }, :verbosity => 3)
9
12
 
10
13
  p 'DBGZ' if nil?
@@ -8,7 +8,7 @@ class TestDeltasGetCrontab < Test::Unit::TestCase
8
8
 
9
9
  def setup
10
10
  assert_nothing_raised do
11
- @app = Rouster.new(:name => 'app')
11
+ @app = Rouster.new(:name => 'app', :cache_timeout => 20)
12
12
  end
13
13
 
14
14
  @app.up()
@@ -92,8 +92,70 @@ class TestDeltasGetCrontab < Test::Unit::TestCase
92
92
 
93
93
  end
94
94
 
95
+ def test_happy_path_cache_invalidated
96
+
97
+ res1, res2 = nil, nil
98
+
99
+ assert_nothing_raised do
100
+ res1 = @app.get_crontab('root', true)
101
+ end
102
+
103
+ first_cache_time = @app.cache[:crontab]
104
+
105
+ sleep (@app.cache_timeout + 1)
106
+
107
+ assert_nothing_raised do
108
+ res2 = @app.get_crontab('root', true)
109
+ end
110
+
111
+ second_cache_time = @app.cache[:crontab]
112
+
113
+ assert_equal(res1, res2)
114
+ assert_not_equal(first_cache_time, second_cache_time)
115
+
116
+ end
117
+
118
+ def test_unhappy_duplicate_entries
119
+
120
+ res = nil
121
+
122
+ # do this in a saner way? crontab call is overwriting existing records
123
+ user = 'puppet'
124
+ tmp = sprintf('/tmp/rouster.tmp.crontab.%s.%s.%s', user, Time.now.to_i, $$)
125
+ @app.run("echo '0 0 * * * echo #{user}' > #{tmp}")
126
+ @app.run("echo '5 5 * * * echo #{user}' >> #{tmp}")
127
+ @app.run("crontab -u #{user} #{tmp}")
128
+
129
+ assert_nothing_raised do
130
+ res = @app.get_crontab(user)
131
+ end
132
+
133
+ assert_equal(Hash, res.class)
134
+ assert(res.has_key?('echo puppet'))
135
+ assert(res.has_key?('echo puppet-duplicate.55***echopuppet'))
136
+
137
+ end
138
+
139
+ def test_non_matching_lines
140
+ res = nil
141
+ user = 'root'
142
+ tmp = sprintf('/tmp/rouster.tmp.crontab.%s.%s.%s', user, Time.now.to_i, $$)
143
+
144
+ @app.run("echo 'PATH=/sbin:/usr/bin:/usr/local/bin' > #{tmp}")
145
+ @app.run("echo '5 5 * * * echo #{user}' >> #{tmp}")
146
+ @app.run("crontab -u #{user} #{tmp}")
147
+
148
+ assert_nothing_raised do
149
+ res = @app.get_crontab(user, false)
150
+ end
151
+
152
+ assert_equal(Hash, res.class)
153
+ assert(res.has_key?('echo root'))
154
+
155
+ end
156
+
95
157
  def teardown
96
158
  @app = nil
97
159
  end
98
160
 
99
- end
161
+ end
@@ -8,7 +8,7 @@ class TestDeltasGetGroups < Test::Unit::TestCase
8
8
 
9
9
  def setup
10
10
  assert_nothing_raised do
11
- @app = Rouster.new(:name => 'app')
11
+ @app = Rouster.new(:name => 'app', :cache_timeout => 10)
12
12
  end
13
13
 
14
14
  @app.up()
@@ -39,7 +39,79 @@ class TestDeltasGetGroups < Test::Unit::TestCase
39
39
 
40
40
  end
41
41
 
42
- # TODO add some non-caching tests
42
+ def test_without_caching
43
+ old_groups, new_groups = nil, nil
44
+
45
+ assert_nothing_raised do
46
+ old_groups = @app.get_groups(false)
47
+ end
48
+
49
+ assert_nil(@app.deltas[:groups])
50
+
51
+ new_group = sprintf('rouster-%s', Time.now.to_i)
52
+
53
+ ## create a group here
54
+ if @app.os_type.eql?(:rhel)
55
+ @app.run(sprintf('groupadd %s', new_group))
56
+ else
57
+ omit('only doing group creation on RHEL hosts')
58
+ end
59
+
60
+ assert_nothing_raised do
61
+ new_groups = @app.get_groups(false)
62
+ end
63
+
64
+ assert_nil(@app.deltas[:groups])
65
+ assert_not_nil(new_groups[new_group])
66
+ assert_not_equal(old_groups, new_groups)
67
+
68
+ end
69
+
70
+ def test_deep_inspection
71
+ deep, shallow = nil, nil
72
+
73
+ assert_nothing_raised do
74
+ deep = @app.get_groups(false, true)
75
+ shallow = @app.get_groups(false, false)
76
+ end
77
+
78
+ assert_not_equal(deep, shallow)
79
+
80
+ ## this is not really the best test
81
+ deep_none, shallow_none = 0, 0
82
+
83
+ deep.each_key do |group|
84
+ deep_none += 1 if deep[group][:users][0].eql?('NONE')
85
+ end
86
+
87
+ shallow.each_key do |group|
88
+ shallow_none += 1 if shallow[group][:users][0].eql?('NONE')
89
+ end
90
+
91
+ assert(shallow_none > deep_none)
92
+ end
93
+
94
+ def test_happy_path_cache_invalidation
95
+ res1, res2 = nil, nil
96
+
97
+ assert_nothing_raised do
98
+ res1 = @app.get_groups(true, false)
99
+ end
100
+
101
+ first_cache_time = @app.cache[:groups]
102
+
103
+ sleep (@app.cache_timeout + 1)
104
+
105
+ assert_nothing_raised do
106
+ res2 = @app.get_groups(true, false)
107
+ end
108
+
109
+ second_cache_time = @app.cache[:groups]
110
+
111
+ assert_equal(res1, res2)
112
+ assert_not_equal(first_cache_time, second_cache_time)
113
+
114
+ end
43
115
 
44
116
  def teardown
45
117
  @app = nil
@@ -0,0 +1,68 @@
1
+ require sprintf('%s/../../../path_helper', File.dirname(File.expand_path(__FILE__)))
2
+
3
+ require 'rouster'
4
+ require 'rouster/puppet'
5
+ require 'rouster/testing'
6
+ require 'test/unit'
7
+
8
+ class TestValidateFileFunctional < Test::Unit::TestCase
9
+
10
+ def setup
11
+ # expose private methods
12
+ Rouster.send(:public, *Rouster.private_instance_methods)
13
+ Rouster.send(:public, *Rouster.protected_instance_methods)
14
+
15
+ @app = Rouster.new(:name => 'app')
16
+ end
17
+
18
+ def teardown
19
+ # put the flag file back in place
20
+ Rouster.os_files.each_pair do |_os, ff|
21
+ [ ff ].flatten.each do |f|
22
+ bkup = sprintf('%s.bkup', f)
23
+ if @app.is_file?(bkup)
24
+ @app.run(sprintf('mv %s %s', bkup, f))
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ def test_happy_path
31
+
32
+ type = @app.os_type
33
+ assert_not_nil(type, sprintf('unable to determine vm[%s] OS', @app))
34
+ assert_not_equal(:invalid, type)
35
+
36
+ version = @app.os_version(type)
37
+ assert_not_nil(version, sprintf('unable to determine vm[%s] OS version', @app))
38
+ assert_not_equal(:invalid, version)
39
+
40
+ assert_nothing_raised do
41
+ @app.get_services
42
+ end
43
+
44
+ end
45
+
46
+ def test_unhappy_path
47
+ # move the flag file out of the way
48
+ Rouster.os_files.each_pair do |_os, ff|
49
+ [ ff ].flatten.each do |f|
50
+ if @app.is_file?(ff)
51
+ @app.run(sprintf('mv %s %s.bkup', f, f))
52
+ end
53
+ end
54
+ end
55
+
56
+ type = @app.os_type
57
+
58
+ assert_equal(:invalid, type, sprintf('got wrong value for unmarked OS[%s]', type))
59
+
60
+ e = assert_raise do
61
+ @app.get_services
62
+ end
63
+
64
+ assert_equal(Rouster::InternalError, e.class, sprintf('wrong exception raised[%s] [%s]', e.class, e.message))
65
+
66
+ end
67
+
68
+ end
@@ -10,7 +10,7 @@ class TestDeltasGetPackages < Test::Unit::TestCase
10
10
 
11
11
  def setup
12
12
  assert_nothing_raised do
13
- @app = Rouster.new(:name => 'app')
13
+ @app = Rouster.new(:name => 'app', :cache_timeout => 10)
14
14
  end
15
15
 
16
16
  @app.up()
@@ -30,7 +30,17 @@ class TestDeltasGetPackages < Test::Unit::TestCase
30
30
 
31
31
  res.each_key do |k|
32
32
  assert_not_nil(res[k])
33
- assert_match(/^\d+/, res[k]) # start with a number
33
+
34
+ if res[k].is_a?(Array)
35
+ res[k].each do |l|
36
+ assert(l.has_key?(:arch))
37
+ assert(l.has_key?(:version))
38
+ end
39
+ else
40
+ assert(res[k].has_key?(:arch))
41
+ assert(res[k].has_key?(:version))
42
+ end
43
+
34
44
  end
35
45
 
36
46
  end
@@ -55,11 +65,68 @@ class TestDeltasGetPackages < Test::Unit::TestCase
55
65
  res = @app.get_packages(true, false)
56
66
  end
57
67
 
58
- res.each_key do |k|
59
- assert_not_nil(res[k])
68
+ # RHEL processing doesn't do anything different in deep/not-deep calls
69
+ if ! (@app.os_type.eql?(:rhel) or @app.os_type.eql?(:ubuntu))
70
+ res.each_key do |k|
71
+ assert_not_nil(res[k])
72
+ assert_match(/\?/, res[k][:arch])
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ def test_happy_path_cache_invalidation
79
+ res1, res2 = nil, nil
80
+
81
+ assert_nothing_raised do
82
+ res1 = @app.get_packages(true, false)
83
+ end
84
+
85
+ first_cache_time = @app.cache[:packages]
86
+
87
+ sleep (@app.cache_timeout + 1)
88
+
89
+ assert_nothing_raised do
90
+ res2 = @app.get_packages(true, false)
91
+ end
92
+
93
+ second_cache_time = @app.cache[:packages]
94
+
95
+ assert_equal(res1, res2)
96
+ assert_not_equal(first_cache_time, second_cache_time)
97
+ assert(second_cache_time > first_cache_time)
98
+
99
+ end
60
100
 
61
- #assert_match(/\d*\..*/, res[k]) # testing the regular expression used in deltas.rb itself
62
- assert_match(/\?/, res[k])
101
+ def test_arch_determination
102
+ after, install = nil, nil
103
+
104
+ if @app.os_type.eql?(:rhel)
105
+ packages = [ 'glibc.x86_64', 'glibc.i686' ]
106
+ install = @app.run(sprintf('yum install -y %s', packages.join(' '))) # TODO these are already in the base, but just to be safe
107
+ after = @app.get_packages(false, false)
108
+
109
+ assert(after.has_key?('glibc'))
110
+ assert(after['glibc'].is_a?(Array))
111
+ assert_equal(after['glibc'].length, 2)
112
+ assert_not_equal(after['glibc'][0][:arch], after['glibc'][1][:arch])
113
+ elsif @app.os_type.eql?(:ubuntu)
114
+ packages = @app.get_packages(false, false)
115
+
116
+ assert(packages.has_key?('xml-core'))
117
+ assert(packages.has_key?('whiptail'))
118
+ assert(packages['xml-core'].has_key?(:version))
119
+ assert(packages['whiptail'].has_key?(:version))
120
+
121
+ assert_equal(packages['xml-core'][:arch], 'all')
122
+ assert_equal(packages['whiptail'][:arch], 'amd64')
123
+
124
+ else
125
+ # TODO should throw a flag here..
126
+ assert_nothing_raised do
127
+ @app.get_packages(false, true)
128
+ @app.get_packages(false, false)
129
+ end
63
130
  end
64
131
 
65
132
  end
@@ -8,7 +8,7 @@ class TestDeltasGetPorts < Test::Unit::TestCase
8
8
 
9
9
  def setup
10
10
  assert_nothing_raised do
11
- @app = Rouster.new(:name => 'app')
11
+ @app = Rouster.new(:name => 'app', :cache_timeout => 10)
12
12
  end
13
13
 
14
14
  @app.up()
@@ -95,6 +95,7 @@ class TestDeltasGetPorts < Test::Unit::TestCase
95
95
  }
96
96
 
97
97
  @app.deltas[:ports] = stock
98
+ @app.cache[:ports] = Time.now.to_i # since we're faking the contents, we also need to fake other artifacts that would have been generated
98
99
 
99
100
  assert_equal(true, @app.is_port_open?(1234, 'tcp', true))
100
101
  assert_equal(true, @app.is_port_active?(22, 'tcp', true))
@@ -107,11 +108,35 @@ class TestDeltasGetPorts < Test::Unit::TestCase
107
108
  assert_equal(false, @app.is_port_active?(1234, 'tcp', true))
108
109
 
109
110
  # caching/argument default validation -- can't currently do this, don't know what ports will be open on others systems
111
+ # TODO but can fix this by running some ncatish commands
110
112
  #assert_equal(true, @app.is_port_active?(22))
111
113
  #assert_equal(true, @app.is_port_open?(1234))
112
114
 
113
115
  end
114
116
 
117
+ def test_happy_path_cache_invalidation
118
+ res1, res2 = nil, nil
119
+
120
+ assert_nothing_raised do
121
+ res1 = @app.get_ports(true)
122
+ end
123
+
124
+ first_cache_time = @app.cache[:ports]
125
+
126
+ sleep (@app.cache_timeout + 1)
127
+
128
+ assert_nothing_raised do
129
+ res2 = @app.get_ports(true)
130
+ end
131
+
132
+ second_cache_time = @app.cache[:ports]
133
+
134
+ assert_equal(res1, res2)
135
+ assert_not_equal(first_cache_time, second_cache_time)
136
+ assert(second_cache_time > first_cache_time)
137
+
138
+ end
139
+
115
140
  def teardown
116
141
  @app = nil
117
142
  end
@@ -8,13 +8,12 @@ class TestDeltasGetServices < Test::Unit::TestCase
8
8
 
9
9
  def setup
10
10
  assert_nothing_raised do
11
- @app = Rouster.new(:name => 'app')
11
+ @app = Rouster.new(:name => 'app', :cache_timeout => 10)
12
12
  end
13
13
 
14
14
  @app.up()
15
15
 
16
- # eventually this should be standardized (and symbolized?)
17
- @allowed_states = %w(exists operational running stopped)
16
+ @allowed_states = %w(exists installed operational running stopped unsure)
18
17
  end
19
18
 
20
19
  def test_happy_path
@@ -29,12 +28,51 @@ class TestDeltasGetServices < Test::Unit::TestCase
29
28
 
30
29
  res.each_key do |k|
31
30
  assert_not_nil(res[k])
32
- #assert(@allowed_states.member?(res[k]))
31
+ assert(@allowed_states.member?(res[k]))
33
32
  end
34
33
 
34
+ # this isn't the best validation, but does prove a point - no nil keys/values
35
+ assert_nothing_raised do
36
+ res.keys.sort
37
+ res.values.sort
38
+ end
39
+
40
+ end
41
+
42
+ def test_happy_path_caching
43
+
44
+ assert_nil(@app.deltas[:services])
45
+
46
+ assert_nothing_raised do
47
+ @app.get_services(true)
48
+ end
49
+
50
+ assert_equal(Hash, @app.deltas[:services].class)
51
+
35
52
  end
36
53
 
37
- # TODO add some caching tests
54
+ def test_happy_path_cache_invalidation
55
+ res1, res2 = nil, nil
56
+
57
+ assert_nothing_raised do
58
+ res1 = @app.get_services(true)
59
+ end
60
+
61
+ first_cache_time = @app.cache[:services]
62
+
63
+ sleep (@app.cache_timeout + 1)
64
+
65
+ assert_nothing_raised do
66
+ res2 = @app.get_services(true)
67
+ end
68
+
69
+ second_cache_time = @app.cache[:services]
70
+
71
+ assert_equal(res1, res2)
72
+ assert_not_equal(first_cache_time, second_cache_time)
73
+ assert(second_cache_time > first_cache_time)
74
+
75
+ end
38
76
 
39
77
  def teardown
40
78
  @app = nil