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
@@ -8,7 +8,7 @@ class TestDeltasGetUsers < 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()
@@ -36,7 +36,40 @@ class TestDeltasGetUsers < Test::Unit::TestCase
36
36
 
37
37
  end
38
38
 
39
- # TODO add some caching tests
39
+ def test_happy_path_caching
40
+
41
+ assert_nil(@app.deltas[:users])
42
+
43
+ assert_nothing_raised do
44
+ @app.get_users(true)
45
+ end
46
+
47
+ assert_equal(Hash, @app.deltas[:users].class)
48
+
49
+ end
50
+
51
+ def test_happy_path_cache_invalidation
52
+ res1, res2 = nil, nil
53
+
54
+ assert_nothing_raised do
55
+ res1 = @app.get_users(true)
56
+ end
57
+
58
+ first_cache_time = @app.cache[:users]
59
+
60
+ sleep (@app.cache_timeout + 1)
61
+
62
+ assert_nothing_raised do
63
+ res2 = @app.get_users(true)
64
+ end
65
+
66
+ second_cache_time = @app.cache[:users]
67
+
68
+ assert_equal(res1, res2)
69
+ assert_not_equal(first_cache_time, second_cache_time)
70
+ assert(second_cache_time > first_cache_time)
71
+
72
+ end
40
73
 
41
74
  def teardown
42
75
  @app = nil
@@ -8,7 +8,7 @@ class TestFacter < 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()
@@ -38,6 +38,46 @@ class TestFacter < Test::Unit::TestCase
38
38
  assert_equal(nil, @app.facts)
39
39
  end
40
40
 
41
+ def test_caching
42
+ # NOTE: this only works if (time_to_run_facter < cache_timeout)
43
+
44
+ assert_nothing_raised do
45
+ @app.facter(true)
46
+ end
47
+
48
+ first_cached_time = @app.cache[:facter]
49
+
50
+ assert_nothing_raised do
51
+ @app.facter(true)
52
+ end
53
+
54
+ second_cached_time = @app.cache[:facter]
55
+
56
+ assert_equal(first_cached_time, second_cached_time)
57
+
58
+ end
59
+
60
+ def test_cache_invalidation
61
+
62
+ assert_nothing_raised do
63
+ @app.facter(true)
64
+ end
65
+
66
+ first_cached_time = @app.cache[:facter]
67
+
68
+ sleep (@app.cache_timeout + 1)
69
+
70
+ assert_nothing_raised do
71
+ @app.facter(true)
72
+ end
73
+
74
+ second_cached_time = @app.cache[:facter]
75
+
76
+ assert_not_equal(first_cached_time, second_cached_time)
77
+ assert(second_cached_time > first_cached_time)
78
+
79
+ end
80
+
41
81
  def test_custom_facts
42
82
 
43
83
  facts = nil
@@ -75,10 +75,10 @@ class TestCaching < Test::Unit::TestCase
75
75
 
76
76
  def test_ssh_caching
77
77
 
78
- skip('see comments in rouster.rb line ~84')
79
-
80
78
  timeout = 100
81
79
  app = Rouster.new(:name => 'app', :sshtunnel => true, :cache_timeout => timeout)
80
+ app.destroy() # should be a no-op if running under rake, doing this to be safe
81
+
82
82
  app.up()
83
83
 
84
84
  assert_equal(app.cache_timeout, timeout)
@@ -21,7 +21,7 @@ class TestInspect < Test::Unit::TestCase
21
21
  assert_match(/status/, res)
22
22
  assert_match(/sudo\[true\]/, res)
23
23
  assert_match(/vagrantfile/, res)
