machines 0.5.1
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.
- data/.gitignore +11 -0
- data/EXAMPLES.md +18 -0
- data/Gemfile +4 -0
- data/Guardfile +14 -0
- data/INSTALL.md +25 -0
- data/LICENSE +23 -0
- data/README.md +271 -0
- data/Rakefile +60 -0
- data/TODO.md +92 -0
- data/bin/machines +6 -0
- data/lib/machines/app_settings.rb +54 -0
- data/lib/machines/base.rb +13 -0
- data/lib/machines/checks.rb +63 -0
- data/lib/machines/cloud_machine.rb +33 -0
- data/lib/machines/command.rb +86 -0
- data/lib/machines/commandline.rb +148 -0
- data/lib/machines/configuration.rb +49 -0
- data/lib/machines/core.rb +117 -0
- data/lib/machines/database.rb +17 -0
- data/lib/machines/file_operations.rb +104 -0
- data/lib/machines/help.rb +30 -0
- data/lib/machines/installation.rb +151 -0
- data/lib/machines/log_command.rb +22 -0
- data/lib/machines/logger.rb +65 -0
- data/lib/machines/machinesfile.rb +25 -0
- data/lib/machines/named_buffer.rb +9 -0
- data/lib/machines/questions.rb +15 -0
- data/lib/machines/services.rb +24 -0
- data/lib/machines/upload.rb +29 -0
- data/lib/machines/version.rb +4 -0
- data/lib/machines.rb +19 -0
- data/lib/packages/abiword.rb +11 -0
- data/lib/packages/amazon_mp3.rb +4 -0
- data/lib/packages/awstats.rb +16 -0
- data/lib/packages/base.rb +14 -0
- data/lib/packages/chrome.rb +12 -0
- data/lib/packages/cruisecontrol.rb +22 -0
- data/lib/packages/dependencies.rb +10 -0
- data/lib/packages/docky.rb +36 -0
- data/lib/packages/dotfiles.rb +26 -0
- data/lib/packages/file_roller.rb +12 -0
- data/lib/packages/finalise.rb +4 -0
- data/lib/packages/firefox.rb +4 -0
- data/lib/packages/gedit.rb +11 -0
- data/lib/packages/git.rb +4 -0
- data/lib/packages/gmate.rb +33 -0
- data/lib/packages/gnome.rb +10 -0
- data/lib/packages/gnumeric.rb +11 -0
- data/lib/packages/hosts.rb +13 -0
- data/lib/packages/load_machines.rb +38 -0
- data/lib/packages/monit.rb +10 -0
- data/lib/packages/mysql.rb +46 -0
- data/lib/packages/nginx.rb +22 -0
- data/lib/packages/nginx_logrotate.rb +26 -0
- data/lib/packages/openbox.rb +35 -0
- data/lib/packages/passenger.rb +14 -0
- data/lib/packages/passenger_nginx.rb +8 -0
- data/lib/packages/postfix.rb +10 -0
- data/lib/packages/questions.rb +5 -0
- data/lib/packages/rbenv.rb +27 -0
- data/lib/packages/rvm.rb +20 -0
- data/lib/packages/save_machines.rb +4 -0
- data/lib/packages/slim.rb +6 -0
- data/lib/packages/sqlserver.rb +5 -0
- data/lib/packages/subtle.rb +29 -0
- data/lib/packages/sudo_mods.rb +6 -0
- data/lib/packages/time.rb +6 -0
- data/lib/packages/time_daily.rb +5 -0
- data/lib/packages/timezone.rb +10 -0
- data/lib/packages/unison.rb +5 -0
- data/lib/packages/virtualbox.rb +11 -0
- data/lib/packages/virtualbox_guest.rb +7 -0
- data/lib/packages/webapps.rb +36 -0
- data/lib/template/Machinesfile +48 -0
- data/lib/template/certificates/example.com.crt +0 -0
- data/lib/template/certificates/example.com.key +0 -0
- data/lib/template/certificates/selfsigned.crt +14 -0
- data/lib/template/certificates/selfsigned.key +16 -0
- data/lib/template/config.yml +98 -0
- data/lib/template/logrotate/app.erb +10 -0
- data/lib/template/logrotate/nginx.erb +12 -0
- data/lib/template/machines.yml +179 -0
- data/lib/template/misc/awstats.conf.erb +7 -0
- data/lib/template/misc/ntp.conf +7 -0
- data/lib/template/monit/conf.d/delayed_job.erb +11 -0
- data/lib/template/monit/conf.d/mysql.erb +7 -0
- data/lib/template/monit/conf.d/nginx +5 -0
- data/lib/template/monit/conf.d/postfix +7 -0
- data/lib/template/monit/conf.d/ssh +6 -0
- data/lib/template/monit/conf.d/system.erb +14 -0
- data/lib/template/monit/monitrc.erb +10 -0
- data/lib/template/monit/upstart.conf +16 -0
- data/lib/template/mysql/dbmaster.cnf +7 -0
- data/lib/template/mysql/dbslave.cnf +3 -0
- data/lib/template/nginx/app_server.conf.erb +87 -0
- data/lib/template/nginx/nginx.conf.erb +46 -0
- data/lib/template/nginx/upstart.conf.erb +21 -0
- data/lib/template/packages/custom.rb +17 -0
- data/lib/template/packages/productivity.rb +18 -0
- data/lib/template/slim/themes/dark/background.jpg +0 -0
- data/lib/template/slim/themes/dark/panel.png +0 -0
- data/lib/template/slim/themes/dark/slim.theme +39 -0
- data/lib/template/users/phil/dotfiles/bash_aliases +45 -0
- data/lib/template/users/phil/dotfiles/config/Trolltech.conf +4 -0
- data/lib/template/users/phil/dotfiles/config/gtk-3.0/settings.ini +9 -0
- data/lib/template/users/phil/dotfiles/config/openbox/autostart.sh +14 -0
- data/lib/template/users/phil/dotfiles/config/openbox/rc.xml +482 -0
- data/lib/template/users/phil/dotfiles/config/terminator/config +10 -0
- data/lib/template/users/phil/dotfiles/fonts.conf +15 -0
- data/lib/template/users/phil/dotfiles/gitconfig +27 -0
- data/lib/template/users/phil/dotfiles/gtkrc-2.0 +16 -0
- data/lib/template/users/phil/dotfiles/local/share/applications/mimeapps.list +4 -0
- data/lib/template/users/phil/dotfiles/unison/default.prf +33 -0
- data/lib/template/users/www/authorized_keys +0 -0
- data/lib/template/users/www/dotfiles/bash_aliases +40 -0
- data/lib/template/webapps.yml +75 -0
- data/machines.gemspec +44 -0
- data/spec/acceptance/dev_machine_spec.rb +22 -0
- data/spec/lib/machines/app_settings_spec.rb +106 -0
- data/spec/lib/machines/checks_spec.rb +105 -0
- data/spec/lib/machines/cloud_machine_spec.rb +36 -0
- data/spec/lib/machines/command_spec.rb +184 -0
- data/spec/lib/machines/commandline_spec.rb +299 -0
- data/spec/lib/machines/configuration_spec.rb +61 -0
- data/spec/lib/machines/core_spec.rb +299 -0
- data/spec/lib/machines/database_spec.rb +51 -0
- data/spec/lib/machines/file_operations_spec.rb +124 -0
- data/spec/lib/machines/help_spec.rb +22 -0
- data/spec/lib/machines/installation_spec.rb +176 -0
- data/spec/lib/machines/log_command_spec.rb +16 -0
- data/spec/lib/machines/logger_spec.rb +70 -0
- data/spec/lib/machines/machinesfile_spec.rb +34 -0
- data/spec/lib/machines/questions_spec.rb +73 -0
- data/spec/lib/machines/services_spec.rb +26 -0
- data/spec/lib/machines/upload_spec.rb +86 -0
- data/spec/lib/packages/abiword_spec.rb +20 -0
- data/spec/lib/packages/amazon_mp3_spec.rb +17 -0
- data/spec/lib/packages/awstats_spec.rb +26 -0
- data/spec/lib/packages/base_spec.rb +21 -0
- data/spec/lib/packages/chrome_spec.rb +30 -0
- data/spec/lib/packages/cruisecontrol_spec.rb +33 -0
- data/spec/lib/packages/dependencies_spec.rb +20 -0
- data/spec/lib/packages/docky_spec.rb +32 -0
- data/spec/lib/packages/dotfiles_spec.rb +44 -0
- data/spec/lib/packages/file_roller_spec.rb +69 -0
- data/spec/lib/packages/firefox_spec.rb +16 -0
- data/spec/lib/packages/gedit_spec.rb +20 -0
- data/spec/lib/packages/git_spec.rb +16 -0
- data/spec/lib/packages/gmate_spec.rb +39 -0
- data/spec/lib/packages/gnome_spec.rb +22 -0
- data/spec/lib/packages/gnumeric_spec.rb +21 -0
- data/spec/lib/packages/hosts_spec.rb +41 -0
- data/spec/lib/packages/load_machines_spec.rb +118 -0
- data/spec/lib/packages/monit_spec.rb +34 -0
- data/spec/lib/packages/mysql_spec.rb +69 -0
- data/spec/lib/packages/nginx_logrotate_spec.rb +80 -0
- data/spec/lib/packages/nginx_spec.rb +46 -0
- data/spec/lib/packages/openbox_spec.rb +41 -0
- data/spec/lib/packages/passenger_nginx_spec.rb +20 -0
- data/spec/lib/packages/passenger_spec.rb +26 -0
- data/spec/lib/packages/postfix_spec.rb +19 -0
- data/spec/lib/packages/questions_spec.rb +29 -0
- data/spec/lib/packages/rbenv_spec.rb +32 -0
- data/spec/lib/packages/rvm_spec.rb +31 -0
- data/spec/lib/packages/save_machines_spec.rb +51 -0
- data/spec/lib/packages/slim_spec.rb +22 -0
- data/spec/lib/packages/sqlserver_spec.rb +17 -0
- data/spec/lib/packages/timezone_spec.rb +27 -0
- data/spec/lib/packages/unison_spec.rb +17 -0
- data/spec/lib/packages/virtualbox_guest_spec.rb +25 -0
- data/spec/lib/packages/virtualbox_spec.rb +23 -0
- data/spec/lib/packages/webapps_spec.rb +70 -0
- data/spec/spec_helper.rb +103 -0
- data/spec/support/coverage.rb +8 -0
- data/spec/support/fake_out.rb +22 -0
- data/spec/support/fakefs_additions.rb +10 -0
- data/spec/support/minitest.rb +69 -0
- data/spec/support/vm_control.rb +54 -0
- data/tmp/.gitkeep +0 -0
- 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
|
+
|