richmeyers-whenever 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,58 @@
1
+ module Whenever
2
+ module Output
3
+ class Redirection
4
+
5
+ def initialize(output)
6
+ @output = output
7
+ end
8
+
9
+ def to_s
10
+ return '' unless defined?(@output)
11
+ case @output
12
+ when String then redirect_from_string
13
+ when Hash then redirect_from_hash
14
+ when NilClass then ">> /dev/null 2>&1"
15
+ else ''
16
+ end
17
+ end
18
+
19
+ protected
20
+
21
+ def stdout
22
+ return unless @output.has_key?(:standard)
23
+ @output[:standard].nil? ? '/dev/null' : @output[:standard]
24
+ end
25
+
26
+ def stderr
27
+ return unless @output.has_key?(:error)
28
+ @output[:error].nil? ? '/dev/null' : @output[:error]
29
+ end
30
+
31
+ def redirect_from_hash
32
+ case
33
+ when stdout == '/dev/null' && stderr == '/dev/null'
34
+ "> /dev/null 2>&1"
35
+ when stdout && stderr == '/dev/null'
36
+ ">> #{stdout} 2> /dev/null"
37
+ when stdout && stderr
38
+ ">> #{stdout} 2>> #{stderr}"
39
+ when stderr == '/dev/null'
40
+ "2> /dev/null"
41
+ when stderr
42
+ "2>> #{stderr}"
43
+ when stdout == '/dev/null'
44
+ "> /dev/null"
45
+ when stdout
46
+ ">> #{stdout}"
47
+ else
48
+ ''
49
+ end
50
+ end
51
+
52
+ def redirect_from_string
53
+ ">> #{@output} 2>&1"
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,18 @@
1
+ # Environemnt defaults to production
2
+ set :environment, "production"
3
+ # Path defaults to the directory `whenever` was run from
4
+ set :path, Whenever.path
5
+
6
+ # All jobs are wrapped in this template.
7
+ # http://blog.scoutapp.com/articles/2010/09/07/rvm-and-cron-in-production
8
+ set :job_template, "/bin/bash -l -c ':job'"
9
+
10
+ job_type :command, ":task :output"
11
+ job_type :rake, "cd :path && RAILS_ENV=:environment rake :task --silent :output"
12
+
13
+ # Create a runner job that's appropriate for the Rails version,
14
+ if File.exists?(File.join(path, 'script', 'rails'))
15
+ job_type :runner, "cd :path && script/rails runner -e :environment ':task' :output"
16
+ else
17
+ job_type :runner, "cd :path && script/runner -e :environment ':task' :output"
18
+ end
@@ -0,0 +1,3 @@
1
+ module Whenever
2
+ VERSION = '0.6.2'
3
+ end unless defined?(Whenever::VERSION)
@@ -0,0 +1,322 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+
3
+ class CommandLineTest < Test::Unit::TestCase
4
+
5
+ context "A command line write" do
6
+ setup do
7
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
8
+ @command = Whenever::CommandLine.new(:write => true, :identifier => 'My identifier')
9
+ @task = "#{two_hours} /my/command"
10
+ Whenever.expects(:cron).returns(@task)
11
+ end
12
+
13
+ should "output the cron job with identifier blocks" do
14
+ output = <<-EXPECTED
15
+ # Begin Whenever generated tasks for: My identifier
16
+ #{@task}
17
+ # End Whenever generated tasks for: My identifier
18
+ EXPECTED
19
+
20
+ assert_equal output, @command.send(:whenever_cron)
21
+ end
22
+
23
+ should "write the crontab when run" do
24
+ @command.expects(:write_crontab).returns(true)
25
+ assert @command.run
26
+ end
27
+ end
28
+
29
+ context "A command line update" do
30
+ setup do
31
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
32
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
33
+ @task = "#{two_hours} /my/command"
34
+ Whenever.expects(:cron).returns(@task)
35
+ end
36
+
37
+ should "add the cron to the end of the file if there is no existing identifier block" do
38
+ existing = '# Existing crontab'
39
+ @command.expects(:read_crontab).at_least_once.returns(existing)
40
+
41
+ new_cron = <<-EXPECTED
42
+ #{existing}
43
+
44
+ # Begin Whenever generated tasks for: My identifier
45
+ #{@task}
46
+ # End Whenever generated tasks for: My identifier
47
+ EXPECTED
48
+
49
+ assert_equal new_cron, @command.send(:updated_crontab)
50
+
51
+ @command.expects(:write_crontab).with(new_cron).returns(true)
52
+ assert @command.run
53
+ end
54
+
55
+ should "replace an existing block if the identifier matches" do
56
+ existing = <<-EXISTING_CRON
57
+ # Something
58
+
59
+ # Begin Whenever generated tasks for: My identifier
60
+ My whenever job that was already here
61
+ # End Whenever generated tasks for: My identifier
62
+
63
+ # Begin Whenever generated tasks for: Other identifier
64
+ This shouldn't get replaced
65
+ # End Whenever generated tasks for: Other identifier
66
+ EXISTING_CRON
67
+
68
+ new_cron = <<-NEW_CRON
69
+ # Something
70
+
71
+ # Begin Whenever generated tasks for: My identifier
72
+ #{@task}
73
+ # End Whenever generated tasks for: My identifier
74
+
75
+ # Begin Whenever generated tasks for: Other identifier
76
+ This shouldn't get replaced
77
+ # End Whenever generated tasks for: Other identifier
78
+ NEW_CRON
79
+
80
+ @command.expects(:read_crontab).at_least_once.returns(existing)
81
+ assert_equal new_cron, @command.send(:updated_crontab)
82
+
83
+ @command.expects(:write_crontab).with(new_cron).returns(true)
84
+ assert @command.run
85
+ end
86
+ end
87
+
88
+ context "A command line update that contains backslashes" do
89
+ setup do
90
+ @existing = <<-EXISTING_CRON
91
+ # Begin Whenever generated tasks for: My identifier
92
+ script/runner -e production 'puts '\\''hello'\\'''
93
+ # End Whenever generated tasks for: My identifier
94
+ EXISTING_CRON
95
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
96
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
97
+ @command.expects(:read_crontab).at_least_once.returns(@existing)
98
+ @command.expects(:whenever_cron).returns(@existing)
99
+ end
100
+
101
+ should "replace the existing block with the backslashes in tact" do
102
+ assert_equal @existing, @command.send(:updated_crontab)
103
+ end
104
+ end
105
+
106
+ context "A command line update with an identifier similar to an existing one in the crontab already" do
107
+ setup do
108
+ @existing = <<-EXISTING_CRON
109
+ # Begin Whenever generated tasks for: WheneverExisting
110
+ # End Whenever generated tasks for: WheneverExisting
111
+ EXISTING_CRON
112
+ @new = <<-NEW_CRON
113
+ # Begin Whenever generated tasks for: Whenever
114
+ # End Whenever generated tasks for: Whenever
115
+ NEW_CRON
116
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
117
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'Whenever')
118
+ @command.expects(:read_crontab).at_least_once.returns(@existing)
119
+ @command.expects(:whenever_cron).returns(@new)
120
+ end
121
+
122
+ should "append the similarly named command" do
123
+ assert_equal @existing + "\n" + @new, @command.send(:updated_crontab)
124
+ end
125
+ end
126
+
127
+ context "A command line clear" do
128
+ setup do
129
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
130
+ @command = Whenever::CommandLine.new(:clear => true, :identifier => 'My identifier')
131
+ @task = "#{two_hours} /my/command"
132
+ end
133
+
134
+ should "clear an existing block if the identifier matches" do
135
+ existing = <<-EXISTING_CRON
136
+ # Something
137
+
138
+ # Begin Whenever generated tasks for: My identifier
139
+ My whenever job that was already here
140
+ # End Whenever generated tasks for: My identifier
141
+
142
+ # Begin Whenever generated tasks for: Other identifier
143
+ This shouldn't get replaced
144
+ # End Whenever generated tasks for: Other identifier
145
+ EXISTING_CRON
146
+
147
+ @command.expects(:read_crontab).at_least_once.returns(existing)
148
+
149
+ new_cron = <<-NEW_CRON
150
+ # Something
151
+
152
+ # Begin Whenever generated tasks for: Other identifier
153
+ This shouldn't get replaced
154
+ # End Whenever generated tasks for: Other identifier
155
+ NEW_CRON
156
+
157
+ assert_equal new_cron, @command.send(:updated_crontab)
158
+
159
+ @command.expects(:write_crontab).with(new_cron).returns(true)
160
+ assert @command.run
161
+ end
162
+ end
163
+
164
+ context "A command line update with no identifier" do
165
+ setup do
166
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
167
+ Whenever::CommandLine.any_instance.expects(:default_identifier).returns('DEFAULT')
168
+ @command = Whenever::CommandLine.new(:update => true, :file => @file)
169
+ end
170
+
171
+ should "use the default identifier" do
172
+ assert_equal "Whenever generated tasks for: DEFAULT", @command.send(:comment_base)
173
+ end
174
+ end
175
+
176
+ context "combined params" do
177
+ setup do
178
+ Whenever::CommandLine.any_instance.expects(:exit)
179
+ Whenever::CommandLine.any_instance.expects(:warn)
180
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
181
+ end
182
+
183
+ should "exit with write and clear" do
184
+ @command = Whenever::CommandLine.new(:write => true, :clear => true)
185
+ end
186
+
187
+ should "exit with write and update" do
188
+ @command = Whenever::CommandLine.new(:write => true, :update => true)
189
+ end
190
+
191
+ should "exit with update and clear" do
192
+ @command = Whenever::CommandLine.new(:update => true, :clear => true)
193
+ end
194
+ end
195
+
196
+ context "A runner where the environment is overridden using the :set option" do
197
+ setup do
198
+ @output = Whenever.cron :set => 'environment=serious', :string => \
199
+ <<-file
200
+ set :job_template, nil
201
+ set :environment, :silly
202
+ set :path, '/my/path'
203
+ every 2.hours do
204
+ runner "blahblah"
205
+ end
206
+ file
207
+ end
208
+
209
+ should "output the runner using the override environment" do
210
+ assert_match two_hours + %( cd /my/path && script/runner -e serious 'blahblah'), @output
211
+ end
212
+ end
213
+
214
+ context "A runner where the environment and path are overridden using the :set option" do
215
+ setup do
216
+ @output = Whenever.cron :set => 'environment=serious&path=/serious/path', :string => \
217
+ <<-file
218
+ set :job_template, nil
219
+ set :environment, :silly
220
+ set :path, '/silly/path'
221
+ every 2.hours do
222
+ runner "blahblah"
223
+ end
224
+ file
225
+ end
226
+
227
+ should "output the runner using the overridden path and environment" do
228
+ assert_match two_hours + %( cd /serious/path && script/runner -e serious 'blahblah'), @output
229
+ end
230
+ end
231
+
232
+ context "A runner where the environment and path are overridden using the :set option with spaces in the string" do
233
+ setup do
234
+ @output = Whenever.cron :set => ' environment = serious& path =/serious/path', :string => \
235
+ <<-file
236
+ set :job_template, nil
237
+ set :environment, :silly
238
+ set :path, '/silly/path'
239
+ every 2.hours do
240
+ runner "blahblah"
241
+ end
242
+ file
243
+ end
244
+
245
+ should "output the runner using the overridden path and environment" do
246
+ assert_match two_hours + %( cd /serious/path && script/runner -e serious 'blahblah'), @output
247
+ end
248
+ end
249
+
250
+ context "A runner where the environment is overridden using the :set option but no value is given" do
251
+ setup do
252
+ @output = Whenever.cron :set => ' environment=', :string => \
253
+ <<-file
254
+ set :job_template, nil
255
+ set :environment, :silly
256
+ set :path, '/silly/path'
257
+ every 2.hours do
258
+ runner "blahblah"
259
+ end
260
+ file
261
+ end
262
+
263
+ should "output the runner using the original environmnet" do
264
+ assert_match two_hours + %( cd /silly/path && script/runner -e silly 'blahblah'), @output
265
+ end
266
+ end
267
+
268
+ context "prepare-ing the output" do
269
+ setup do
270
+ File.expects(:exists?).with('config/schedule.rb').returns(true)
271
+ end
272
+
273
+ should "not trim off the top lines of the file" do
274
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier', :cut => 0)
275
+ existing = <<-EXISTING_CRON
276
+ # Useless Comments
277
+ # at the top of the file
278
+
279
+ # Begin Whenever generated tasks for: My identifier
280
+ My whenever job that was already here
281
+ # End Whenever generated tasks for: My identifier
282
+ EXISTING_CRON
283
+
284
+ assert_equal existing, @command.send(:prepare, existing)
285
+ end
286
+
287
+ should "trim off the top lines of the file" do
288
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier', :cut => '3')
289
+ existing = <<-EXISTING_CRON
290
+ # Useless Comments
291
+ # at the top of the file
292
+
293
+ # Begin Whenever generated tasks for: My identifier
294
+ My whenever job that was already here
295
+ # End Whenever generated tasks for: My identifier
296
+ EXISTING_CRON
297
+
298
+ new_cron = <<-NEW_CRON
299
+ # Begin Whenever generated tasks for: My identifier
300
+ My whenever job that was already here
301
+ # End Whenever generated tasks for: My identifier
302
+ NEW_CRON
303
+
304
+ assert_equal new_cron, @command.send(:prepare, existing)
305
+ end
306
+
307
+ should "preserve terminating newlines in files" do
308
+ @command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
309
+ existing = <<-EXISTING_CRON
310
+ # Begin Whenever generated tasks for: My identifier
311
+ My whenever job that was already here
312
+ # End Whenever generated tasks for: My identifier
313
+
314
+ # A non-Whenever task
315
+ My non-whenever job that was already here
316
+ EXISTING_CRON
317
+
318
+ assert_equal existing, @command.send(:prepare, existing)
319
+ end
320
+ end
321
+
322
+ end
@@ -0,0 +1,251 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+
3
+ class OutputAtTest < Test::Unit::TestCase
4
+
5
+ context "weekday at a (single) given time" do
6
+ setup do
7
+ @output = Whenever.cron \
8
+ <<-file
9
+ set :job_template, nil
10
+ every "weekday", :at => '5:02am' do
11
+ command "blahblah"
12
+ end
13
+ file
14
+ end
15
+
16
+ should "output the command using that time" do
17
+ assert_match '2 5 * * 1-5 blahblah', @output
18
+ end
19
+ end
20
+
21
+ context "weekday at a multiple diverse times, via an array" do
22
+ setup do
23
+ @output = Whenever.cron \
24
+ <<-file
25
+ set :job_template, nil
26
+ every "weekday", :at => %w(5:02am 3:52pm) do
27
+ command "blahblah"
28
+ end
29
+ file
30
+ end
31
+
32
+ should "output the commands for both times given" do
33
+ assert_match '2 5 * * 1-5 blahblah', @output
34
+ assert_match '52 15 * * 1-5 blahblah', @output
35
+ end
36
+ end
37
+
38
+ context "weekday at a multiple diverse times, comma separated" do
39
+ setup do
40
+ @output = Whenever.cron \
41
+ <<-file
42
+ set :job_template, nil
43
+ every "weekday", :at => '5:02am, 3:52pm' do
44
+ command "blahblah"
45
+ end
46
+ file
47
+ end
48
+
49
+ should "output the commands for both times given" do
50
+ assert_match '2 5 * * 1-5 blahblah', @output
51
+ assert_match '52 15 * * 1-5 blahblah', @output
52
+ end
53
+ end
54
+
55
+ context "weekday at a multiple aligned times" do
56
+ setup do
57
+ @output = Whenever.cron \
58
+ <<-file
59
+ set :job_template, nil
60
+ every "weekday", :at => '5:02am, 3:02pm' do
61
+ command "blahblah"
62
+ end
63
+ file
64
+ end
65
+
66
+ should "output the command using one entry because the times are aligned" do
67
+ assert_match '2 5,15 * * 1-5 blahblah', @output
68
+ end
69
+ end
70
+
71
+ context "various days at a various aligned times" do
72
+ setup do
73
+ @output = Whenever.cron \
74
+ <<-file
75
+ set :job_template, nil
76
+ every "mon,wed,fri", :at => '5:02am, 3:02pm' do
77
+ command "blahblah"
78
+ end
79
+ file
80
+ end
81
+
82
+ should "output the command using one entry because the times are aligned" do
83
+ assert_match '2 5,15 * * 1,3,5 blahblah', @output
84
+ end
85
+ end
86
+
87
+ context "various days at a various aligned times using a runner" do
88
+ setup do
89
+ @output = Whenever.cron \
90
+ <<-file
91
+ set :job_template, nil
92
+ set :path, '/your/path'
93
+ every "mon,wed,fri", :at => '5:02am, 3:02pm' do
94
+ runner "blahblah"
95
+ end
96
+ file
97
+ end
98
+
99
+ should "output the runner using one entry because the times are aligned" do
100
+ assert_match %(2 5,15 * * 1,3,5 cd /your/path && script/runner -e production 'blahblah'), @output
101
+ end
102
+ end
103
+
104
+ context "various days at a various aligned times using a rake task" do
105
+ setup do
106
+ @output = Whenever.cron \
107
+ <<-file
108
+ set :job_template, nil
109
+ set :path, '/your/path'
110
+ every "mon,wed,fri", :at => '5:02am, 3:02pm' do
111
+ rake "blah:blah"
112
+ end
113
+ file
114
+ end
115
+
116
+ should "output the rake task using one entry because the times are aligned" do
117
+ assert_match '2 5,15 * * 1,3,5 cd /your/path && RAILS_ENV=production rake blah:blah --silent', @output
118
+ end
119
+ end
120
+
121
+ context "A command every 1.month at very diverse times" do
122
+ setup do
123
+ @output = Whenever.cron \
124
+ <<-file
125
+ set :job_template, nil
126
+ every [1.month, 1.day], :at => 'january 5:02am, june 17th at 2:22pm, june 3rd at 3:33am' do
127
+ command "blahblah"
128
+ end
129
+ file
130
+ end
131
+
132
+ should "output 6 commands since none align" do
133
+ # The 1.month commands
134
+ assert_match '2 5 1 * * blahblah', @output
135
+ assert_match '22 14 17 * * blahblah', @output
136
+ assert_match '33 3 3 * * blahblah', @output
137
+
138
+ # The 1.day commands
139
+ assert_match '2 5 * * * blahblah', @output
140
+ assert_match '22 14 * * * blahblah', @output
141
+ assert_match '33 3 * * * blahblah', @output
142
+ end
143
+ end
144
+
145
+ context "Multiple commands output every :reboot" do
146
+ setup do
147
+ @output = Whenever.cron \
148
+ <<-file
149
+ set :job_template, nil
150
+ every :reboot do
151
+ command "command_1"
152
+ command "command_2"
153
+ end
154
+ file
155
+ end
156
+
157
+ should "output both commands @reboot" do
158
+ assert_match "@reboot command_1", @output
159
+ assert_match "@reboot command_2", @output
160
+ end
161
+ end
162
+
163
+ context "Many different job types output every :day" do
164
+ setup do
165
+ @output = Whenever.cron \
166
+ <<-file
167
+ set :job_template, nil
168
+ set :path, '/your/path'
169
+ every :day do
170
+ rake "blah:blah"
171
+ runner "runner_1"
172
+ command "command_1"
173
+ runner "runner_2"
174
+ command "command_2"
175
+ end
176
+ file
177
+ end
178
+
179
+ should "output all of the commands @daily" do
180
+ assert_match '@daily cd /your/path && RAILS_ENV=production rake blah:blah --silent', @output
181
+ assert_match %(@daily cd /your/path && script/runner -e production 'runner_1'), @output
182
+ assert_match '@daily command_1', @output
183
+ assert_match %(@daily cd /your/path && script/runner -e production 'runner_2'), @output
184
+ assert_match '@daily command_2', @output
185
+ end
186
+ end
187
+
188
+ context "every 5 minutes but but starting at 1" do
189
+ setup do
190
+ @output = Whenever.cron \
191
+ <<-file
192
+ set :job_template, nil
193
+ every 5.minutes, :at => 1 do
194
+ command "blahblah"
195
+ end
196
+ file
197
+ end
198
+
199
+ should "output the command using that time" do
200
+ assert_match '1,6,11,16,21,26,31,36,41,46,51,56 * * * * blahblah', @output
201
+ end
202
+ end
203
+
204
+ context "every 4 minutes but starting at 2" do
205
+ setup do
206
+ @output = Whenever.cron \
207
+ <<-file
208
+ set :job_template, nil
209
+ every 4.minutes, :at => 2 do
210
+ command "blahblah"
211
+ end
212
+ file
213
+ end
214
+
215
+ should "output the command using that time" do
216
+ assert_match '2,6,10,14,18,22,26,30,34,38,42,46,50,54,58 * * * * blahblah', @output
217
+ end
218
+ end
219
+
220
+ context "every 3 minutes but starting at 7" do
221
+ setup do
222
+ @output = Whenever.cron \
223
+ <<-file
224
+ set :job_template, nil
225
+ every 3.minutes, :at => 7 do
226
+ command "blahblah"
227
+ end
228
+ file
229
+ end
230
+
231
+ should "output the command using that time" do
232
+ assert_match '7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58 * * * * blahblah', @output
233
+ end
234
+ end
235
+
236
+ context "every 2 minutes but starting at 27" do
237
+ setup do
238
+ @output = Whenever.cron \
239
+ <<-file
240
+ set :job_template, nil
241
+ every 2.minutes, :at => 27 do
242
+ command "blahblah"
243
+ end
244
+ file
245
+ end
246
+
247
+ should "output the command using that time" do
248
+ assert_match '27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59 * * * * blahblah', @output
249
+ end
250
+ end
251
+ end