24
- assert_match(/verbosity\[4\]/, res)
24
+ assert_match(/verbosity console\[3\] \/ log\[2/, res)
25
25
  end
26
26
 
27
27
  def teardown
@@ -22,8 +22,9 @@ class TestIsFile < Test::Unit::TestCase
22
22
  @file_other_rwx = sprintf('%s/other', @dir_tmp)
23
23
  @file_644 = sprintf('%s/sixfourfour', @dir_tmp)
24
24
  @file_755 = sprintf('%s/sevenfivefive', @dir_tmp)
25
+ @symlink = sprintf('%s/symlinking', @dir_tmp)
25
26
 
26
- @files = [@file_user_rwx, @file_group_rwx, @file_other_rwx, @file_644, @file_755]
27
+ @files = [@file_user_rwx, @file_group_rwx, @file_other_rwx, @file_644, @file_755, @symlink]
27
28
  end
28
29
 
29
30
  def test_user
@@ -41,6 +42,8 @@ class TestIsFile < Test::Unit::TestCase
41
42
  assert_equal(false, @app.is_readable?(@file_user_rwx, 'o'))
42
43
  assert_equal(false, @app.is_writeable?(@file_user_rwx, 'o'))
43
44
  assert_equal(false, @app.is_executable?(@file_user_rwx, 'o'))
45
+
46
+ assert_equal(false, @app.is_symlink?(@file_755))
44
47
  end
45
48
 
46
49
  def test_group
@@ -58,6 +61,8 @@ class TestIsFile < Test::Unit::TestCase
58
61
  assert_equal(false, @app.is_readable?(@file_group_rwx, 'o'))
59
62
  assert_equal(false, @app.is_writeable?(@file_group_rwx, 'o'))
60
63
  assert_equal(false, @app.is_executable?(@file_group_rwx, 'o'))
64
+
65
+ assert_equal(false, @app.is_symlink?(@file_755))
61
66
  end
62
67
 
63
68
  def test_other
@@ -76,6 +81,7 @@ class TestIsFile < Test::Unit::TestCase
76
81
  assert_equal(true, @app.is_writeable?(@file_other_rwx, 'o'))
77
82
  assert_equal(true, @app.is_executable?(@file_other_rwx, 'o'))
78
83
 
84
+ assert_equal(false, @app.is_symlink?(@file_755))
79
85
  end
80
86
 
81
87
  def test_644
@@ -93,6 +99,8 @@ class TestIsFile < Test::Unit::TestCase
93
99
  assert_equal(true, @app.is_readable?(@file_644, 'o'))
94
100
  assert_equal(false, @app.is_writeable?(@file_644, 'o'))
95
101
  assert_equal(false, @app.is_executable?(@file_644, 'o'))
102
+
103
+ assert_equal(false, @app.is_symlink?(@file_755))
96
104
  end
97
105
 
98
106
  def test_755
@@ -110,6 +118,14 @@ class TestIsFile < Test::Unit::TestCase
110
118
  assert_equal(true, @app.is_readable?(@file_755, 'o'))
111
119
  assert_equal(false, @app.is_writeable?(@file_755, 'o'))
112
120
  assert_equal(true, @app.is_executable?(@file_755, 'o'))
121
+
122
+ assert_equal(false, @app.is_symlink?(@file_755))
123
+ end
124
+
125
+ def test_symlink
126
+ @app.run("ln -s /etc/hosts #{@symlink}")
127
+
128
+ assert_equal(true, @app.is_symlink?(@symlink))
113
129
  end
114
130
 
115
131
  def teardown
@@ -0,0 +1,40 @@
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
@@ -7,13 +7,25 @@ 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
+
14
26
  end
15
27
 
16
- def test_1_able_to_instantiate
28
+ def test_able_to_instantiate
17
29
 
18
30
  assert_nothing_raised do
19
31
  @app = Rouster.new(:name => 'app')
@@ -21,62 +33,93 @@ class TestNew < Test::Unit::TestCase
21
33
 
22
34
  end
23
35
 
24
- def test_2_good_openssh_tunnel
36
+ def test_defaults
37
+
38
+ assert_nothing_raised do
39
+ @app = Rouster.new(:name => 'app')
40
+ end
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
+
53
+ end
54
+
55
+ def test_good_openssh_tunnel
25
56
  @app = Rouster.new(:name => 'app', :sshtunnel => true)
26
57
 
27
58
  # TODO how do we properly test this? we really need the rspec should_call mechanism...
28
-
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
- :name => 'app',
37
- :passthrough => true,
38
- :sudo => false,
39
- :verbosity => 4,
40
- #:vagrantfile => traverse_up(Dir.pwd, 'Vagrantfile'), # this is what happens anyway..
41
- :sshkey => ENV['VAGRANT_HOME'].nil? ? sprintf('%s/.vagrant.d/insecure_private_key', ENV['HOME']) : sprintf('%s/insecure_private_key', ENV['VAGRANT_HOME']),
66
+ :name => 'app',
67
+ :passthrough => false,
68
+ :sudo => false,
69
+ :verbosity => [4,0],
70
+ #:vagrantfile => traverse_up(Dir.pwd, 'Vagrantfile'), # this is what happens anyway..
71
+ :sshkey => ENV['VAGRANT_HOME'].nil? ? sprintf('%s/.vagrant.d/insecure_private_key', ENV['HOME']) : sprintf('%s/insecure_private_key', ENV['VAGRANT_HOME']),
72
+ :cache_timeout => 10,
73
+ :logfile => true,
42
74
  )
