machines 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. data/.gitignore +11 -0
  2. data/EXAMPLES.md +18 -0
  3. data/Gemfile +4 -0
  4. data/Guardfile +14 -0
  5. data/INSTALL.md +25 -0
  6. data/LICENSE +23 -0
  7. data/README.md +271 -0
  8. data/Rakefile +60 -0
  9. data/TODO.md +92 -0
  10. data/bin/machines +6 -0
  11. data/lib/machines/app_settings.rb +54 -0
  12. data/lib/machines/base.rb +13 -0
  13. data/lib/machines/checks.rb +63 -0
  14. data/lib/machines/cloud_machine.rb +33 -0
  15. data/lib/machines/command.rb +86 -0
  16. data/lib/machines/commandline.rb +148 -0
  17. data/lib/machines/configuration.rb +49 -0
  18. data/lib/machines/core.rb +117 -0
  19. data/lib/machines/database.rb +17 -0
  20. data/lib/machines/file_operations.rb +104 -0
  21. data/lib/machines/help.rb +30 -0
  22. data/lib/machines/installation.rb +151 -0
  23. data/lib/machines/log_command.rb +22 -0
  24. data/lib/machines/logger.rb +65 -0
  25. data/lib/machines/machinesfile.rb +25 -0
  26. data/lib/machines/named_buffer.rb +9 -0
  27. data/lib/machines/questions.rb +15 -0
  28. data/lib/machines/services.rb +24 -0
  29. data/lib/machines/upload.rb +29 -0
  30. data/lib/machines/version.rb +4 -0
  31. data/lib/machines.rb +19 -0
  32. data/lib/packages/abiword.rb +11 -0
  33. data/lib/packages/amazon_mp3.rb +4 -0
  34. data/lib/packages/awstats.rb +16 -0
  35. data/lib/packages/base.rb +14 -0
  36. data/lib/packages/chrome.rb +12 -0
  37. data/lib/packages/cruisecontrol.rb +22 -0
  38. data/lib/packages/dependencies.rb +10 -0
  39. data/lib/packages/docky.rb +36 -0
  40. data/lib/packages/dotfiles.rb +26 -0
  41. data/lib/packages/file_roller.rb +12 -0
  42. data/lib/packages/finalise.rb +4 -0
  43. data/lib/packages/firefox.rb +4 -0
  44. data/lib/packages/gedit.rb +11 -0
  45. data/lib/packages/git.rb +4 -0
  46. data/lib/packages/gmate.rb +33 -0
  47. data/lib/packages/gnome.rb +10 -0
  48. data/lib/packages/gnumeric.rb +11 -0
  49. data/lib/packages/hosts.rb +13 -0
  50. data/lib/packages/load_machines.rb +38 -0
  51. data/lib/packages/monit.rb +10 -0
  52. data/lib/packages/mysql.rb +46 -0
  53. data/lib/packages/nginx.rb +22 -0
  54. data/lib/packages/nginx_logrotate.rb +26 -0
  55. data/lib/packages/openbox.rb +35 -0
  56. data/lib/packages/passenger.rb +14 -0
  57. data/lib/packages/passenger_nginx.rb +8 -0
  58. data/lib/packages/postfix.rb +10 -0
  59. data/lib/packages/questions.rb +5 -0
  60. data/lib/packages/rbenv.rb +27 -0
  61. data/lib/packages/rvm.rb +20 -0
  62. data/lib/packages/save_machines.rb +4 -0
  63. data/lib/packages/slim.rb +6 -0
  64. data/lib/packages/sqlserver.rb +5 -0
  65. data/lib/packages/subtle.rb +29 -0
  66. data/lib/packages/sudo_mods.rb +6 -0
  67. data/lib/packages/time.rb +6 -0
  68. data/lib/packages/time_daily.rb +5 -0
  69. data/lib/packages/timezone.rb +10 -0
  70. data/lib/packages/unison.rb +5 -0
  71. data/lib/packages/virtualbox.rb +11 -0
  72. data/lib/packages/virtualbox_guest.rb +7 -0
  73. data/lib/packages/webapps.rb +36 -0
  74. data/lib/template/Machinesfile +48 -0
  75. data/lib/template/certificates/example.com.crt +0 -0
  76. data/lib/template/certificates/example.com.key +0 -0
  77. data/lib/template/certificates/selfsigned.crt +14 -0
  78. data/lib/template/certificates/selfsigned.key +16 -0
  79. data/lib/template/config.yml +98 -0
  80. data/lib/template/logrotate/app.erb +10 -0
  81. data/lib/template/logrotate/nginx.erb +12 -0
  82. data/lib/template/machines.yml +179 -0
  83. data/lib/template/misc/awstats.conf.erb +7 -0
  84. data/lib/template/misc/ntp.conf +7 -0
  85. data/lib/template/monit/conf.d/delayed_job.erb +11 -0
  86. data/lib/template/monit/conf.d/mysql.erb +7 -0
  87. data/lib/template/monit/conf.d/nginx +5 -0
  88. data/lib/template/monit/conf.d/postfix +7 -0
  89. data/lib/template/monit/conf.d/ssh +6 -0
  90. data/lib/template/monit/conf.d/system.erb +14 -0
  91. data/lib/template/monit/monitrc.erb +10 -0
  92. data/lib/template/monit/upstart.conf +16 -0
  93. data/lib/template/mysql/dbmaster.cnf +7 -0
  94. data/lib/template/mysql/dbslave.cnf +3 -0
  95. data/lib/template/nginx/app_server.conf.erb +87 -0
  96. data/lib/template/nginx/nginx.conf.erb +46 -0
  97. data/lib/template/nginx/upstart.conf.erb +21 -0
  98. data/lib/template/packages/custom.rb +17 -0
  99. data/lib/template/packages/productivity.rb +18 -0
  100. data/lib/template/slim/themes/dark/background.jpg +0 -0
  101. data/lib/template/slim/themes/dark/panel.png +0 -0
  102. data/lib/template/slim/themes/dark/slim.theme +39 -0
  103. data/lib/template/users/phil/dotfiles/bash_aliases +45 -0
  104. data/lib/template/users/phil/dotfiles/config/Trolltech.conf +4 -0
  105. data/lib/template/users/phil/dotfiles/config/gtk-3.0/settings.ini +9 -0
  106. data/lib/template/users/phil/dotfiles/config/openbox/autostart.sh +14 -0
  107. data/lib/template/users/phil/dotfiles/config/openbox/rc.xml +482 -0
  108. data/lib/template/users/phil/dotfiles/config/terminator/config +10 -0
  109. data/lib/template/users/phil/dotfiles/fonts.conf +15 -0
  110. data/lib/template/users/phil/dotfiles/gitconfig +27 -0
  111. data/lib/template/users/phil/dotfiles/gtkrc-2.0 +16 -0
  112. data/lib/template/users/phil/dotfiles/local/share/applications/mimeapps.list +4 -0
  113. data/lib/template/users/phil/dotfiles/unison/default.prf +33 -0
  114. data/lib/template/users/www/authorized_keys +0 -0
  115. data/lib/template/users/www/dotfiles/bash_aliases +40 -0
  116. data/lib/template/webapps.yml +75 -0
  117. data/machines.gemspec +44 -0
  118. data/spec/acceptance/dev_machine_spec.rb +22 -0
  119. data/spec/lib/machines/app_settings_spec.rb +106 -0
  120. data/spec/lib/machines/checks_spec.rb +105 -0
  121. data/spec/lib/machines/cloud_machine_spec.rb +36 -0
  122. data/spec/lib/machines/command_spec.rb +184 -0
  123. data/spec/lib/machines/commandline_spec.rb +299 -0
  124. data/spec/lib/machines/configuration_spec.rb +61 -0
  125. data/spec/lib/machines/core_spec.rb +299 -0
  126. data/spec/lib/machines/database_spec.rb +51 -0
  127. data/spec/lib/machines/file_operations_spec.rb +124 -0
  128. data/spec/lib/machines/help_spec.rb +22 -0
  129. data/spec/lib/machines/installation_spec.rb +176 -0
  130. data/spec/lib/machines/log_command_spec.rb +16 -0
  131. data/spec/lib/machines/logger_spec.rb +70 -0
  132. data/spec/lib/machines/machinesfile_spec.rb +34 -0
  133. data/spec/lib/machines/questions_spec.rb +73 -0
  134. data/spec/lib/machines/services_spec.rb +26 -0
  135. data/spec/lib/machines/upload_spec.rb +86 -0
  136. data/spec/lib/packages/abiword_spec.rb +20 -0
  137. data/spec/lib/packages/amazon_mp3_spec.rb +17 -0
  138. data/spec/lib/packages/awstats_spec.rb +26 -0
  139. data/spec/lib/packages/base_spec.rb +21 -0
  140. data/spec/lib/packages/chrome_spec.rb +30 -0
  141. data/spec/lib/packages/cruisecontrol_spec.rb +33 -0
  142. data/spec/lib/packages/dependencies_spec.rb +20 -0
  143. data/spec/lib/packages/docky_spec.rb +32 -0
  144. data/spec/lib/packages/dotfiles_spec.rb +44 -0
  145. data/spec/lib/packages/file_roller_spec.rb +69 -0
  146. data/spec/lib/packages/firefox_spec.rb +16 -0
  147. data/spec/lib/packages/gedit_spec.rb +20 -0
  148. data/spec/lib/packages/git_spec.rb +16 -0
  149. data/spec/lib/packages/gmate_spec.rb +39 -0
  150. data/spec/lib/packages/gnome_spec.rb +22 -0
  151. data/spec/lib/packages/gnumeric_spec.rb +21 -0
  152. data/spec/lib/packages/hosts_spec.rb +41 -0
  153. data/spec/lib/packages/load_machines_spec.rb +118 -0
  154. data/spec/lib/packages/monit_spec.rb +34 -0
  155. data/spec/lib/packages/mysql_spec.rb +69 -0
  156. data/spec/lib/packages/nginx_logrotate_spec.rb +80 -0
  157. data/spec/lib/packages/nginx_spec.rb +46 -0
  158. data/spec/lib/packages/openbox_spec.rb +41 -0
  159. data/spec/lib/packages/passenger_nginx_spec.rb +20 -0
  160. data/spec/lib/packages/passenger_spec.rb +26 -0
  161. data/spec/lib/packages/postfix_spec.rb +19 -0
  162. data/spec/lib/packages/questions_spec.rb +29 -0
  163. data/spec/lib/packages/rbenv_spec.rb +32 -0
  164. data/spec/lib/packages/rvm_spec.rb +31 -0
  165. data/spec/lib/packages/save_machines_spec.rb +51 -0
  166. data/spec/lib/packages/slim_spec.rb +22 -0
  167. data/spec/lib/packages/sqlserver_spec.rb +17 -0
  168. data/spec/lib/packages/timezone_spec.rb +27 -0
  169. data/spec/lib/packages/unison_spec.rb +17 -0
  170. data/spec/lib/packages/virtualbox_guest_spec.rb +25 -0
  171. data/spec/lib/packages/virtualbox_spec.rb +23 -0
  172. data/spec/lib/packages/webapps_spec.rb +70 -0
  173. data/spec/spec_helper.rb +103 -0
  174. data/spec/support/coverage.rb +8 -0
  175. data/spec/support/fake_out.rb +22 -0
  176. data/spec/support/fakefs_additions.rb +10 -0
  177. data/spec/support/minitest.rb +69 -0
  178. data/spec/support/vm_control.rb +54 -0
  179. data/tmp/.gitkeep +0 -0
  180. metadata +581 -0
