rouster 0.53 → 0.57

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.
@@ -7,39 +7,70 @@ require 'test/unit'
7
7
 
8
8
  class TestNew < Test::Unit::TestCase
9
9
 
10
- def setup
11
- @app = Rouster.new(:name => 'app')
12
- @app.destroy() if @app.status().eql?('running')
10
+ # when run under Rake, if named 'setup', @@user_sshkey is not initialized in the
11
+ # TestNew namespace (does not matter if running directly). since setup() really
12
+ # only needed to be run once anyway, this isn't a huge problem
13
+ def test_0_setup
14
+ @app = Rouster.new(:name => 'app', :sshtunnel => false)
15
+ @app.destroy() if @app.status().eql?('running') # TODO do we really need to do this?
13
16
  @app = nil
17
+
18
+ @@user_sshkey = sprintf('%s/.ssh/id_rsa', ENV['HOME'])
19
+
20
+ unless File.file?(@@user_sshkey)
21
+ #`ssh-keygen -t rsa -q -f #{@@user_sshkey} -N ''` # this will create the file, and we can track with another class variable.. but how do we safely install/uninstall this to localhost ~/.ssh/authorized_keys ?
22
+ File.write(@@user_sshkey, '') # either this or `touch`
23
+ File.chmod(0600, @@user_sshkey)
24
+ end
25
+
26
+ end
27
+
28
+ def test_able_to_instantiate
29
+
30
+ assert_nothing_raised do
31
+ @app = Rouster.new(:name => 'app')
32
+ end
33
+
14
34
  end
15
35
 
16
- def test_1_able_to_instantiate
36
+ def test_defaults
17
37
 
18
38
  assert_nothing_raised do
19
39
  @app = Rouster.new(:name => 'app')
20
40
  end
21
41
 
42
+ assert_equal('app', @app.name)
43
+ assert_equal(false, @app.cache_timeout)
44
+ assert_equal(false, @app.instance_variable_get(:@logfile))
45
+ assert_equal(false, @app.is_passthrough?())
46
+ assert_equal(0, @app.retries)
47
+ assert_equal(true, @app.instance_variable_get(:@sshtunnel))
48
+ assert_equal(false, @app.instance_variable_get(:@unittest))
49
+ assert_equal(false, @app.instance_variable_get(:@vagrant_concurrency))
50
+ assert_equal(3, @app.instance_variable_get(:@verbosity_console))
51
+ assert_equal(2, @app.instance_variable_get(:@verbosity_logfile))
52
+
22
53
  end
23
54
 
24
- def test_2_good_openssh_tunnel
55
+ def test_good_openssh_tunnel
25
56
  @app = Rouster.new(:name => 'app', :sshtunnel => true)
26
- 7
27
- # TODO how do we properly test this? we really need the rspec should_call mechanism...
28
57
 
58
+ # TODO how do we properly test this? we really need the rspec should_call mechanism...
29
59
  assert_equal(true, @app.is_available_via_ssh?)
30
60
  end
31
61
 
32
- def test_3_good_advanced_instantiation
62
+ def test_good_advanced_instantiation
33
63
 
34
64
  assert_nothing_raised do
35
65
  @app = Rouster.new(
36
66
  :name => 'app',
37
67
  :passthrough => false,
38
68
  :sudo => false,
39
- :verbosity => 4,
69
+ :verbosity => [4,0],
40
70
  #:vagrantfile => traverse_up(Dir.pwd, 'Vagrantfile'), # this is what happens anyway..
41
71
  :sshkey => ENV['VAGRANT_HOME'].nil? ? sprintf('%s/.vagrant.d/insecure_private_key', ENV['HOME']) : sprintf('%s/insecure_private_key', ENV['VAGRANT_HOME']),
42
72
  :cache_timeout => 10,
73
+ :logfile => true,
43
74
  )
44
75
 
45
76
  end
@@ -47,37 +78,48 @@ class TestNew < Test::Unit::TestCase
47
78
  assert_equal('app', @app.name)
48
79
  assert_equal(false, @app.is_passthrough?())
49
80
  assert_equal(false, @app.uses_sudo?())
50
- assert_equal(4, @app.verbosity) # is this going to be strinigified?
81
+ assert_equal(4, @app.instance_variable_get(:@verbosity_console))
82
+ assert_equal(0, @app.instance_variable_get(:@verbosity_logfile))
51
83
  assert_equal(true, File.file?(@app.vagrantfile))
52
84
  assert_equal(true, File.file?(@app.sshkey))
53
85
  assert_equal(10, @app.cache_timeout)
86
+
87
+ ## logfile validation -- do we need to do more here?
88
+ logfile = @app.instance_variable_get(:@logfile)
89
+
90
+ assert_not_equal(true, logfile)
91
+ assert(File.file?(logfile))
92
+
93
+ contents = File.read(logfile)
94
+ assert_not_nil(contents)
54
95
  end
55
96
 
56
- def test_4_bad_name_instantiation
97
+ def test_bad_name_instantiation
57
98
 