43
75
 
44
-
45
76
  end
46
77
 
47
78
  assert_equal('app', @app.name)
48
- assert_equal(true, @app.is_passthrough?())
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))
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)
53
95
  end
54
96
 
55
- def test_4_bad_name_instantiation
97
+ def test_bad_name_instantiation
56
98
 
99
+ # TODO this is probably wrong, should really be an ArgumentError
57
100
  assert_raise Rouster::InternalError do
58
101
  @app = Rouster.new(:name => 'foo')
59
102
  end
60
103
 
61
- assert_raise Rouster::InternalError do
104
+ assert_raise Rouster::ArgumentError do
62
105
  @app = Rouster.new(:not_a_name => 'test')
63
106
  end
64
107
 
65
108
  end
66
109
 
67
- def test_5_bad_vagrantfile_instantiation
110
+ def test_bad_vagrantfile_instantiation
68
111
 
69
112
  assert_raise Rouster::InternalError do
70
113
  @app = Rouster.new(:name => 'FIZZY') # auto find Vagrantfile
71
114
  end
72
115
 
73
- assert_raise Rouster::InternalError do
116
+ assert_raise Rouster::ArgumentError do
74
117
  @app = Rouster.new(:name => 'testing', :vagrantfile => '/this/file/dne')
75
118
  end
76
119
 
77
120
  end
78
121
 
79
- def test_6_bad_sshkey_instantiation
122
+ def test_bad_sshkey_instantiation
80
123
 
81
124
  assert_raise Rouster::InternalError do
82
125
  @app = Rouster.new(:name => 'app', :sshkey => '/this/file/dne')
@@ -84,9 +127,177 @@ class TestNew < Test::Unit::TestCase
84
127
 
85
128
  end