@@ -0,0 +1,299 @@
1
+ require 'spec_helper'
2
+
3
+ describe Machines::Commandline do
4
+ include Machines::Core
5
+ include Machines::Commandline
6
+ include Machines::Questions
7
+
8
+ before(:each) do
9
+ $conf.log_only = false
10
+ File.open('config.yml', 'w') { |f| f.puts "timezone: GB" }
11
+ FileUtils.mkdir_p 'log'
12
+ end
13
+
14
+ describe 'build' do
15
+ before(:each) do
16
+ stubs(:init)
17
+ FileUtils.touch('Machinesfile')
18
+ $conf.machine = AppConf.new
19
+ $conf.machine.address = 'target'
20
+ $conf.machine.user = 'username'
21
+ $conf.password = 'userpass'
22
+ Net::SCP.stubs(:new)
23
+ @ssh_stub = stub('Net::SSH', :close => nil, :exec! => nil)
24
+ Net::SSH.stubs(:start).returns @ssh_stub
25
+ end
26
+
27
+ it 'sets machine_name' do
28
+ build ['machine']
29
+ $conf.machine_name.must_equal 'machine'
30
+ end
31
+
32
+ it 'starts an SCP session using password authentication' do
33
+ Net::SSH.expects(:start).with('target', 'username', :paranoid => false, :password => 'userpass').returns @ssh_stub
34
+ build []
35
+ end
36
+
37
+ it 'starts an SCP session using key based authentication' do
38
+ $conf.machine.cloud = AppConf.new
39
+ $conf.machine.cloud.private_key_path = 'path/to/private_key'
40
+ $conf.machine.cloud.username = 'ubuntu'
41
+ Net::SSH.expects(:start).with('target', 'ubuntu', :paranoid => false, :keys => ['path/to/private_key']).returns @ssh_stub
42
+
43
+ build []
44
+ end
45
+
46
+ it 'runs each command' do
47
+ mock_command = mock 'Machines::Command'
48
+ $conf.commands = [mock_command]
49
+
50
+ mock_command.expects(:run)
51
+
52
+ build []
53
+ end
54
+
55
+ it 'flushes log file after running command' do
56
+ $conf.log_only = false
57
+ command_stub = stub('Machines::Command', :run => nil)
58
+ $conf.commands = [command_stub]
59
+
60
+ Machines::Command.file.expects(:flush)
61
+ build []
62
+ end
63
+
64
+ it 'replaces commands with the single task when supplied' do
65
+ command_will_run = Machines::Command.new '', ''
66
+ command_wont_run = Machines::Command.new '', ''
67
+ $conf.tasks = { :task => {:block => Proc.new { run command_will_run }} }
68
+
69
+ build ['machine', 'task']
70
+
71
+ $conf.commands.must_equal [command_will_run]
72
+ end
73
+
74
+ it 'logs instead of SSHing and running commands' do
75
+ Net::SCP.expects(:start).never
76
+ $conf.commands = [mock('Machines::Command')]
77
+ $conf.commands.first.expects(:run)
78
+ $conf.log_only = true
79
+ build []
80
+ end
81
+
82
+ describe 'interrupts' do
83
+ before(:each) do
84
+ mock_command = mock 'Machines::Command'
85
+ $conf.commands = [mock_command]
86
+
87
+ mock_command.stubs(:run)
88
+ $exit_requested = false
89
+ end
90
+
91
+ it 'handles CTRL+C and calls handler' do
92
+ expects(:prepare_to_exit)
93
+ Kernel.expects(:trap).with('INT').yields
94
+ build []
95
+ end
96
+
97
+
98
+ it 'sets exit flag and displays message' do
99
+ prepare_to_exit
100
+ $exit_requested.must_equal true
101
+ $console.next.must_equal colored("\nEXITING after current command completes...\n", :warning)
102
+ end
103
+
104
+ it 'second request to exit exits immediately' do
105
+ $exit_requested = true
106
+ expects(:exit)
107
+ prepare_to_exit
108
+ end
109
+
110
+ it 'exits when exit requested' do
111
+ $exit_requested = true
112
+ expects(:exit)
113
+
114
+ build []
115
+ end
116
+ end
117
+ end
118
+
119
+ describe 'dryrun' do
120
+ it 'asks build to only log commands' do
121
+ options = []
122
+ expects(:build).with options
123
+ dryrun options
124
+ $conf.log_only.must_equal true
125
+ end
126
+ end
127
+
128
+ describe 'execute' do
129
+ it 'calls specified action' do
130
+ Machines::Help.new.actions.reject{|a| a == 'new'}.each do |action|
131
+ expects action
132
+ execute [action]
133
+ end
134
+ end
135
+
136
+ it 'calls generate with folder' do
137
+ expects(:generate).with(['dir'])
138
+ execute ['new', 'dir']
139
+ end
140
+
141
+ it 'calls generate without folder' do
142
+ expects(:generate).with([])
143
+ execute ['new']
144
+ end
145
+
146
+ it 'calls help when no matching command' do
147
+ lambda { execute ['anything'] }.must_output Machines::Help.new.syntax
148
+ end
149
+ end
150
+
151
+ describe 'generate' do
152
+ it 'copies the template within ./' do
153
+ expects(:ask).with("Overwrite './' (y/n)? ").returns 'y'
154
+ FileUtils.expects(:cp_r).with("#{$conf.application_dir}/template/.", './')
155
+ FileUtils.expects(:mkdir_p).with('./packages')
156
+ generate []
157
+ end
158
+
159
+ it 'copies the template within dir' do
160
+ FileUtils.expects(:cp_r).with("#{$conf.application_dir}/template/.", 'dir')
161
+ FileUtils.expects(:mkdir_p).with(File.join('dir', 'packages'))
162
+ expects(:say).with('Project created at dir/')
163
+ generate ['dir']
164
+ end
165
+
166
+ describe 'when folder exists' do
167
+ before(:each) do
168
+ FileUtils.mkdir_p('dir')
169
+ end
170
+
171
+ it 'is overwritten after user confirmation' do
172
+ expects(:ask).with("Overwrite 'dir' (y/n)? ").returns 'y'
173
+ FileUtils.expects(:cp_r).with("#{$conf.application_dir}/template/.", 'dir')
174
+ FileUtils.expects(:mkdir_p).with(File.join('dir', 'packages'))
175
+ generate ['dir']
176
+ end
177
+
178
+ it 'generation is aborted at user request' do
179
+ expects(:ask).with("Overwrite 'dir' (y/n)? ").returns 'n'
180
+ FileUtils.expects(:cp_r).never
181
+ FileUtils.expects(:mkdir_p).never
182
+ generate ['dir']
183
+ end
184
+ end
185
+ end
186
+
187
+ describe 'htpasswd' do
188
+ it 'htpasswd is generated and saved' do
189
+ $conf.webserver = 'server'
190
+ $input.string = "user\npass\npass\n"
191
+ htpasswd nil
192
+ File.read('server/conf/htpasswd').must_match /user:.{13}/
193
+ end
194
+ end
195
+
196
+ describe 'init' do
197
+ it 'initializes some $conf settings and loads configs' do
198
+ Machines::Command.file = nil
199
+ Machines::Command.console = nil
200
+ Machines::Command.debug = nil
201
+ init
202
+ $conf.passwords.must_equal []
203
+ $conf.commands.must_equal []
204
+ $conf.tasks.must_equal({})
205
+ $conf.timezone.must_equal 'GB'
206
+ File.exists?('log/output.log').must_equal true
207
+ Machines::Command.file.must_be_instance_of Machines::Logger
208
+ Machines::Command.console.must_be_instance_of Machines::Logger
209
+ Machines::Command.debug.must_be_instance_of Machines::Logger
210
+ end
211
+ end
212
+
213
+ describe 'load_machinesfile' do
214
+ it 'raises LoadError with custom message when no Machinesfile' do
215
+ File.expects(:read).with("Machinesfile").raises LoadError.new('Machinesfile not found')
216
+
217
+ begin
218
+ load_machinesfile
219
+ rescue LoadError => e
220
+ e.message.must_equal 'Machinesfile does not exist. Use `machines new <DIR>` to create a template.'
221
+ end
222
+ end
223
+
224
+ it 'raises normal LoadError on other files' do
225
+ File.expects(:read).with("Machinesfile").raises LoadError
226
+
227
+ begin
228
+ load_machinesfile
229
+ rescue LoadError => e
230
+ e.message.must_equal 'LoadError'
231
+ end
232
+ end
233
+ end
234
+
235
+ describe 'override' do
236
+ before(:each) do
237
+ FileUtils.mkdir_p File.join($conf.application_dir, 'packages')
238
+ FileUtils.mkdir_p 'packages'
239
+ FileUtils.touch File.join($conf.application_dir, 'packages', 'base.rb')
240
+ end
241
+
242
+ it 'copies package to project folder' do
243
+ override ['base']
244
+ File.exists?('packages/base.rb').must_equal true
245
+ end
246
+
247
+ describe 'when copying over existing package' do
248
+ before(:each) do
249
+ FileUtils.touch 'packages/base.rb'
250
+ end
251
+
252
+ it 'terminates when user answer no' do
253
+ $input.string = "n\n"
254
+ lambda { override ['base'] }.must_output 'Project package already exists. Overwrite? (y/n)
255
+ Aborted.
256
+ '
257
+ end
258
+
259
+ it 'overwrites project package with default package' do
260
+ $input.string = "y\n"
261
+ lambda { override ['base'] }.must_output 'Project package already exists. Overwrite? (y/n)
262
+ Package copied to packages/base.rb
263
+ '
264
+ end
265
+ end
266
+ end
267
+
268
+ describe 'packages' do
269
+ it 'displays a list of default and project packages' do
270
+ FileUtils.mkdir_p File.join($conf.application_dir, 'packages')
271
+ FileUtils.mkdir_p 'packages'
272
+ FileUtils.touch File.join($conf.application_dir, 'packages', 'base.rb')
273
+ FileUtils.touch File.join('packages', 'apps.rb')
274
+ lambda { packages nil }.must_output 'Default packages
275
+ * base
276
+ Project packages
277
+ * apps
278
+ '
279
+ end
280
+ end
281
+
282
+ describe 'tasks' do
283
+ it 'displays a list of tasks' do
284
+ expects(:init)
285
+ expects(:load_machinesfile)
286
+ $conf.tasks = {
287
+ :task1 => {:description => 'description 1'},
288
+ :task2 => {:description => 'description 2'},
289
+ :task3 => {:description => 'description 3'}
290
+ }
291
+ lambda { tasks }.must_output 'Tasks
292
+ task1 description 1
293
+ task2 description 2
294
+ task3 description 3
295
+ '
296
+ end
297
+ end
298
+ end
299
+
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Configuration' do
4
+ include Machines::Core
5
+ include Machines::Configuration
6
+
7
+ describe 'add_user' do
8
+ it do
9
+ command = add_user 'login'
10
+ command.command.must_equal 'useradd -s /bin/bash -d /home/login -m login'
11
+ command.check.must_equal "test -d /home/login #{echo_result}"
12
+ end
13
+
14
+ it do
15
+ command = add_user 'a_user', :password => 'password', :admin => true
16
+ command.command.must_match /useradd -s \/bin\/bash -d \/home\/a_user -m -p .* -G admin a_user/
17
+ command.check.must_equal "test -d /home/a_user #{echo_result}"
18
+ end
19
+ end
20
+
21
+ describe 'add' do
22
+ it 'add an existing user to a group' do
23
+ command = add :user => 'phil', :to => 'group'
24
+ command.command.must_equal 'usermod -a -G group phil'
25
+ end
26
+ end
27
+
28
+ describe 'configure' do
29
+ before(:each) do
30
+ @options = {:string => 'str', :number => 123, :t => true, :f => false, :float => 1.1, :array => ['item 1', 'item 2']}
31
+ end
32
+
33
+ it 'supports different types' do
34
+ commands = configure @options
35
+ commands.map(&:command).must_equal [
36
+ 'gconftool-2 --set "string" --type string "str"',
37
+ 'gconftool-2 --set "number" --type int 123',
38
+ 'gconftool-2 --set "t" --type bool true',
39
+ 'gconftool-2 --set "f" --type bool false',
40
+ 'gconftool-2 --set "float" --type float 1.1',
41
+ 'gconftool-2 --set "array" --type list --list-type=string ["item 1","item 2"]'
42
+ ]
43
+ end
44
+
45
+ it 'checks value has been set' do
46
+ command = configure 'key' => 'value'
47
+ command.first.check.must_equal 'gconftool-2 --get "key" | grep "value" ' + echo_result
48
+ end
49
+
50
+ it { lambda{ configure(:invalid_type => Object.new) }.must_raise RuntimeError }
51
+ end
52
+
53
+ describe 'del_user' do
54
+ it 'calls deluser with remove-all-files option' do
55
+ subject = del_user 'login'
56
+ subject.command.must_equal 'deluser login --remove-home -q'
57
+ subject.check.must_equal "test ! -s /home/login #{echo_result}"
58
+ end
59
+ end
60
+ end
61
+
@@ -0,0 +1,299 @@
1
+ require 'spec_helper'
2
+
3
+ describe Machines::Core do
4
+ include Machines::Core
5
+ include Machines::FileOperations
6
+
7
+ before do
8
+ @command1 = Machines::Command.new('command 1', 'check 1')
9
+ @command2 = Machines::Command.new('command 2', 'check 2')
10
+ end
11
+
12
+ describe 'generate_password' do
13
+ it 'generates a random password' do
14
+ WEBrick::Utils.stubs(:random_string).with(20).returns '01234567890123456789'
15
+ generate_password.must_equal '01234567890123456789'
16
+ end
17
+ end
18
+
19
+ describe 'task' do
20
+ it 'yields' do
21
+ yielded = false
22
+ task :name do
23
+ yielded = true
24
+ end
25
+ yielded.must_equal true
26
+ end
27
+
28
+ it 'logs the task' do
29
+ task :name, 'description' do
30
+ end
31
+ $conf.commands.first.info.must_equal "TASK name - description"
32
+ end
33
+
34
+ it 'stores task' do
35
+ block = Proc.new {}
36
+ task :name, 'description', &block
37
+ $conf.tasks.must_equal :name => {:description => 'description', :block => block}
38
+ end
39
+
40
+ it 'sets commands to only run those from the specified task' do
41
+ block_ran = false
42
+ block = Proc.new { block_ran = true }
43
+ $conf.tasks[:name] = {:block => block}
44
+ task :name, nil
45
+ block_ran.must_equal true
46
+ end
47
+
48
+ describe 'when dependent task' do
49
+ before(:each) do
50
+ @yielded = false
51
+ @block = Proc.new { @yielded = true }
52
+ end
53
+
54
+ describe 'exists' do
55
+ before(:each) do
56
+ store_task :dependent_task, nil
57
+ task :name, nil, :if => :dependent_task, &@block
58
+ end
59
+
60
+ it { @yielded.must_equal true }
61
+ it 'task stored' do
62
+ $conf.tasks.must_include :name
63
+ end
64
+ end
65
+
66
+ describe 'does not exist' do
67
+ before(:each) { task :name, nil, :if => :dependent_task, &@block }
68
+ it { @yielded.must_equal false }
69
+ it 'task not stored' do
70
+ $conf.tasks.wont_include :name
71
+ end
72
+ end
73
+ end
74
+
75
+ describe 'when multiple dependent tasks' do
76
+ before(:each) do
77
+ @yielded = false
78
+ @block = Proc.new { @yielded = true }
79
+ end
80
+
81
+ describe 'all exist' do
82
+ before(:each) do
83
+ store_task :dependent_task, nil
84
+ store_task :another_dependent, nil
85
+ task :name, nil, :if => [:dependent_task, :another_dependent], &@block
86
+ end
87
+
88
+ it { @yielded.must_equal true }
89
+ it 'task stored' do
90
+ $conf.tasks.must_include :name
91
+ end
92
+ end
93
+
94
+ describe 'all but one exist' do
95
+ before(:each) do
96
+ store_task :another_dependent, nil
97
+ task :name, nil, :if => [:dependent_task, :another_dependent], &@block
98
+ end
99
+
100
+ it { @yielded.must_equal false }
101
+ it 'task not stored' do
102
+ $conf.tasks.wont_include :name
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ describe 'list_tasks' do
109
+ it 'displays a list of tasks' do
110
+ task :name, 'description', &Proc.new {}
111
+ task :another, 'another description', &Proc.new {}
112
+ lambda { list_tasks }.must_output ' name description
113
+ another another description
114
+ '
115
+ end
116
+ end
117
+
118
+ describe 'only' do
119
+ it 'yields when matched' do
120
+ expects(:matched).with('options').returns true
121
+ yielded = false
122
+ only 'options' do
123
+ yielded = true
124
+ end
125
+ yielded.must_equal true
126
+ end
127
+
128
+ it 'does not yield when not matched' do
129
+ expects(:matched).with('options').returns false
130
+ yielded = false
131
+ only 'options' do
132
+ yielded = true
133
+ end
134
+ yielded.must_equal false
135
+ end
136
+
137
+ it 'yields when symbol matches string' do
138
+ $conf.environment = 'development'
139
+ yielded = false
140
+ only :environment => :development do
141
+ yielded = true
142
+ end
143
+ yielded.must_equal true
144
+ end
145
+ end
146
+
147
+ describe 'except' do
148
+ it 'does not yield when matched' do
149
+ expects(:matched).with('options').returns true
150
+ yielded = false
151
+ except 'options' do
152
+ yielded = true
153
+ end
154
+ yielded.must_equal false
155
+ end
156
+
157
+ it 'yields when not matched' do
158
+ expects(:matched).with('options').returns false
159
+ yielded = false
160
+ except 'options' do
161
+ yielded = true
162
+ end
163
+ yielded.must_equal true
164
+ end
165
+ end
166
+
167
+ describe 'matched' do
168
+ describe '$conf values are strings' do
169
+ before do
170
+ $conf.string_param = 'matched'
171
+ end
172
+
173
+ it { matched(:string_param => :matched).must_equal true }
174
+ it { matched(:string_param => 'matched').must_equal true }
175
+ it { matched(:string_param => :unmatched).wont_equal true }
176
+ end
177
+
178
+ describe '$conf values are arrays' do
179
+ before do
180
+ $conf.params_array = [:matched, :another]
181
+ end
182
+
183
+ describe 'options values are arrays of symbols' do
184
+ it { matched({:params_array => [:matched]}).must_equal true }
185
+ it { matched({:params_array => [:unmatched]}).wont_equal true }
186
+ end
187
+
188
+ describe 'options values are arrays of strings' do
189
+ it { matched({'params_array' => ['matched']}).must_equal true }
190
+ it { matched({'params_array' => ['unmatched']}).wont_equal true }
191
+ end
192
+
193
+ describe 'options values are symbols' do
194
+ it { matched({:params_array => :matched}).must_equal true }
195
+ it { matched({:params_array => :unmatched}).wont_equal true }
196
+ end
197
+
198
+ describe 'options values are strings' do
199
+ it { matched({:params_array => 'matched'}).must_equal true }
200
+ it { matched({:params_array => 'unmatched'}).wont_equal true }
201
+ end
202
+ end
203
+
204
+ describe '$conf values are symbols' do
205
+ before do
206
+ $conf.single_param = :matched
207
+ end
208
+
209
+ describe 'options values are arrays' do
210
+ it { matched({:single_param => [:matched]}).must_equal true }
211
+ it { matched({:single_param => [:unmatched]}).wont_equal true }
212
+ end
213
+
214
+ describe 'options values are symbols' do
215
+ it { matched({:single_param => :matched}).must_equal true }
216
+ it { matched({:single_param => :unmatched}).wont_equal true }
217
+ end
218
+ end
219
+ end
220
+
221
+ describe 'run' do
222
+ it 'adds a command to the commands array' do
223
+ run @command1
224
+ $conf.commands.must_equal [@command1]
225
+ end
226
+
227
+ it 'appends several commands' do
228
+ run @command1
229
+ run @command2
230
+ $conf.commands.must_equal [@command1, @command2]
231
+ end
232
+
233
+ it 'appends several commands in a single call' do
234
+ run @command1, @command2
235
+ $conf.commands.must_equal [@command1, @command2]
236
+ end
237
+
238
+ describe 'when commands are two strings' do
239
+ it 'creates a Command' do
240
+ run 'command', 'check'
241
+ $conf.commands.first.command.must_equal 'command'
242
+ $conf.commands.first.check.must_equal 'check'
243
+ end
244
+ end
245
+ end
246
+
247
+ describe 'sudo' do
248
+ it 'wraps a command in a sudo with password call' do
249
+ $conf.password = 'password'
250
+ @command1.expects(:use_sudo)
251
+ sudo @command1
252
+ end
253
+
254
+ describe 'when commands are two strings' do
255
+ it 'creates a Command' do
256
+ sudo 'command', 'check'
257
+ $conf.commands.first.command.must_equal 'command'
258
+ $conf.commands.first.check.must_equal 'check'
259
+ end
260
+ end
261
+ end
262
+
263
+ describe 'upload' do
264
+ subject { upload 'source', 'dest' }
265
+ it { subject.local.must_equal 'source' }
266
+ it { subject.remote.must_equal 'dest' }
267
+ end
268
+
269
+ describe 'sudo upload' do
270
+ it 'modifies Upload to send it to a temp file and sudos to copy it to destination' do
271
+ File.stubs(:directory?).returns false
272
+ sudo upload 'source', 'dest'
273
+
274
+ $conf.commands.map(&:command).must_equal [nil, "cp -rf /tmp/dest dest", "rm -rf /tmp/dest"]
275
+ $conf.commands.map(&:check).must_equal [
276
+ "test -s /tmp/dest && echo CHECK PASSED || echo CHECK FAILED",
277
+ "test -s dest && echo CHECK PASSED || echo CHECK FAILED",
278
+ "test ! -s /tmp/dest && echo CHECK PASSED || echo CHECK FAILED"
279
+ ]
280
+ end
281
+
282
+ it 'adds /. to the end of folder paths' do
283
+ File.stubs(:directory?).with('source').returns true
284
+ sudo upload 'source', 'dest'
285
+ $conf.commands.map(&:command).must_equal [nil, "cp -rf /tmp/dest/. dest", "rm -rf /tmp/dest"]
286
+ end
287
+ end
288
+
289
+ describe 'required_options' do
290
+ it 'does not raise when option exists' do
291
+ required_options({:required => :option}, [:required])
292
+ end
293
+
294
+ it 'raises when option does not exist' do
295
+ lambda{required_options({}, [:required])}.must_raise(ArgumentError)
296
+ end
297
+ end
298
+ end
299
+
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Database' do
4
+ include Machines::Core
5
+ include Machines::Configuration
6
+ include Machines::Database
7
+ include Machines::AppSettings
8
+ include Machines::FileOperations
9
+
10
+ describe 'write_database_yml' do
11
+ before do
12
+ $conf.environment = 'staging'
13
+ $conf.db_server = AppConf.new
14
+ $conf.db_server.address = 'dbhost'
15
+ end
16
+
17
+ it 'supplies correct parameters' do
18
+ file = write_database_yml AppBuilder.new(:name => 'app', :password => 'password', :path => 'path')
19
+ file.local.read.must_equal <<-EOF
20
+ ---
21
+ staging:
22
+ adapter: mysql
23
+ database: app
24
+ username: app
25
+ password: password
26
+ host: dbhost
27
+ encoding: utf8
28
+ EOF
29
+ end
30
+
31
+ it 'writes file to specified path' do
32
+ file = write_database_yml AppBuilder.new(:name => 'app', :password => 'password', :path => 'path')
33
+ file.remote.must_equal 'path/shared/config/database.yml'
34
+ end
35
+
36
+ it 'overrides database name when supplied' do
37
+ file = write_database_yml AppBuilder.new(:name => 'app', :password => 'password', :username => 'phil', :database => 'myapp', :path => 'path')
38
+ file.local.read.must_equal <<-EOF
39
+ ---
40
+ staging:
41
+ adapter: mysql
42
+ database: myapp
43
+ username: phil
44
+ password: password
45
+ host: dbhost
46
+ encoding: utf8
47
+ EOF
48
+ end
49
+ end
50
+ end
51
+