whenever 0.8.0 → 0.8.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/CHANGELOG.md +13 -0
- data/lib/whenever.rb +6 -6
- data/lib/whenever/capistrano/recipes.rb +29 -46
- data/lib/whenever/capistrano/support.rb +41 -0
- data/lib/whenever/command_line.rb +6 -5
- data/lib/whenever/cron.rb +1 -1
- data/lib/whenever/job.rb +2 -2
- data/lib/whenever/version.rb +1 -1
- data/test/functional/command_line_test.rb +26 -26
- data/test/functional/output_defined_job_test.rb +16 -16
- data/test/functional/output_jobs_for_roles_test.rb +84 -0
- data/test/unit/capistrano_support_test.rb +138 -0
- data/test/unit/cron_test.rb +1 -0
- data/test/unit/job_test.rb +4 -0
- data/whenever.gemspec +2 -8
- metadata +7 -18
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,19 @@
|
|
3
3
|
* Time zone support
|
4
4
|
|
5
5
|
|
6
|
+
### 0.8.1 / December 22nd, 2012
|
7
|
+
|
8
|
+
* Fix multiserver roles bug. [Wes Morgan]
|
9
|
+
|
10
|
+
* Refactor Cap recipes and add tests for them. [Wes Morgan]
|
11
|
+
|
12
|
+
* Fix file not found error when running under JRuby. [Wes Morgan]
|
13
|
+
|
14
|
+
* Stop interpolating template attributes with no corresponding value. [Vincent Boisard]
|
15
|
+
|
16
|
+
* Support for raw cron separated by tabs. [Étienne Barrié]
|
17
|
+
|
18
|
+
|
6
19
|
### 0.8.0 / November 8th, 2012
|
7
20
|
|
8
21
|
* Separate Capistrano recipes to allow custom execution. [Bogdan Gusiev]
|
data/lib/whenever.rb
CHANGED
@@ -2,19 +2,19 @@ require 'thread'
|
|
2
2
|
require 'active_support/all'
|
3
3
|
|
4
4
|
module Whenever
|
5
|
-
autoload :JobList,
|
6
|
-
autoload :Job,
|
7
|
-
autoload :CommandLine,
|
8
|
-
|
5
|
+
autoload :JobList, 'whenever/job_list'
|
6
|
+
autoload :Job, 'whenever/job'
|
7
|
+
autoload :CommandLine, 'whenever/command_line'
|
8
|
+
|
9
9
|
module Output
|
10
10
|
autoload :Cron, 'whenever/cron'
|
11
11
|
autoload :Redirection, 'whenever/output_redirection'
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def self.cron(options)
|
15
15
|
Whenever::JobList.new(options).generate_cron_output
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def self.path
|
19
19
|
Dir.pwd
|
20
20
|
end
|
@@ -1,4 +1,8 @@
|
|
1
|
+
require 'whenever/capistrano/support'
|
2
|
+
|
1
3
|
Capistrano::Configuration.instance(:must_exist).load do
|
4
|
+
Whenever::CapistranoSupport.load_into(self)
|
5
|
+
|
2
6
|
_cset(:whenever_roles) { :db }
|
3
7
|
_cset(:whenever_options) { {:roles => fetch(:whenever_roles)} }
|
4
8
|
_cset(:whenever_command) { "whenever" }
|
@@ -9,63 +13,42 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
9
13
|
_cset(:whenever_clear_flags) { "--clear-crontab #{fetch :whenever_identifier}" }
|
10
14
|
|
11
15
|
namespace :whenever do
|
12
|
-
desc
|
13
|
-
Update application's crontab entries using Whenever. You can configure \
|
14
|
-
the command used to invoke Whenever by setting the :whenever_command \
|
15
|
-
variable, which can be used with Bundler to set the command to \
|
16
|
-
"bundle exec whenever". You can configure the identifier used by setting \
|
17
|
-
the :whenever_identifier variable, which defaults to the same value configured \
|
18
|
-
for the :application variable. You can configure the environment by setting \
|
19
|
-
the :whenever_environment variable, which defaults to the same value \
|
20
|
-
configured for the :rails_env variable which itself defaults to "production". \
|
21
|
-
Finally, you can completely override all arguments to the Whenever command \
|
22
|
-
by setting the :whenever_update_flags variable. Additionally you can configure \
|
23
|
-
which servers the crontab is updated on by setting the :whenever_roles variable.
|
24
|
-
DESC
|
16
|
+
desc "Update application's crontab entries using Whenever"
|
25
17
|
task :update_crontab do
|
26
|
-
|
27
|
-
|
18
|
+
args = {
|
19
|
+
:command => fetch(:whenever_command),
|
20
|
+
:flags => fetch(:whenever_update_flags),
|
21
|
+
:path => fetch(:release_path)
|
22
|
+
}
|
28
23
|
|
29
|
-
if
|
30
|
-
|
31
|
-
roles << :__none if roles.empty?
|
24
|
+
if whenever_servers.any?
|
25
|
+
whenever_run_commands(args)
|
32
26
|
|
33
|
-
|
34
|
-
if
|
35
|
-
|
27
|
+
on_rollback do
|
28
|
+
if fetch(:previous_release)
|
29
|
+
# rollback to the previous release's crontab
|
30
|
+
args[:path] = fetch(:previous_release)
|
36
31
|
else
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
on_rollback do
|
42
|
-
if fetch :previous_release
|
43
|
-
run "cd #{fetch :previous_release} && #{fetch :whenever_command} #{fetch :whenever_update_flags}#{role_arg}", options
|
44
|
-
else
|
45
|
-
run "cd #{fetch :release_path} && #{fetch :whenever_command} #{fetch :whenever_clear_flags}", options
|
46
|
-
end
|
32
|
+
# clear the crontab if no previous release
|
33
|
+
args[:flags] = fetch(:whenever_clear_flags)
|
47
34
|
end
|
48
35
|
|
49
|
-
|
36
|
+
whenever_run_commands(args)
|
50
37
|
end
|
51
38
|
end
|
52
39
|
end
|
53
40
|
|
54
|
-
desc
|
55
|
-
Clear application's crontab entries using Whenever. You can configure \
|
56
|
-
the command used to invoke Whenever by setting the :whenever_command \
|
57
|
-
variable, which can be used with Bundler to set the command to \
|
58
|
-
"bundle exec whenever". You can configure the identifier used by setting \
|
59
|
-
the :whenever_identifier variable, which defaults to the same value configured \
|
60
|
-
for the :application variable. Finally, you can completely override all \
|
61
|
-
arguments to the Whenever command by setting the :whenever_clear_flags variable. \
|
62
|
-
Additionally you can configure which servers the crontab is cleared on by setting \
|
63
|
-
the :whenever_roles variable.
|
64
|
-
DESC
|
65
|
-
|
41
|
+
desc "Clear application's crontab entries using Whenever"
|
66
42
|
task :clear_crontab do
|
67
|
-
|
68
|
-
|
43
|
+
if whenever_servers.any?
|
44
|
+
args = {
|
45
|
+
:command => fetch(:whenever_command),
|
46
|
+
:flags => fetch(:whenever_clear_flags),
|
47
|
+
:path => fetch(:latest_release)
|
48
|
+
}
|
49
|
+
|
50
|
+
whenever_run_commands(args)
|
51
|
+
end
|
69
52
|
end
|
70
53
|
end
|
71
54
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Whenever
|
2
|
+
module CapistranoSupport
|
3
|
+
def self.load_into(capistrano_configuration)
|
4
|
+
capistrano_configuration.load do
|
5
|
+
|
6
|
+
def whenever_options
|
7
|
+
fetch(:whenever_options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def whenever_roles
|
11
|
+
Array(whenever_options[:roles])
|
12
|
+
end
|
13
|
+
|
14
|
+
def whenever_servers
|
15
|
+
find_servers(whenever_options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def whenever_server_roles
|
19
|
+
whenever_servers.inject({}) do |map, server|
|
20
|
+
map[server] = role_names_for_host(server) & whenever_roles
|
21
|
+
map
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def whenever_run_commands(args)
|
26
|
+
unless [:command, :path, :flags].all? { |a| args.include?(a) }
|
27
|
+
raise ArgumentError, ":command, :path, & :flags are required"
|
28
|
+
end
|
29
|
+
|
30
|
+
whenever_server_roles.each do |server, roles|
|
31
|
+
roles_arg = roles.empty? ? "" : " --roles #{roles.join(',')}"
|
32
|
+
|
33
|
+
command = "cd #{args[:path]} && #{args[:command]} #{args[:flags]}#{roles_arg}"
|
34
|
+
run command, whenever_options.merge(:hosts => server.host)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -66,22 +66,23 @@ module Whenever
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def write_crontab(contents)
|
69
|
-
tmp_cron_file = Tempfile.
|
70
|
-
|
71
|
-
|
72
|
-
end
|
69
|
+
tmp_cron_file = Tempfile.open('whenever_tmp_cron')
|
70
|
+
tmp_cron_file << contents
|
71
|
+
tmp_cron_file.fsync
|
73
72
|
|
74
73
|
command = ['crontab']
|
75
74
|
command << "-u #{@options[:user]}" if @options[:user]
|
76
|
-
command << tmp_cron_file
|
75
|
+
command << tmp_cron_file.path
|
77
76
|
|
78
77
|
if system(command.join(' '))
|
79
78
|
action = 'written' if @options[:write]
|
80
79
|
action = 'updated' if @options[:update]
|
81
80
|
puts "[write] crontab file #{action}"
|
81
|
+
tmp_cron_file.close!
|
82
82
|
exit(0)
|
83
83
|
else
|
84
84
|
warn "[fail] Couldn't write crontab; try running `whenever' with no options to ensure your schedule file is valid."
|
85
|
+
tmp_cron_file.close!
|
85
86
|
exit(1)
|
86
87
|
end
|
87
88
|
end
|
data/lib/whenever/cron.rb
CHANGED
@@ -4,7 +4,7 @@ module Whenever
|
|
4
4
|
module Output
|
5
5
|
class Cron
|
6
6
|
KEYWORDS = [:reboot, :yearly, :annually, :monthly, :weekly, :daily, :midnight, :hourly]
|
7
|
-
REGEX = /^(@(#{KEYWORDS.join '|'})
|
7
|
+
REGEX = /^(@(#{KEYWORDS.join '|'})|.+\s+.+\s+.+\s+.+\s+.+.?)$/
|
8
8
|
|
9
9
|
attr_accessor :time, :task
|
10
10
|
|
data/lib/whenever/job.rb
CHANGED
@@ -10,7 +10,7 @@ module Whenever
|
|
10
10
|
@template = options.delete(:template)
|
11
11
|
@job_template = options.delete(:job_template) || ":job"
|
12
12
|
@roles = Array.wrap(options.delete(:roles))
|
13
|
-
@options[:output] = Whenever::Output::Redirection.new(options[:output]).to_s
|
13
|
+
@options[:output] = options.has_key?(:output) ? Whenever::Output::Redirection.new(options[:output]).to_s : ''
|
14
14
|
@options[:environment] ||= :production
|
15
15
|
@options[:path] = Shellwords.shellescape(@options[:path] || Whenever.path)
|
16
16
|
end
|
@@ -33,7 +33,7 @@ module Whenever
|
|
33
33
|
def process_template(template, options)
|
34
34
|
template.gsub(/:\w+/) do |key|
|
35
35
|
before_and_after = [$`[-1..-1], $'[0..0]]
|
36
|
-
option = options[key.sub(':', '').to_sym]
|
36
|
+
option = options[key.sub(':', '').to_sym] || key
|
37
37
|
|
38
38
|
if before_and_after.all? { |c| c == "'" }
|
39
39
|
escape_single_quotes(option)
|
data/lib/whenever/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
|
2
2
|
|
3
3
|
class CommandLineTest < Test::Unit::TestCase
|
4
|
-
|
4
|
+
|
5
5
|
context "A command line write" do
|
6
6
|
setup do
|
7
7
|
File.expects(:exists?).with('config/schedule.rb').returns(true)
|
@@ -16,16 +16,16 @@ class CommandLineTest < Test::Unit::TestCase
|
|
16
16
|
#{@task}
|
17
17
|
# End Whenever generated tasks for: My identifier
|
18
18
|
EXPECTED
|
19
|
-
|
19
|
+
|
20
20
|
assert_equal output, @command.send(:whenever_cron)
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
should "write the crontab when run" do
|
24
24
|
@command.expects(:write_crontab).returns(true)
|
25
25
|
assert @command.run
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
context "A command line update" do
|
30
30
|
setup do
|
31
31
|
File.expects(:exists?).with('config/schedule.rb').returns(true)
|
@@ -37,7 +37,7 @@ EXPECTED
|
|
37
37
|
should "add the cron to the end of the file if there is no existing identifier block" do
|
38
38
|
existing = '# Existing crontab'
|
39
39
|
@command.expects(:read_crontab).at_least_once.returns(existing)
|
40
|
-
|
40
|
+
|
41
41
|
new_cron = <<-EXPECTED
|
42
42
|
#{existing}
|
43
43
|
|
@@ -45,13 +45,13 @@ EXPECTED
|
|
45
45
|
#{@task}
|
46
46
|
# End Whenever generated tasks for: My identifier
|
47
47
|
EXPECTED
|
48
|
-
|
48
|
+
|
49
49
|
assert_equal new_cron, @command.send(:updated_crontab)
|
50
|
-
|
50
|
+
|
51
51
|
@command.expects(:write_crontab).with(new_cron).returns(true)
|
52
52
|
assert @command.run
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
should "replace an existing block if the identifier matches" do
|
56
56
|
existing = <<-EXISTING_CRON
|
57
57
|
# Something
|
@@ -76,15 +76,15 @@ EXISTING_CRON
|
|
76
76
|
This shouldn't get replaced
|
77
77
|
# End Whenever generated tasks for: Other identifier
|
78
78
|
NEW_CRON
|
79
|
-
|
79
|
+
|
80
80
|
@command.expects(:read_crontab).at_least_once.returns(existing)
|
81
81
|
assert_equal new_cron, @command.send(:updated_crontab)
|
82
|
-
|
82
|
+
|
83
83
|
@command.expects(:write_crontab).with(new_cron).returns(true)
|
84
84
|
assert @command.run
|
85
85
|
end
|
86
86
|
end
|
87
|
-
|
87
|
+
|
88
88
|
context "A command line update that contains backslashes" do
|
89
89
|
setup do
|
90
90
|
@existing = <<-EXISTING_CRON
|
@@ -97,12 +97,12 @@ EXISTING_CRON
|
|
97
97
|
@command.expects(:read_crontab).at_least_once.returns(@existing)
|
98
98
|
@command.expects(:whenever_cron).returns(@existing)
|
99
99
|
end
|
100
|
-
|
100
|
+
|
101
101
|
should "replace the existing block with the backslashes in tact" do
|
102
102
|
assert_equal @existing, @command.send(:updated_crontab)
|
103
103
|
end
|
104
104
|
end
|
105
|
-
|
105
|
+
|
106
106
|
context "A command line update with an identifier similar to an existing one in the crontab already" do
|
107
107
|
setup do
|
108
108
|
@existing = <<-EXISTING_CRON
|
@@ -118,7 +118,7 @@ NEW_CRON
|
|
118
118
|
@command.expects(:read_crontab).at_least_once.returns(@existing)
|
119
119
|
@command.expects(:whenever_cron).returns(@new)
|
120
120
|
end
|
121
|
-
|
121
|
+
|
122
122
|
should "append the similarly named command" do
|
123
123
|
assert_equal @existing + "\n" + @new, @command.send(:updated_crontab)
|
124
124
|
end
|
@@ -160,7 +160,7 @@ NEW_CRON
|
|
160
160
|
assert @command.run
|
161
161
|
end
|
162
162
|
end
|
163
|
-
|
163
|
+
|
164
164
|
context "A command line update with no identifier" do
|
165
165
|
setup do
|
166
166
|
File.expects(:exists?).with('config/schedule.rb').returns(true)
|
@@ -183,7 +183,7 @@ NEW_CRON
|
|
183
183
|
should "exit with write and clear" do
|
184
184
|
@command = Whenever::CommandLine.new(:write => true, :clear => true)
|
185
185
|
end
|
186
|
-
|
186
|
+
|
187
187
|
should "exit with write and update" do
|
188
188
|
@command = Whenever::CommandLine.new(:write => true, :update => true)
|
189
189
|
end
|
@@ -192,7 +192,7 @@ NEW_CRON
|
|
192
192
|
@command = Whenever::CommandLine.new(:update => true, :clear => true)
|
193
193
|
end
|
194
194
|
end
|
195
|
-
|
195
|
+
|
196
196
|
context "A runner where the environment is overridden using the :set option" do
|
197
197
|
setup do
|
198
198
|
@output = Whenever.cron :set => 'environment=serious', :string => \
|
@@ -205,12 +205,12 @@ NEW_CRON
|
|
205
205
|
end
|
206
206
|
file
|
207
207
|
end
|
208
|
-
|
208
|
+
|
209
209
|
should "output the runner using the override environment" do
|
210
210
|
assert_match two_hours + %( cd /my/path && script/runner -e serious 'blahblah'), @output
|
211
211
|
end
|
212
212
|
end
|
213
|
-
|
213
|
+
|
214
214
|
context "A runner where the environment and path are overridden using the :set option" do
|
215
215
|
setup do
|
216
216
|
@output = Whenever.cron :set => 'environment=serious&path=/serious/path', :string => \
|
@@ -223,12 +223,12 @@ NEW_CRON
|
|
223
223
|
end
|
224
224
|
file
|
225
225
|
end
|
226
|
-
|
226
|
+
|
227
227
|
should "output the runner using the overridden path and environment" do
|
228
228
|
assert_match two_hours + %( cd /serious/path && script/runner -e serious 'blahblah'), @output
|
229
229
|
end
|
230
230
|
end
|
231
|
-
|
231
|
+
|
232
232
|
context "A runner where the environment and path are overridden using the :set option with spaces in the string" do
|
233
233
|
setup do
|
234
234
|
@output = Whenever.cron :set => ' environment = serious& path =/serious/path', :string => \
|
@@ -241,12 +241,12 @@ NEW_CRON
|
|
241
241
|
end
|
242
242
|
file
|
243
243
|
end
|
244
|
-
|
244
|
+
|
245
245
|
should "output the runner using the overridden path and environment" do
|
246
246
|
assert_match two_hours + %( cd /serious/path && script/runner -e serious 'blahblah'), @output
|
247
247
|
end
|
248
248
|
end
|
249
|
-
|
249
|
+
|
250
250
|
context "A runner where the environment is overridden using the :set option but no value is given" do
|
251
251
|
setup do
|
252
252
|
@output = Whenever.cron :set => ' environment=', :string => \
|
@@ -259,7 +259,7 @@ NEW_CRON
|
|
259
259
|
end
|
260
260
|
file
|
261
261
|
end
|
262
|
-
|
262
|
+
|
263
263
|
should "output the runner using the original environmnet" do
|
264
264
|
assert_match two_hours + %( cd /silly/path && script/runner -e silly 'blahblah'), @output
|
265
265
|
end
|
@@ -283,7 +283,7 @@ EXISTING_CRON
|
|
283
283
|
|
284
284
|
assert_equal existing, @command.send(:prepare, existing)
|
285
285
|
end
|
286
|
-
|
286
|
+
|
287
287
|
should "trim off the top lines of the file" do
|
288
288
|
@command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier', :cut => '3')
|
289
289
|
existing = <<-EXISTING_CRON
|
@@ -303,7 +303,7 @@ NEW_CRON
|
|
303
303
|
|
304
304
|
assert_equal new_cron, @command.send(:prepare, existing)
|
305
305
|
end
|
306
|
-
|
306
|
+
|
307
307
|
should "preserve terminating newlines in files" do
|
308
308
|
@command = Whenever::CommandLine.new(:update => true, :identifier => 'My identifier')
|
309
309
|
existing = <<-EXISTING_CRON
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
|
2
2
|
|
3
3
|
class OutputDefinedJobTest < Test::Unit::TestCase
|
4
|
-
|
4
|
+
|
5
5
|
context "A defined job with a :task" do
|
6
6
|
setup do
|
7
7
|
@output = Whenever.cron \
|
@@ -13,12 +13,12 @@ class OutputDefinedJobTest < Test::Unit::TestCase
|
|
13
13
|
end
|
14
14
|
file
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
should "output the defined job with the task" do
|
18
18
|
assert_match /^.+ .+ .+ .+ before during after$/, @output
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
context "A defined job with a :task and some options" do
|
23
23
|
setup do
|
24
24
|
@output = Whenever.cron \
|
@@ -30,12 +30,12 @@ class OutputDefinedJobTest < Test::Unit::TestCase
|
|
30
30
|
end
|
31
31
|
file
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
should "output the defined job with the task and options" do
|
35
35
|
assert_match /^.+ .+ .+ .+ before during after happy birthday$/, @output
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
context "A defined job with a :task and an option where the option is set globally" do
|
40
40
|
setup do
|
41
41
|
@output = Whenever.cron \
|
@@ -48,12 +48,12 @@ class OutputDefinedJobTest < Test::Unit::TestCase
|
|
48
48
|
end
|
49
49
|
file
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
should "output the defined job with the task and options" do
|
53
53
|
assert_match /^.+ .+ .+ .+ before during after happy$/, @output
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
context "A defined job with a :task and an option where the option is set globally and locally" do
|
58
58
|
setup do
|
59
59
|
@output = Whenever.cron \
|
@@ -66,12 +66,12 @@ class OutputDefinedJobTest < Test::Unit::TestCase
|
|
66
66
|
end
|
67
67
|
file
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
should "output the defined job using the local option" do
|
71
71
|
assert_match /^.+ .+ .+ .+ before during after local$/, @output
|
72
72
|
end
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
context "A defined job with a :task and an option that is not set" do
|
76
76
|
setup do
|
77
77
|
@output = Whenever.cron \
|
@@ -83,16 +83,16 @@ class OutputDefinedJobTest < Test::Unit::TestCase
|
|
83
83
|
end
|
84
84
|
file
|
85
85
|
end
|
86
|
-
|
87
|
-
should "output the defined job with that option
|
88
|
-
assert_match /^.+ .+ .+ .+ before during after$/, @output
|
86
|
+
|
87
|
+
should "output the defined job with that option left untouched" do
|
88
|
+
assert_match /^.+ .+ .+ .+ before during after :option1$/, @output
|
89
89
|
end
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
context "A defined job that uses a :path where none is explicitly set" do
|
93
93
|
setup do
|
94
94
|
Whenever.stubs(:path).returns('/my/path')
|
95
|
-
|
95
|
+
|
96
96
|
@output = Whenever.cron \
|
97
97
|
<<-file
|
98
98
|
set :job_template, nil
|
@@ -102,10 +102,10 @@ class OutputDefinedJobTest < Test::Unit::TestCase
|
|
102
102
|
end
|
103
103
|
file
|
104
104
|
end
|
105
|
-
|
105
|
+
|
106
106
|
should "default to using the Whenever.path" do
|
107
107
|
assert_match two_hours + %( cd /my/path && blahblah), @output
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
|
-
end
|
111
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
|
2
|
+
|
3
|
+
class OutputJobsForRolesTest < Test::Unit::TestCase
|
4
|
+
context "with one role requested and specified on the job" do
|
5
|
+
setup do
|
6
|
+
@output = Whenever.cron :roles => [:role1], :string => \
|
7
|
+
<<-file
|
8
|
+
every 2.hours, :roles => [:role1] do
|
9
|
+
command "blahblah"
|
10
|
+
end
|
11
|
+
file
|
12
|
+
end
|
13
|
+
|
14
|
+
should "output the cron job" do
|
15
|
+
assert_equal two_hours + " /bin/bash -l -c 'blahblah'\n\n", @output
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with one role requested but none specified on the job" do
|
20
|
+
setup do
|
21
|
+
@output = Whenever.cron :roles => [:role1], :string => \
|
22
|
+
<<-file
|
23
|
+
every 2.hours do
|
24
|
+
command "blahblah"
|
25
|
+
end
|
26
|
+
file
|
27
|
+
end
|
28
|
+
|
29
|
+
# this should output the job because not specifying a role means "all roles"
|
30
|
+
should "output the cron job" do
|
31
|
+
assert_equal two_hours + " /bin/bash -l -c 'blahblah'\n\n", @output
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with no roles requested but one specified on the job" do
|
36
|
+
setup do
|
37
|
+
@output = Whenever.cron \
|
38
|
+
<<-file
|
39
|
+
every 2.hours, :roles => [:role1] do
|
40
|
+
command "blahblah"
|
41
|
+
end
|
42
|
+
file
|
43
|
+
end
|
44
|
+
|
45
|
+
# this should output the job because not requesting roles means "all roles"
|
46
|
+
should "output the cron job" do
|
47
|
+
assert_equal two_hours + " /bin/bash -l -c 'blahblah'\n\n", @output
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "with a different role requested than the one specified on the job" do
|
52
|
+
setup do
|
53
|
+
@output = Whenever.cron :roles => [:role1], :string => \
|
54
|
+
<<-file
|
55
|
+
every 2.hours, :roles => [:role2] do
|
56
|
+
command "blahblah"
|
57
|
+
end
|
58
|
+
file
|
59
|
+
end
|
60
|
+
|
61
|
+
should "not output the cron job" do
|
62
|
+
assert_equal "", @output
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with 2 roles requested and a job defined for each" do
|
67
|
+
setup do
|
68
|
+
@output = Whenever.cron :roles => [:role1, :role2], :string => \
|
69
|
+
<<-file
|
70
|
+
every 2.hours, :roles => [:role1] do
|
71
|
+
command "role1_cmd"
|
72
|
+
end
|
73
|
+
|
74
|
+
every :hour, :roles => [:role2] do
|
75
|
+
command "role2_cmd"
|
76
|
+
end
|
77
|
+
file
|
78
|
+
end
|
79
|
+
|
80
|
+
should "output both jobs" do
|
81
|
+
assert_equal two_hours + " /bin/bash -l -c 'role1_cmd'\n\n0 * * * * /bin/bash -l -c 'role2_cmd'\n\n", @output
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/../../lib/whenever/capistrano/support")
|
3
|
+
|
4
|
+
class CapistranoSupportTestSubject
|
5
|
+
include Whenever::CapistranoSupport
|
6
|
+
end
|
7
|
+
|
8
|
+
class CapistranoSupportTest < Test::Unit::TestCase
|
9
|
+
context "when using capistrano support module" do
|
10
|
+
setup do
|
11
|
+
@capistrano = CapistranoSupportTestSubject.new
|
12
|
+
configuration = mock
|
13
|
+
configuration.stubs(:load).yields(@capistrano)
|
14
|
+
Whenever::CapistranoSupport.load_into(configuration)
|
15
|
+
end
|
16
|
+
|
17
|
+
context "#whenever_options" do
|
18
|
+
should "return fetch(:whenever_options)" do
|
19
|
+
@capistrano.expects(:fetch).with(:whenever_options)
|
20
|
+
@capistrano.whenever_options
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "#whenever_roles with one role" do
|
25
|
+
setup do
|
26
|
+
@capistrano.stubs(:whenever_options).returns({:roles => :role1})
|
27
|
+
end
|
28
|
+
|
29
|
+
should "return whenever_options[:roles] as an array" do
|
30
|
+
assert_equal [:role1], @capistrano.whenever_roles
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "#whenever_roles with no defined roles" do
|
35
|
+
setup do
|
36
|
+
@capistrano.stubs(:whenever_options).returns({})
|
37
|
+
end
|
38
|
+
|
39
|
+
should "return an empty array" do
|
40
|
+
assert_equal [], @capistrano.whenever_roles
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "#whenever_servers" do
|
45
|
+
should "return the list of servers returned by find_servers" do
|
46
|
+
@capistrano.stubs(:whenever_options).returns({})
|
47
|
+
@capistrano.stubs(:find_servers).returns([:server1, :server2])
|
48
|
+
|
49
|
+
assert_equal [:server1, :server2], @capistrano.whenever_servers
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "#whenever_server_roles" do
|
54
|
+
setup do
|
55
|
+
@mock_servers = ["foo", "bar"]
|
56
|
+
@capistrano.stubs(:whenever_servers).returns(@mock_servers)
|
57
|
+
end
|
58
|
+
|
59
|
+
should "return a map of servers to their role(s)" do
|
60
|
+
@capistrano.stubs(:whenever_roles).returns([:role1, :role2])
|
61
|
+
@capistrano.stubs(:role_names_for_host).with("foo").returns([:role1])
|
62
|
+
@capistrano.stubs(:role_names_for_host).with("bar").returns([:role2])
|
63
|
+
assert_equal({"foo" => [:role1], "bar" => [:role2]}, @capistrano.whenever_server_roles)
|
64
|
+
end
|
65
|
+
|
66
|
+
should "exclude non-requested roles" do
|
67
|
+
@capistrano.stubs(:whenever_roles).returns([:role1, :role2])
|
68
|
+
@capistrano.stubs(:role_names_for_host).with("foo").returns([:role1, :role3])
|
69
|
+
@capistrano.stubs(:role_names_for_host).with("bar").returns([:role2])
|
70
|
+
assert_equal({"foo" => [:role1], "bar" => [:role2]}, @capistrano.whenever_server_roles)
|
71
|
+
end
|
72
|
+
|
73
|
+
should "include all roles for servers w/ >1 when they're requested" do
|
74
|
+
@capistrano.stubs(:whenever_roles).returns([:role1, :role2, :role3])
|
75
|
+
@capistrano.stubs(:role_names_for_host).with("foo").returns([:role1, :role3])
|
76
|
+
@capistrano.stubs(:role_names_for_host).with("bar").returns([:role2])
|
77
|
+
assert_equal({"foo" => [:role1, :role3], "bar" => [:role2]}, @capistrano.whenever_server_roles)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "#whenever_run_commands" do
|
82
|
+
should "require :command arg" do
|
83
|
+
assert_raise ArgumentError do
|
84
|
+
@capistrano.whenever_run_commands(:options => {}, :path => {}, :flags => {})
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
should "require :path arg" do
|
89
|
+
assert_raise ArgumentError do
|
90
|
+
@capistrano.whenever_run_commands(:options => {}, :command => {}, :flags => {})
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
should "require :flags arg" do
|
95
|
+
assert_raise ArgumentError do
|
96
|
+
@capistrano.whenever_run_commands(:options => {}, :path => {}, :command => {})
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "with some servers defined" do
|
101
|
+
setup do
|
102
|
+
@mock_server1, @mock_server2 = mock(), mock()
|
103
|
+
@mock_server1.stubs(:host).returns("server1.foo.com")
|
104
|
+
@mock_server2.stubs(:host).returns("server2.foo.com")
|
105
|
+
@mock_servers = [@mock_server1, @mock_server2]
|
106
|
+
end
|
107
|
+
|
108
|
+
should "call run for each host w/ appropriate role args" do
|
109
|
+
@capistrano.stubs(:role_names_for_host).with(@mock_server1).returns([:role1])
|
110
|
+
@capistrano.stubs(:role_names_for_host).with(@mock_server2).returns([:role2])
|
111
|
+
@capistrano.stubs(:whenever_servers).returns(@mock_servers)
|
112
|
+
roles = [:role1, :role2]
|
113
|
+
@capistrano.stubs(:whenever_options).returns({:roles => roles})
|
114
|
+
|
115
|
+
@capistrano.expects(:run).once.with('cd /foo/bar && whenever --flag1 --flag2 --roles role1', {:roles => [:role1, :role2], :hosts => 'server1.foo.com'})
|
116
|
+
@capistrano.expects(:run).once.with('cd /foo/bar && whenever --flag1 --flag2 --roles role2', {:roles => [:role1, :role2], :hosts => 'server2.foo.com'})
|
117
|
+
|
118
|
+
@capistrano.whenever_run_commands(:command => "whenever",
|
119
|
+
:path => "/foo/bar",
|
120
|
+
:flags => "--flag1 --flag2")
|
121
|
+
end
|
122
|
+
|
123
|
+
should "call run w/ all role args for servers w/ >1 role" do
|
124
|
+
@capistrano.stubs(:role_names_for_host).with(@mock_server1).returns([:role1, :role3])
|
125
|
+
@capistrano.stubs(:whenever_servers).returns([@mock_servers.first])
|
126
|
+
roles = [:role1, :role2, :role3]
|
127
|
+
@capistrano.stubs(:whenever_options).returns({:roles => roles})
|
128
|
+
|
129
|
+
@capistrano.expects(:run).once.with('cd /foo/bar && whenever --flag1 --flag2 --roles role1,role3', {:roles => [:role1, :role2, :role3], :hosts => 'server1.foo.com'})
|
130
|
+
|
131
|
+
@capistrano.whenever_run_commands(:command => "whenever",
|
132
|
+
:path => "/foo/bar",
|
133
|
+
:flags => "--flag1 --flag2")
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
data/test/unit/cron_test.rb
CHANGED
@@ -218,6 +218,7 @@ class CronTest < Test::Unit::TestCase
|
|
218
218
|
context "When given raw cron sytax" do
|
219
219
|
should "return the same cron sytax" do
|
220
220
|
crons = ['0 0 27-31 * *', '* * * * *', '2/3 1,9,22 11-26 1-6 *',
|
221
|
+
"*\t*\t*\t*\t*",
|
221
222
|
'@reboot', '@yearly', '@annually', '@monthly', '@weekly',
|
222
223
|
'@daily', '@midnight', '@hourly']
|
223
224
|
crons.each do |cron|
|
data/test/unit/job_test.rb
CHANGED
@@ -30,6 +30,10 @@ class JobTest < Test::Unit::TestCase
|
|
30
30
|
assert_equal '/my/path', new_job(:template => ':path').output
|
31
31
|
end
|
32
32
|
|
33
|
+
should "not substitute parameters for which no value is set" do
|
34
|
+
assert_equal 'Hello :world', new_job(:template => ':matching :world', :matching => 'Hello').output
|
35
|
+
end
|
36
|
+
|
33
37
|
should "escape the :path" do
|
34
38
|
assert_equal '/my/spacey\ path', new_job(:template => ':path', :path => '/my/spacey path').output
|
35
39
|
end
|
data/whenever.gemspec
CHANGED
@@ -15,17 +15,11 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.test_files = `git ls-files -- test/{functional,unit}/*`.split("\n")
|
16
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
17
|
s.require_paths = ["lib"]
|
18
|
-
|
18
|
+
|
19
19
|
s.add_dependency "chronic", ">= 0.6.3"
|
20
20
|
s.add_dependency "activesupport", ">= 2.3.4"
|
21
|
-
|
21
|
+
|
22
22
|
s.add_development_dependency "shoulda", ">= 2.1.1"
|
23
23
|
s.add_development_dependency "mocha", ">= 0.9.5"
|
24
24
|
s.add_development_dependency "rake"
|
25
|
-
|
26
|
-
# I'm not sure why this isn't installed along with activesupport,
|
27
|
-
# but for whatever reason running `bundle install` doesn't install
|
28
|
-
# i18n so I'm adding it here for now.
|
29
|
-
# https://github.com/rails/rails/blob/master/activesupport/activesupport.gemspec#L19 ?
|
30
|
-
s.add_development_dependency "i18n"
|
31
25
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: whenever
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: chronic
|
@@ -91,22 +91,6 @@ dependencies:
|
|
91
91
|
- - ! '>='
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: '0'
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
name: i18n
|
96
|
-
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
|
-
requirements:
|
99
|
-
- - ! '>='
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
version: '0'
|
102
|
-
type: :development
|
103
|
-
prerelease: false
|
104
|
-
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ! '>='
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '0'
|
110
94
|
description: Clean ruby syntax for writing and deploying cron jobs.
|
111
95
|
email:
|
112
96
|
- javan@javan.us
|
@@ -128,6 +112,7 @@ files:
|
|
128
112
|
- lib/whenever.rb
|
129
113
|
- lib/whenever/capistrano.rb
|
130
114
|
- lib/whenever/capistrano/recipes.rb
|
115
|
+
- lib/whenever/capistrano/support.rb
|
131
116
|
- lib/whenever/command_line.rb
|
132
117
|
- lib/whenever/cron.rb
|
133
118
|
- lib/whenever/job.rb
|
@@ -140,8 +125,10 @@ files:
|
|
140
125
|
- test/functional/output_default_defined_jobs_test.rb
|
141
126
|
- test/functional/output_defined_job_test.rb
|
142
127
|
- test/functional/output_env_test.rb
|
128
|
+
- test/functional/output_jobs_for_roles_test.rb
|
143
129
|
- test/functional/output_redirection_test.rb
|
144
130
|
- test/test_helper.rb
|
131
|
+
- test/unit/capistrano_support_test.rb
|
145
132
|
- test/unit/cron_test.rb
|
146
133
|
- test/unit/job_test.rb
|
147
134
|
- whenever.gemspec
|
@@ -175,6 +162,8 @@ test_files:
|
|
175
162
|
- test/functional/output_default_defined_jobs_test.rb
|
176
163
|
- test/functional/output_defined_job_test.rb
|
177
164
|
- test/functional/output_env_test.rb
|
165
|
+
- test/functional/output_jobs_for_roles_test.rb
|
178
166
|
- test/functional/output_redirection_test.rb
|
167
|
+
- test/unit/capistrano_support_test.rb
|
179
168
|
- test/unit/cron_test.rb
|
180
169
|
- test/unit/job_test.rb
|