crontabinator 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
@@ -1,2 +1,6 @@
|
|
1
1
|
set :crontab_log_level, "info"
|
2
|
+
set :crontab_logs_path, -> { shared_path.join('log') }
|
2
3
|
set :crontab_templates_path, "templates/crontab"
|
4
|
+
set :crontab_lockfile_path, -> { "#{fetch(:crontab_templates_path)}/crontab.lock" }
|
5
|
+
set :crontab_scripts_path, -> { "#{fetch(:crontab_templates_path)}/scripts.d" }
|
6
|
+
set :crontab_server_scripts_path, -> { current_path.join('script') }
|
data/lib/crontabinator/check.rb
CHANGED
@@ -1,8 +1,37 @@
|
|
1
1
|
namespace :crontab do
|
2
2
|
namespace :check do
|
3
3
|
|
4
|
+
task :scripts do
|
5
|
+
run_locally do
|
6
|
+
files = Dir.glob("#{fetch(:crontab_scripts_path)}/*\.erb")
|
7
|
+
set :crontab_script_files, files.collect { |f| File.expand_path(f) }
|
8
|
+
fetch(:crontab_script_files).each do |file|
|
9
|
+
hash = eval(File.read(file).lines.to_a.shift)
|
10
|
+
if hash.nil? or hash[:user].nil? or hash[:schedule].nil?
|
11
|
+
fatal "Error reading the first line of #{file}"
|
12
|
+
fatal "Ensure the first line is a Ruby hash in the form: " +
|
13
|
+
"\"{ :user => \"www-data\", :schedule => \"* * * * *\" }\""
|
14
|
+
fatal "Your shebang line directly next"
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
task :erb_validity do
|
22
|
+
run_locally do
|
23
|
+
fetch(:crontab_script_files).each do |file|
|
24
|
+
unless test "erb", "-x", "-T", "'-'", file, "|", "ruby", "-c"
|
25
|
+
fatal "There's a syntax error with #{file}"
|
26
|
+
fatal "Test it manually with `erb -x -T '-' #{file} | ruby -c`"
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
4
33
|
desc 'Ensure all crontabinator specific settings are set, and warn and exit if not.'
|
5
|
-
|
34
|
+
task :settings => [:scripts, :erb_validity] do
|
6
35
|
{
|
7
36
|
(File.dirname(__FILE__) + "/examples/config/deploy.rb") => 'config/deploy.rb',
|
8
37
|
(File.dirname(__FILE__) + "/examples/config/deploy/staging.rb") => "config/deploy/#{fetch(:stage)}.rb"
|
data/lib/crontabinator/config.rb
CHANGED
@@ -18,12 +18,13 @@ namespace :crontabinator do
|
|
18
18
|
desc "Write example config files (with '_example' appended to their names)."
|
19
19
|
task :write_example_configs do
|
20
20
|
run_locally do
|
21
|
-
execute "mkdir", "-p", "config/deploy", fetch(:crontab_templates_path)
|
21
|
+
execute "mkdir", "-p", "config/deploy", fetch(:crontab_templates_path), fetch(:crontab_scripts_path)
|
22
22
|
{
|
23
23
|
"examples/Capfile" => "Capfile#{fetch(:example)}",
|
24
24
|
"examples/config/deploy.rb" => "config/deploy#{fetch(:example)}.rb",
|
25
25
|
"examples/config/deploy/staging.rb" => "config/deploy/staging#{fetch(:example)}.rb",
|
26
26
|
"examples/crontab.erb" => "#{fetch(:crontab_templates_path)}/crontab#{fetch(:example)}.erb",
|
27
|
+
"examples/myscript.sh.erb" => "#{fetch(:crontab_scripts_path)}/myscript#{fetch(:example)}.sh.erb"
|
27
28
|
}.each do |source, destination|
|
28
29
|
config = File.read(File.dirname(__FILE__) + "/#{source}")
|
29
30
|
File.open("./#{destination}", 'w') { |f| f.write(config) }
|
@@ -1,31 +1,108 @@
|
|
1
1
|
namespace :crontab do
|
2
2
|
|
3
|
+
# sets :user_crontab_hash in the form:
|
4
|
+
# { :"user" => ["#!/bin/bash", "/bin/echo 'asdf' >> /tmp/test.log"] }
|
5
|
+
task :read_all_settings => ['crontab:check:scripts'] do
|
6
|
+
run_locally do
|
7
|
+
user_crontab_hash = {}
|
8
|
+
|
9
|
+
# Auto entries
|
10
|
+
auto_entries = []
|
11
|
+
fetch(:crontab_script_files).each do |file|
|
12
|
+
hash = eval(File.read(file).lines.to_a.shift)
|
13
|
+
path = "#{fetch(:crontab_server_scripts_path)}/#{File.basename(file, '.erb')}"
|
14
|
+
auto_entries += [{ :user => hash[:user], :schedule => hash[:schedule], :path => path }]
|
15
|
+
end
|
16
|
+
auto_entries.each do |entry|
|
17
|
+
name = File.basename(entry[:path], '.erb')
|
18
|
+
user_crontab_hash[entry[:user]] ||= []
|
19
|
+
user_crontab_hash[entry[:user]] << [
|
20
|
+
"# #{name}",
|
21
|
+
"#{entry[:schedule]} #{entry[:path]} >> #{fetch(:crontab_logs_path)}/#{name} 2>&1",
|
22
|
+
""
|
23
|
+
]
|
24
|
+
end
|
25
|
+
|
26
|
+
# User entries
|
27
|
+
fetch(:user_crontab_entries, {}).each do |user, lines|
|
28
|
+
user_crontab_hash[user] ||= []
|
29
|
+
user_crontab_hash[user] << [lines]
|
30
|
+
end
|
31
|
+
|
32
|
+
# All entries
|
33
|
+
user_crontab_hash.each { |user, lines| user_crontab_hash[user] = lines.flatten }
|
34
|
+
|
35
|
+
set :user_crontab_hash, user_crontab_hash
|
36
|
+
|
37
|
+
# Newly removed crontabs
|
38
|
+
crontabs_to_remove = []
|
39
|
+
if File.exists?(fetch(:crontab_lockfile_path))
|
40
|
+
old_users = eval(File.read(fetch(:crontab_lockfile_path))).sort
|
41
|
+
new_users = user_crontab_hash.collect { |user, _| user }.sort
|
42
|
+
crontabs_to_remove = old_users - new_users
|
43
|
+
end
|
44
|
+
set :crontabs_to_remove, crontabs_to_remove
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
task :upload_scripts => [:read_all_settings] do
|
49
|
+
on roles(:cron) do |host|
|
50
|
+
fetch(:crontab_script_files).each do |path|
|
51
|
+
lines = File.read(path).lines.to_a
|
52
|
+
lines.shift
|
53
|
+
file = ERB.new(lines.join, nil, '-').result(binding)
|
54
|
+
as :root do execute("rm", "/tmp/script", "-f") end
|
55
|
+
upload! StringIO.new(file), "/tmp/script"
|
56
|
+
final_path = "#{fetch(:crontab_server_scripts_path)}/#{File.basename(path, '.erb')}"
|
57
|
+
as :root do
|
58
|
+
execute("mv", "/tmp/script", final_path)
|
59
|
+
execute("chmod", "750", final_path)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
3
65
|
desc "Idempotently setup Crontabs."
|
4
|
-
task :setup do
|
66
|
+
task :setup => ['crontab:check:settings', :read_all_settings, :upload_scripts] do
|
5
67
|
log_level = SSHKit.config.output_verbosity
|
6
68
|
log_level = "info" if log_level.nil?
|
7
69
|
SSHKit.config.output_verbosity = fetch(:crontab_log_level)
|
8
70
|
|
9
71
|
on roles(:cron) do |host|
|
10
|
-
|
72
|
+
# New
|
73
|
+
fetch(:user_crontab_hash).each do |user, lines|
|
11
74
|
unless unix_user_exists?(user)
|
12
|
-
error "
|
75
|
+
error "You defined crontab settings for '#{user}', but no such user exists - Skipping!"
|
13
76
|
else
|
14
|
-
set :crontab_entries,
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
as user do
|
22
|
-
execute "crontab", "/tmp/crontab"
|
23
|
-
end
|
77
|
+
set :crontab_entries, lines
|
78
|
+
path = File.expand_path("./#{fetch(:crontab_templates_path)}/crontab.erb")
|
79
|
+
file = ERB.new(File.read(path), nil, '-').result(binding)
|
80
|
+
as :root do execute("rm", "/tmp/crontab", "-f") end
|
81
|
+
upload! StringIO.new(file), "/tmp/crontab"
|
82
|
+
as :root do execute("chown", "#{user}:#{user}", "/tmp/crontab") end
|
83
|
+
as user do execute "crontab", "/tmp/crontab" end
|
24
84
|
as :root do
|
25
85
|
execute "rm", "/tmp/crontab"
|
26
86
|
end
|
27
87
|
end
|
28
88
|
end
|
89
|
+
|
90
|
+
# Old
|
91
|
+
fetch(:crontabs_to_remove).each do |user|
|
92
|
+
as :root do
|
93
|
+
execute "crontab", "-u", user, "-r"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
content = [
|
97
|
+
"# Add this file to version control, - it tracks and removes crontab",
|
98
|
+
"# entries on the server which you have removed from the config",
|
99
|
+
fetch(:user_crontab_hash).collect { |u, _| u }.sort.to_s
|
100
|
+
].join("\n") + "\n"
|
101
|
+
unless File.exists?(fetch(:crontab_lockfile_path)) &&
|
102
|
+
File.read(fetch(:crontab_lockfile_path)) == content
|
103
|
+
File.open(fetch(:crontab_lockfile_path), 'w') { |f| f.write(content) }
|
104
|
+
warn "Updated '#{fetch(:crontab_lockfile_path)}', add it to version control"
|
105
|
+
end
|
29
106
|
end
|
30
107
|
SSHKit.config.output_verbosity = log_level
|
31
108
|
end
|
@@ -35,13 +112,13 @@ namespace :crontab do
|
|
35
112
|
end
|
36
113
|
|
37
114
|
desc "Check the status of the Crontabs."
|
38
|
-
task :status do
|
115
|
+
task :status => [:read_all_settings] do
|
39
116
|
log_level = SSHKit.config.output_verbosity
|
40
117
|
log_level = "info" if log_level.nil?
|
41
118
|
SSHKit.config.output_verbosity = fetch(:crontab_log_level)
|
42
119
|
|
43
120
|
on roles(:cron) do
|
44
|
-
fetch(:
|
121
|
+
fetch(:user_crontab_hash).each do |user, _|
|
45
122
|
as :root do
|
46
123
|
unless unix_user_exists?(user)
|
47
124
|
error "User #{user} does not exist even though you defined crontab settings for it - Skipping!"
|
@@ -4,7 +4,7 @@ set :domain, "my-app.example.com"
|
|
4
4
|
server fetch(:domain),
|
5
5
|
:user => fetch(:deployment_username),
|
6
6
|
:roles => ["cron"]
|
7
|
-
set :user_crontab_entries, {
|
7
|
+
set :user_crontab_entries, { # this must be set, even if an empty Hash
|
8
8
|
"www-data" => [
|
9
9
|
"SHELL=/bin/bash",
|
10
10
|
"MAILTO=myemail@example.com",
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crontabinator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.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: 2015-
|
12
|
+
date: 2015-10-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: capistrano
|
@@ -90,6 +90,7 @@ files:
|
|
90
90
|
- lib/crontabinator/examples/config/deploy.rb
|
91
91
|
- lib/crontabinator/examples/config/deploy/staging.rb
|
92
92
|
- lib/crontabinator/examples/crontab.erb
|
93
|
+
- lib/crontabinator/examples/myscript.sh.erb
|
93
94
|
homepage: https://github.com/snarlysodboxer/crontabinator
|
94
95
|
licenses:
|
95
96
|
- GNU
|
@@ -117,3 +118,4 @@ signing_key:
|
|
117
118
|
specification_version: 3
|
118
119
|
summary: Deploy Crontabs
|
119
120
|
test_files: []
|
121
|
+
has_rdoc:
|