99
+ # TODO this is probably wrong, should really be an ArgumentError
58
100
  assert_raise Rouster::InternalError do
59
101
  @app = Rouster.new(:name => 'foo')
60
102
  end
61
103
 
62
- assert_raise Rouster::InternalError do
104
+ assert_raise Rouster::ArgumentError do
63
105
  @app = Rouster.new(:not_a_name => 'test')
64
106
  end
65
107
 
66
108
  end
67
109
 
68
- def test_5_bad_vagrantfile_instantiation
110
+ def test_bad_vagrantfile_instantiation
69
111
 
70
112
  assert_raise Rouster::InternalError do
71
113
  @app = Rouster.new(:name => 'FIZZY') # auto find Vagrantfile
72
114
  end
73
115
 
74
- assert_raise Rouster::InternalError do
116
+ assert_raise Rouster::ArgumentError do
75
117
  @app = Rouster.new(:name => 'testing', :vagrantfile => '/this/file/dne')
76
118
  end
77
119
 
78
120
  end
79
121
 
80
- def test_6_bad_sshkey_instantiation
122
+ def test_bad_sshkey_instantiation
81
123
 
82
124
  assert_raise Rouster::InternalError do
83
125
  @app = Rouster.new(:name => 'app', :sshkey => '/this/file/dne')
@@ -85,9 +127,136 @@ class TestNew < Test::Unit::TestCase
85
127
 
86
128
  end
87
129
 
130
+ def test_good_local_passthrough
131
+
132
+ assert_nothing_raised do
133
+ @app = Rouster.new(:name => 'local', :passthrough => { :type => :local }, :verbosity => 4)
134
+ end
135
+
136
+ assert_equal('local', @app.name)
137
+ assert_equal(true, @app.is_passthrough?())
138
+ assert_equal(false, @app.uses_sudo?())
139
+ assert_equal(true, @app.is_available_via_ssh?())
140
+
141
+ end
142
+
143
+ def test_good_remote_passthrough
144
+
145
+ skip('not running test_good_remote_passthrough, autogenerated a fake ssh key') if File.file?(@@user_sshkey) and File.read(@@user_sshkey).eql?("")
146
+
147
+ host = '127.0.0.1'
148
+ `ssh -i #{@@user_sshkey} #{host}`
149
+ skip("found an ssh key, but it doesn't appear to be valid for this host") unless $?.success?
150
+
151
+ assert_nothing_raised do
152
+ @app = Rouster.new(
153
+ :name => 'remote',
154
+ :sudo => false,
155
+ :passthrough => {
156
+ :type => :remote,
157
+ :host => host,
158
+ :user => ENV['USER'],
159
+ :key => @@user_sshkey,
160
+ },
161
+ :verbosity => 4,
162
+ )
163
+ end
164
+
165
+ assert_equal('remote', @app.name)
166
+ assert_equal(true, @app.is_passthrough?())
167
+ assert_equal(false, @app.uses_sudo?())
168
+ assert_equal(true, @app.is_available_via_ssh?())
169
+
170
+ end
171
+
172
+ def test_invalid_passthrough
173
+
174
+ # invalid type
175
+ # missing required parameters
176
+
177
+ assert_raise Rouster::ArgumentError do
178
+ @app = Rouster.new(:name => 'fizzy', :passthrough => {}, :verbosity => 4)
179
+ end
180
+
181
+ assert_raise Rouster::ArgumentError do
182
+ @app = Rouster.new(:name => 'fizzy', :passthrough => { :type => 'invalid' }, :verbosity => 4)
183
+ end
184
+
185
+ assert_raise Rouster::ArgumentError do
186
+ @app = Rouster.new(:name => 'fizzy', :passthrough => { :type => :remote }, :verbosity => 4)
187
+ end
188
+
189
+ assert_raise Rouster::ArgumentError do
190
+ @app = Rouster.new(:name => 'fizzy', :passthrough => { :type => :remote, :user => 'foo' }, :verbosity => 4)
191
+ end
192
+
193
+ end
194
+
195
+ def test_bad_passthrough
196
+
197
+ # invalid key
198
+ assert_raise Rouster::InternalError do
199
+ @app = Rouster.new(
200
+ :name => 'fizzy',
201
+ :passthrough => {
202
+ :type => :remote,
203
+ :key => '/etc/hosts',
204
+ :user => 'foo',
205
+ :host => 'bar',
206
+ },
207
+ :verbosity => 4,
208
+ )
209
+ end
210
+
211
+ # key that DNE
212
+ assert_raise Rouster::ArgumentError do
213
+ @app = Rouster.new(
214
+ :name => 'fizzy',
215
+ :passthrough => {
216
+ :type => :remote,
217
+ :key => '/etc/this-file-dne',
218
+ :user => 'foo',
219
+ :host => 'bar',
220
+ },
221
+ :verbosity => 4,
222
+ )
223
+ end
224
+
225
+ # host that DNE
226
+ # TODO should we be catching this ourselves?
227
+ assert_raise SocketError do
228
+ @app = Rouster.new(
229
+ :name => 'fizzy',
230
+ :passthrough => {
231
+ :type => :remote,
232
+ :key => @@user_sshkey,
233
+ :user => 'foo',
234
+ :host => 'this.host.does.not.exist',
235
+ },
236
+ :verbosity => 4,
237
+ )
238
+ end
239
+
240
+ # IP that doesn't resolve
241
+ # TODO should we be catching this ourselves?
242
+ assert_raise SocketError do
243
+ @app = Rouster.new(
244
+ :name => 'fizzy',
245
+ :passthrough => {
246
+ :type => :remote,
247
+ :key => @@user_sshkey,
248
+ :user => 'foo',
249
+ :host => '255.256.257.258',
250
+ },
251
+ :verbosity => 4,
252
+ )
253
+ end
254
+
255
+ end
88
256
 