86
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(false, @app.is_available_via_ssh?())
140
+
141
+ end
142
+
143
+ def test_good_remote_passthrough
144
+
145
+ omit('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} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null #{host} exit` # if this succeeds, we want to exit immediately so we don't get hung
149
+ omit("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
+ :paranoid => false,
161
+ },
162
+ :verbosity => 4,
163
+ )
164
+ end
165
+
166
+ assert_equal('remote', @app.name)
167
+ assert_equal(true, @app.is_passthrough?())
168
+ assert_equal(false, @app.uses_sudo?())
169
+ assert_equal(true, @app.is_available_via_ssh?())
170
+
171
+ end
172
+
173
+ def test_paranoia_remote_passthrough
174
+
175
+ omit('not running test_good_remote_passthrough, autogenerated a fake ssh key') if File.file?(@@user_sshkey) and File.read(@@user_sshkey).eql?("")
176
+
177
+ host = '127.0.0.1'
178
+ `ssh -i #{@@user_sshkey} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null #{host} exit` # if this succeeds, we want to exit immediately so we don't get hung
179
+ omit("found an ssh key, but it doesn't appear to be valid for this host") unless $?.success?
180
+
181
+ assert_nothing_raised do
182
+ @app = Rouster.new(
183
+ :name => 'remote',
184
+ :sudo => false,
185
+ :passthrough => {
186
+ :type => :remote,
187
+ :host => host,
188
+ :user => ENV['USER'],
189
+ :key => @@user_sshkey,
190
+ :paranoid => :very,
191
+ },
192
+ :verbosity => 4,
193
+ )
194
+ end
195
+
196
+ assert_equal('remote', @app.name)
197
+ assert_equal(true, @app.is_passthrough?())
198
+ assert_equal(false, @app.uses_sudo?())
199
+ assert_equal(true, @app.is_available_via_ssh?())
200
+
201
+ end
202
+
203
+
204
+ def test_invalid_passthrough
205
+
206
+ # invalid type
207
+ # missing required parameters
208
+
209
+ assert_raise Rouster::ArgumentError do
210
+ @app = Rouster.new(:name => 'fizzy', :passthrough => {}, :verbosity => 4)
211
+ end
212
+
213
+ assert_raise Rouster::ArgumentError do
214
+ @app = Rouster.new(:name => 'fizzy', :passthrough => { :type => 'invalid' }, :verbosity => 4)
215
+ end
216
+
217
+ assert_raise Rouster::ArgumentError do
218
+ @app = Rouster.new(:name => 'fizzy', :passthrough => { :type => :remote }, :verbosity => 4)
219
+ end
220
+
221
+ assert_raise Rouster::ArgumentError do
222
+ @app = Rouster.new(:name => 'fizzy', :passthrough => { :type => :remote, :user => 'foo' }, :verbosity => 4)
223
+ end
224
+
225
+ end
226
+
227
+ def test_bad_passthrough
228
+
229
+ # invalid key
230
+ assert_raise Rouster::InternalError do
231
+ @app = Rouster.new(
232
+ :name => 'fizzy',
233
+ :passthrough => {
234
+ :type => :remote,
235
+ :key => '/etc/hosts',
236
+ :user => 'foo',
237
+ :host => 'bar',
238
+ },
239
+ :verbosity => 4,
240
+ )
241
+ end
242
+
243
+ # key that DNE
244
+ assert_raise Rouster::ArgumentError do
245
+ @app = Rouster.new(
246
+ :name => 'fizzy',
247
+ :passthrough => {
248
+ :type => :remote,
249
+ :key => '/etc/this-file-dne',
250
+ :user => 'foo',
251
+ :host => 'bar',
252
+ },
253
+ :verbosity => 4,
254
+ )
255
+ end
256
+
257
+ # host that DNE
258
+ assert_raise SocketError do
259
+ @app = Rouster.new(
260
+ :name => 'fizzy',
261
+ :passthrough => {
262
+ :type => :remote,
263
+ :key => @@user_sshkey,
264
+ :user => 'foo',
265
+ :host => 'this.host.does.not.exist',
266
+
267
+ # don't retry.. too much
268
+ :ssh_sleep_ceiling => 1,
269
+ :ssh_sleep_time => 1,
270
+ },
271
+
272
+ :sshtunnel => true,
273
+ :verbosity => 4,
274
+ )
275
+ end
276
+
277
+ # IP that doesn't resolve
278
+ assert_raise SocketError do
279
+ @app = Rouster.new(
280
+ :name => 'fizzy',
281
+ :passthrough => {
282
+ :type => :remote,
283
+ :key => @@user_sshkey,
284
+ :user => 'foo',
285
+ :host => '255.256.257.258',
286
+
287
+ :ssh_sleep_ceiling => 1,
288
+ :ssh_sleep_time => 1,
289
+ },
290
+
291
+ :sshtunnel => true,
292
+ :verbosity => 4,
293
+ )
294
+ end
295
+
296
+ end
87
297
 
88
298
  def teardown
89
- # noop
299
+ # if the file is empty, we know we created it (or it doesn't matter)..
300
+ File.delete(@@user_sshkey) if File.file?(@@user_sshkey) and File.read(@@user_sshkey).eql?('')
90
301
  end
91
302
 
92
303
  end