rouster 0.7 → 0.41

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -3
  3. data/README.md +7 -241
  4. data/Rakefile +18 -55
  5. data/Vagrantfile +8 -26
  6. data/lib/rouster.rb +183 -404
  7. data/lib/rouster/deltas.rb +118 -577
  8. data/lib/rouster/puppet.rb +34 -209
  9. data/lib/rouster/testing.rb +59 -366
  10. data/lib/rouster/tests.rb +19 -70
  11. data/path_helper.rb +7 -5
  12. data/rouster.gemspec +1 -3
  13. data/test/basic.rb +1 -4
  14. data/test/functional/deltas/test_get_groups.rb +2 -74
  15. data/test/functional/deltas/test_get_packages.rb +4 -86
  16. data/test/functional/deltas/test_get_ports.rb +1 -26
  17. data/test/functional/deltas/test_get_services.rb +4 -43
  18. data/test/functional/deltas/test_get_users.rb +2 -35
  19. data/test/functional/puppet/test_facter.rb +1 -41
  20. data/test/functional/puppet/test_get_puppet_star.rb +68 -0
  21. data/test/functional/test_caching.rb +1 -5
  22. data/test/functional/test_dirs.rb +0 -25
  23. data/test/functional/test_get.rb +6 -10
  24. data/test/functional/test_inspect.rb +1 -1
  25. data/test/functional/test_is_file.rb +1 -17
  26. data/test/functional/test_new.rb +22 -233
  27. data/test/functional/test_put.rb +11 -9
  28. data/test/functional/test_restart.rb +4 -1
  29. data/test/functional/test_run.rb +3 -2
  30. data/test/puppet/test_apply.rb +11 -13
  31. data/test/puppet/test_roles.rb +173 -0
  32. data/test/unit/test_new.rb +0 -88
  33. data/test/unit/test_parse_ls_string.rb +0 -67
  34. data/test/unit/testing/test_validate_file.rb +47 -39
  35. data/test/unit/testing/test_validate_package.rb +10 -36
  36. metadata +6 -46
  37. data/.reek +0 -63
  38. data/.travis.yml +0 -11
  39. data/Gemfile +0 -17
  40. data/Gemfile.lock +0 -102
  41. data/LICENSE +0 -9
  42. data/examples/aws.rb +0 -85
  43. data/examples/openstack.rb +0 -61
  44. data/examples/passthrough.rb +0 -71
  45. data/lib/rouster/vagrant.rb +0 -311
  46. data/plugins/aws.rb +0 -347
  47. data/plugins/openstack.rb +0 -136
  48. data/test/functional/deltas/test_get_crontab.rb +0 -161
  49. data/test/functional/deltas/test_get_os.rb +0 -68
  50. data/test/functional/test_is_in_file.rb +0 -40
  51. data/test/functional/test_passthroughs.rb +0 -94
  52. data/test/functional/test_validate_file.rb +0 -131
  53. data/test/unit/puppet/resources/puppet_run_with_failed_exec +0 -59
  54. data/test/unit/puppet/resources/puppet_run_with_successful_exec +0 -61
  55. data/test/unit/puppet/test_get_puppet_star.rb +0 -91
  56. data/test/unit/puppet/test_puppet_parsing.rb +0 -44
  57. data/test/unit/testing/resources/osx-launchd +0 -285
  58. data/test/unit/testing/resources/rhel-systemd +0 -46
  59. data/test/unit/testing/resources/rhel-systemv +0 -41
  60. data/test/unit/testing/resources/rhel-upstart +0 -20
  61. data/test/unit/testing/test_get_services.rb +0 -178
  62. data/test/unit/testing/test_validate_cron.rb +0 -78
  63. data/test/unit/testing/test_validate_port.rb +0 -103