89
257
  def teardown
90
- # noop
258
+ # if the file is empty, we know we created it (or it doesn't matter)..
259
+ File.delete(@@user_sshkey) if File.file?(@@user_sshkey) and File.read(@@user_sshkey).eql?('')
91
260
  end
92
261
 
93
262
  end
@@ -0,0 +1,94 @@
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(@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
+ skip('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} #{host}`
61
+ skip("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
@@ -75,7 +75,7 @@ class TestPut < Test::Unit::TestCase
75
75
 
76
76
  def teardown
77
77
  #@app.destroy()
78
- @app.suspend()
78
+ #@app.suspend()
79
79
  File.delete(@kg_location) if File.file?(@kg_location).true?
80
80
  end
81
- end
81
+ end
@@ -17,9 +17,61 @@ class TestValidateFileFunctional < Test::Unit::TestCase
17
17
 
18
18
  def test_negative_functional_fallthrough
19
19
 
20
- assert_equal(false, @app.validate_file('/foo', {}, false, true))
21
- assert_equal(false, @app.validate_file('/fizzy', { :ensure => 'directory' }, false, true))
22
- assert_equal(false, @app.validate_file('/bang', { :ensure => 'file' }, false, true))
20
+ assert_equal(false, @app.validate_file('/foo', {}, false, true), 'when no expectation is specified, :ensure => present is assumed')
21
+ assert_equal(false, @app.validate_file('/fizzy', { :ensure => 'directory' }, false, true), 'standard DNE directory test')
22
+ assert_equal(false, @app.validate_file('/bang', { :ensure => 'file' }, false, true), '~standard DNE directory test')
23
+
24
+ end
25
+
26
+ # TODO tests
27
+ # :contains string
28
+ # :contains array
29
+ # :exists vs. :ensure -> what options are supported?
30
+ # :mode vs. :permissions
31
+ # :size
32
+ # :owner
33
+ # :group
34
+ # :constrain
35
+
36
+
37
+ def test_happy_basic
38
+ file = '/tmp/chiddy'
39
+ expectation = { :ensure => 'file' }
40
+
41
+ @app.run("touch #{file}")
42
+
43
+ assert_equal(true, @app.validate_file(file, expectation, false, true))
44
+
45
+ end
46
+
47
+ def test_happy_doesnt_contain
48
+ file = '/etc/hosts'
49
+ expectations = {
50
+ :ensure => 'file',
51
+ :doesntcontain => 'fizzybang.12345',
52
+ :notcontains => 'this.isnt.there.either'
53
+ }
54
+
55
+ assert_equal(true, @app.validate_file(file, expectations, false, true))
56
+
57
+ end
58
+
59
+ def test_happy_symlink
60
+ file = '/tmp/bang'
61
+
62
+ @app.run("ln -sf /etc/hosts #{file}")
63
+
64
+ expectations = [
65
+ { :ensure => 'symlink' },
66
+ { :ensure => 'link' },
67
+ { :ensure => 'link', :target => '/etc/hosts' }
68
+ ]
69
+
70
+ expectations.each do |e|
71
+ # this is a weird convention, maybe reconsider the calling signature for validate_file
72
+ # thinking something like validate_file(expectations) instead of validate_file(file, expectations)
73
+ assert_equal(true, @app.validate_file(file, e, false, true))
74
+ end
23
75
 
24
76
  end
25
77
 
@@ -21,11 +21,13 @@ class TestPuppetApply < Test::Unit::TestCase
21
21
  'test/puppet/modules/role/manifests/ui.pp' => 'modules/role/manifests/ui.pp',
22
22
  }
23
23
 
24
- ## TODO figure out a better pattern here -- scp tunnel is under 'vagrant' context, but dirs created with 'root'
25
- @app.sudo = false
26
- @app.run('mkdir -p manifests/hieradata')
27
- @app.run('mkdir -p modules/role/manifests')
28
- @app.sudo = true
24
+ ['manifests/hieradata', 'modules/role/manifests'].each do |dir|
25
+ top = dir.split('/')[0]
26
+
27
+ @app.run("mkdir -p #{dir}")
28
+ @app.run("chown -R vagrant:vagrant #{top}") # because sudo=true, directories will be created with root:root
29
+
30
+ end
29
31
 
30
32
  required_files.each_pair do |source,dest|
31
33
  @app.put(source, dest)