crontabinator 0.0.0 → 0.0.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.
@@ -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:
|