data/plugins/openstack.rb DELETED
@@ -1,136 +0,0 @@
1
- #!/usr/bin/ruby
2
- ## plugins/openstack.rb - provide helper functions for Rouster objects running on OpenStack/Compute
3
-
4
- require sprintf('%s/../%s', File.dirname(File.expand_path(__FILE__)), 'path_helper')
5
-
6
- require 'fog'
7
- require 'uri'
8
-
9
- class Rouster
10
-
11
- attr_reader :nova # expose OpenStack workers
12
- attr_reader :instance_data # the result of the runInstances request
13
-
14
- # return a hash containing meta-data items
15
- def ostack_get_instance_id ()
16
- # The instance id is kept in @passthrough[:instance] or
17
- # can be obtained from @instance_data which has all instance
18
- # details.
19
- if ! @instance_data.nil? and ! @instance_data.id.nil?
20
- return @instance_data.id # we already know the id
21
- elsif @passthrough.has_key?(:instance)
22
- return @passthrough[:instance] # we know the id we want
23
- else
24
- @logger.debug(sprintf('unable to determine id from instance_data[%s] or passthrough specification[%s]', @instance_data, @passthrough))
25
- return nil # we don't have an id yet, likely a up() call
26
- end
27
- end
28
-
29
- def ostack_up
30
- # wait for machine to transition to running state and become sshable (TODO maybe make the second half optional)
31
- self.ostack_connect
32
- # This will check if instance_id has been provided. If so, it will check on status of the instance.
33
- status = self.status()
34
- if status.eql?('running')
35
- self.passthrough[:instance] = self.ostack_get_instance_id
36
- @logger.debug(sprintf('Connecting to running instance [%s] while calling ostack_up()', self.passthrough[:instance]))
37
- self.connect_ssh_tunnel
38
- else
39
- server = @nova.servers.create(:name => @name, :flavor_ref => @passthrough[:flavor_ref],
40
- :image_ref => @passthrough[:image_ref], :key_name => @passthrough[:keypair], :user_data => @passthrough[:user_data])
41
- server.wait_for { ready? }
42
- @instance_data = server
43
- server.addresses.each_key do |address_key|
44
- if defined?(server.addresses[address_key])
45
- self.passthrough[:host] = server.addresses[address_key].first['addr']
46
- break
47
- end
48
- end
49
- self.passthrough[:instance] = self.ostack_get_instance_id
50
- @logger.debug(sprintf('Connecting to running instance [%s] while calling ostack_up()', self.passthrough[:instance]))
51
- self.connect_ssh_tunnel
52
- end
53
- self.passthrough[:instance]
54
- end
55
-
56
- def ostack_get_ip()
57
- self.passthrough[:host]
58
- end
59
-
60
- def ostack_destroy
61
- server = self.ostack_describe_instance
62
- raise sprintf("instance[%s] not found by destroy()", self.ostack_get_instance_id) if server.nil?
63
- server.destroy
64
- @instance_data = nil
65
- self.passthrough.delete(:instance)
66
- end
67
-
68
- def ostack_describe_instance(instance_id = ostack_get_instance_id)
69
-
70
- if @cache_timeout
71
- if @cache.has_key?(:ostack_describe_instance)
72
- if (Time.now.to_i - @cache[:ostack_describe_instance][:time]) < @cache_timeout
73
- @logger.debug(sprintf('using cached ostack_describe_instance?[%s] from [%s]', @cache[:ostack_describe_instance][:instance], @cache[:ostack_describe_instance][:time]))
74
- return @cache[:ostack_describe_instance][:instance]
75
- end
76
- end
77
- end
78
- # We don't have a instance.
79
- return nil if instance_id.nil?
80
- self.ostack_connect
81
- response = @nova.servers.get(instance_id)
82
- return nil if response.nil?
83
- @instance_data = response
84
-
85
- if @cache_timeout
86
- @cache[:ostack_describe_instance] = Hash.new unless @cache[:ostack_describe_instance].class.eql?(Hash)
87
- @cache[:ostack_describe_instance][:time] = Time.now.to_i
88
- @cache[:ostack_describe_instance][:instance] = response
89
- @logger.debug(sprintf('caching is_available_via_ssh?[%s] at [%s]', @cache[:ostack_describe_instance][:instance], @cache[:ostack_describe_instance][:time]))
90
- end
91
-
92
- @instance_data
93
- end
94
-
95
- def ostack_status
96
- self.ostack_describe_instance
97
- return 'not-created' if @instance_data.nil?
98
- if @instance_data.state.eql?('ACTIVE')
99
- # Make this consistent with AWS response.
100
- return 'running'
101
- else
102
- return @instance_data.state
103
- end
104
- end
105
-
106
-
107
- # TODO this will throw at the first error - should we catch?
108
- # run some commands, return an array of the output
109
- def ostack_bootstrap (commands)
110
- self.ostack_connect
111
- commands = (commands.is_a?(Array)) ? commands : [ commands ]
112
- output = Array.new
113
-
114
- commands.each do |command|
115
- output << self.run(command)
116
- end
117
-
118
- return output
119
- end
120
-
121
- def ostack_connect
122
- # Instantiates an Object which can communicate with OS Compute.
123
- # No instance specific information is set at this time.
124
- return @nova unless @nova.nil?
125
-
126
- config = {
127
- :provider => 'openstack', # OpenStack Fog provider
128
- :openstack_auth_url => self.passthrough[:openstack_auth_url], # OpenStack Keystone endpoint
129
- :openstack_username => self.passthrough[:openstack_username], # Your OpenStack Username
130
- :openstack_tenant => self.passthrough[:openstack_tenant], # Your tenant id
131
- :openstack_api_key => self.passthrough[:openstack_api_key], # Your OpenStack Password
132
- :connection_options => self.passthrough[:connection_options] # Optional
133
- }
134
- @nova = Fog::Compute.new(config)
135
- end
136
- end
@@ -1,161 +0,0 @@
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 TestDeltasGetCrontab < Test::Unit::TestCase
8
-
9
- def setup
10
- assert_nothing_raised do
11
- @app = Rouster.new(:name => 'app', :cache_timeout => 20)
12
- end
13
-
14
- @app.up()
15
-
16
- ## setup some cronjobs so we have something to look at - and yes, this is hacktastic
17
- ['root', 'puppet'].each do | user|
18
- tmp = sprintf('/tmp/rouster.tmp.crontab.%s.%s.%s', user, Time.now.to_i, $$)
19
- @app.run("echo '0 0 * * * echo #{user}' > #{tmp}")
20
- #@app.run("crontab -u #{user} -f #{tmp}") # rhel
21
- @app.run("crontab -u #{user} #{tmp}") # centos
22
- end
23
-
24
- end
25
-
26
- def test_happy_path
27
-
28
- res = nil
29
-
30
- assert_nothing_raised do
31
- res = @app.get_crontab()
32
- end
33
-
34
- assert_equal(Hash, res.class)
35
- assert_equal(res, @app.deltas[:crontab]['root'])
36
- assert_not_nil(@app.deltas[:crontab]['root'])
37
-
38
- end
39
-
40
- def test_happy_path_specified_user
41
-
42
- res = nil
43
-
44
- assert_nothing_raised do
45
- res = @app.get_crontab('puppet')
46
- end
47
-
48
- assert_equal(Hash, res.class)
49
- assert_equal(res, @app.deltas[:crontab]['puppet'])
50
- assert_not_nil(@app.deltas[:crontab]['puppet'])
51
-
52
- end
53
-
54
- def test_happy_path_specified_star
55
-
56
- res = nil
57
-
58
- assert_nothing_raised do
59
- res = @app.get_crontab('*')
60
- end
61
-
62
- assert_equal(Hash, res.class)
63
- assert_equal(res, @app.deltas[:crontab])
64
- assert_not_nil(@app.deltas[:crontab]['root'])
65
- assert_not_nil(@app.deltas[:crontab]['puppet'])
66
-
67
- end
68
-
69
- def test_unhappy_path_non_existent_user
70
-
71
- res = nil
72
-
73
- assert_nothing_raised do
74
- res = @app.get_crontab('fizzybang')
75
- end
76
-
77
- assert_equal(Hash, res.class)
78
- assert_equal(0, res.keys.size)
79
-
80
- end
81
-
82
- def test_happy_path_no_cache
83
-
84
- res = nil
85
-
86
- assert_nothing_raised do
87
- res = @app.get_crontab('root', false)
88
- end
89
-
90
- assert_equal(Hash, res.class)
91
- assert_nil(@app.deltas[:crontab])
92
-
93
- end
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
-
157
- def teardown
158
- @app = nil
159
- end
160
-
161
- end
@@ -1,68 +0,0 @@
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
@@ -1,40 +0,0 @@
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 TestIsInFile < Test::Unit::TestCase
8
-
9
- SHIBBOLETH = 'foobar'
10
-
11
- def setup
12
- assert_nothing_raised do
13
- # no reason not to do this as a passthrough once we can
14
- @app = Rouster.new(:name => 'app', :sudo => false)
15
- @app.up()
16
- end
17
-
18
- # create some temporary files
19
- @dir_tmp = sprintf('/tmp/rouster-%s.%s', $$, Time.now.to_i)
20
- @app.run(sprintf('mkdir %s', @dir_tmp))
21
-
22
- @file = sprintf('%s/file', @dir_tmp)
23
- @app.run(sprintf('echo "%s" >> %s', SHIBBOLETH, @file))
24
- end
25
-
26
- def teardown; end
27
-
28
- def test_positive
29
-
30
- assert_equal(true, @app.is_in_file?(@file, SHIBBOLETH))
31
-
32
- end
33
-
34
- def test_negative
35
-
36
- assert_equal(false, @app.is_in_file?(@file, 'fizzbuzz'))
37
-
38
- end
39
-
40
- end
@@ -1,94 +0,0 @@
1
- require sprintf('%s/../../path_helper', File.dirname(File.expand_path(__FILE__)))
2
-
3
- require 'rouster'
4
- require 'test/unit'
5
-
6
- # most of the real passthrough testing is done in test_new.rb, since the only effective difference should be the target of the SSH connection
7
-
8
- class TestPassthroughs < Test::Unit::TestCase
9
-
10
- def setup
11
- @@user_sshkey = sprintf('%s/.ssh/id_rsa', ENV['HOME'])
12
-
13
- unless File.file?(@@user_sshkey)
14
- File.write(@@user_sshkey, '') # either this or `touch`
15
- File.chmod(0600, @@user_sshkey)
16
- end
17
-
18
- end
19
-
20
- def test_functional_local_passthrough
21
-
22
- assert_nothing_raised do
23
- @local = Rouster.new(
24
- :name => 'local',
25
- :passthrough => {
26
- :type => :local,
27
- },
28
- :verbose => 4,
29
- )
30
- end
31
-
32
- assert(@local.is_passthrough?(), 'worker is a passthrough')
33
- assert_equal(false, @local.is_available_via_ssh?(), 'worker is available via SSH')
34
-
35
- # put a file in /tmp/fizz and read it back
36
- tmpfile = sprintf('/tmp/fizzy.%s.%s', Time.now.to_i, $$)
37
- content = 'this is some sample text'
38
-
39
- assert_nothing_raised do
40
- @local.run("echo #{content} >> #{tmpfile}")
41
- end
42
-
43
- read = @local.run("cat #{tmpfile}").chomp! # using >> automatically includes \n
44
-
45
- assert_equal(content, read, 'worker is able to read and write files on system')
46
-
47
- # TODO better here
48
- assert_nothing_raised do
49
- @local.file('/etc/hosts')
50
- @local.dir('/tmp')
51
- end
52
-
53
- end
54
-
55
- def test_functional_remote_passthrough
56
-
57
- omit('not running test_good_remote_passthrough, autogenerated a fake ssh key') if File.file?(@@user_sshkey) and File.read(@@user_sshkey).eql?("")
58
-
59
- host = '127.0.0.1'
60
- `ssh -i #{@@user_sshkey} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null #{host} exit`
61
- omit("found an ssh key, but it doesn't appear to be valid for this host") unless $?.success?
62
-
63
- assert_nothing_raised do
64
- @remote = Rouster.new(
65
- :name => 'remote',
66
- :passthrough => {
67
- :type => :remote,
68
- :host => host,
69
- :user => ENV['USER'],
70
- :key => @@user_sshkey,
71
- },
72
- :verbosity => 4,
73
- )
74
- end
75
-
76
- assert_equal('remote', @remote.name)
77
- assert_equal(true, @remote.is_passthrough?())
78
- assert_equal(false, @remote.uses_sudo?())
79
- assert_equal(true, @remote.is_available_via_ssh?())
80
-
81
- # TODO better here
82
- assert_nothing_raised do
83
- @remote.file('/etc/hosts')
84
- @remote.dir('/tmp')
85
- end
86
-
87
- end
88
-
89
- def teardown
90
- # if the file is empty, we know we created it (or it doesn't matter)..
91
- File.delete(@@user_sshkey) if File.file?(@@user_sshkey) and File.read(@@user_sshkey).eql?('')
92
- end
93
-
94
- end