cronicle 0.1.4 → 0.1.5
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/README.md +9 -5
- data/cronicle.gemspec +1 -0
- data/lib/cronicle/cli.rb +2 -2
- data/lib/cronicle/client.rb +3 -1
- data/lib/cronicle/driver.rb +30 -2
- data/lib/cronicle/dsl/context.rb +6 -1
- data/lib/cronicle/dsl/context/job.rb +6 -1
- data/lib/cronicle/exporter.rb +2 -2
- data/lib/cronicle/ext/hash_ext.rb +1 -1
- data/lib/cronicle/ext/sshkit_ext.rb +80 -5
- data/lib/cronicle/version.rb +1 -1
- data/spec/cronicle_create_spec.rb +97 -0
- data/spec/cronicle_delete_spec.rb +159 -0
- data/spec/cronicle_exec_spec.rb +48 -0
- data/spec/spec_helper.rb +16 -1
- metadata +15 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 397f41f3a15c86c5307a304e878fdf755ee47474
|
4
|
+
data.tar.gz: 57a0933ff281f922f79bcef23304d570e563d56a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aba44a6c955bfc541ddf83d010031656935800cfca10b7c4dc88194201bddb8149762b5a7d93754363c691ff12a22da71950ba6b959326464bd6a8c2992fc538
|
7
|
+
data.tar.gz: 5772cd0031968bc5e026dc773190baffdff5d98c376ea4b8c7e119e19143d4a29f765519c4938f484027fec583d5b11684d70c4f3ec6b11c4fda57dc22d90683
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/README.md
CHANGED
@@ -39,13 +39,13 @@ Options:
|
|
39
39
|
[--ask-pass], [--no-ask-pass] # Ask sudo password
|
40
40
|
[--dry-run], [--no-dry-run] # Do not actually change
|
41
41
|
-c, [--ssh-config=SSH-CONFIG] # OpenSSH configuration file
|
42
|
-
# Default:
|
42
|
+
# Default: ssh_config
|
43
43
|
[--ssh-options=SSH-OPTIONS] # SSH options (JSON)
|
44
44
|
[--connection-timeout=N] # SSH connection timeout
|
45
45
|
[--concurrency=N] # SSH concurrency
|
46
46
|
# Default: 10
|
47
|
-
[--
|
48
|
-
# Default: /var/lib/cronicle
|
47
|
+
[--var-dir=VAR-DIR] # Cronicle var dir path
|
48
|
+
# Default: /var/lib/cronicle
|
49
49
|
-v, [--verbose], [--no-verbose] # Verbose mode
|
50
50
|
[--debug], [--no-debug] # Debug mode
|
51
51
|
[--color], [--no-color] # Colorize log
|
@@ -90,8 +90,12 @@ puts "hello"
|
|
90
90
|
|
91
91
|
```ruby
|
92
92
|
on servers: :your_hostname do
|
93
|
-
job :my_job, user: "ec2-user", schedule: "* * * * *" do
|
94
|
-
|
93
|
+
job :my_job, user: "ec2-user", schedule: "* * * * *", bundle: 'ruby-mysql' do
|
94
|
+
require 'mysql'
|
95
|
+
my = Mysql.connect('hostname', 'username', 'password', 'dbname')
|
96
|
+
my.query("select col1, col2 from tblname").each do |col1, col2|
|
97
|
+
p col1, col2
|
98
|
+
end
|
95
99
|
end
|
96
100
|
|
97
101
|
job :my_job2, user: "ec2-user", schedule: "* * * * *", content: <<-EOS
|
data/cronicle.gemspec
CHANGED
data/lib/cronicle/cli.rb
CHANGED
@@ -12,7 +12,7 @@ class Cronicle::CLI < Thor
|
|
12
12
|
class_option 'ssh-options', :desc => 'SSH options (JSON)', :default => ENV['CRONICLE_SSH_OPTIONS']
|
13
13
|
class_option 'connection-timeout', :desc => 'SSH connection timeout', :type => :numeric, :default => nil
|
14
14
|
class_option 'concurrency', :desc => 'SSH concurrency', :type => :numeric, :default => Cronicle::Client::DEFAULTS[:concurrency]
|
15
|
-
class_option '
|
15
|
+
class_option 'var-dir', :desc => 'Cronicle var dir path', :default => Cronicle::Client::DEFAULTS[:var_dir]
|
16
16
|
class_option 'verbose', :aliases => '-v', :desc => 'Verbose mode', :type => :boolean, :default => false
|
17
17
|
class_option 'debug', :desc => 'Debug mode', :type => :boolean, :default => false
|
18
18
|
class_option 'color', :desc => 'Colorize log', :type => :boolean, :default => true
|
@@ -85,7 +85,7 @@ class Cronicle::CLI < Thor
|
|
85
85
|
:sudo_password => options['sudo-password'],
|
86
86
|
:ssh_user => options['ssh-user'],
|
87
87
|
:concurrency => options['concurrency'],
|
88
|
-
:
|
88
|
+
:var_dir => options['var-dir'],
|
89
89
|
:dry_run => options['dry-run'],
|
90
90
|
:verbose => options['verbose']
|
91
91
|
}
|
data/lib/cronicle/client.rb
CHANGED
@@ -3,7 +3,7 @@ class Cronicle::Client
|
|
3
3
|
|
4
4
|
DEFAULTS = {
|
5
5
|
:concurrency => 10,
|
6
|
-
:
|
6
|
+
:var_dir => '/var/lib/cronicle'
|
7
7
|
}
|
8
8
|
|
9
9
|
def initialize(host_list, options = {})
|
@@ -138,6 +138,8 @@ class Cronicle::Client
|
|
138
138
|
(selected_hots + dsl_hosts).uniq.each do |h|
|
139
139
|
if hosts[h][job_user][job_name]
|
140
140
|
log(:warn, "Job is duplicated", :color => :yellow, :host => h, :user => job_user, :job => job_name)
|
141
|
+
elsif job_name.nil?
|
142
|
+
hosts[h] ||= {}
|
141
143
|
else
|
142
144
|
hosts[h][job_user][job_name] = job_hash
|
143
145
|
end
|
data/lib/cronicle/driver.rb
CHANGED
@@ -54,7 +54,20 @@ class Cronicle::Driver
|
|
54
54
|
end
|
55
55
|
|
56
56
|
upload_script(temp_dir, name, job[:content]) do |temp_script|
|
57
|
-
|
57
|
+
exec_opts = {:user => user, :raise_on_non_zero_exit => false}
|
58
|
+
command = nil
|
59
|
+
|
60
|
+
if job[:bundle]
|
61
|
+
mkgemfile(user, name, job[:bundle], temp_dir)
|
62
|
+
bundle(user, name, temp_dir)
|
63
|
+
|
64
|
+
with_bundle(user, name, temp_dir) do
|
65
|
+
command = sudo(:_execute, bundler_path, :exec, temp_script, exec_opts)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
command = sudo(:_execute, temp_script, exec_opts)
|
69
|
+
end
|
70
|
+
|
58
71
|
out = command.full_stdout
|
59
72
|
Cronicle::Utils.remove_prompt!(out)
|
60
73
|
host_user_job = {:host => host.hostname, :user => user, :job => name}
|
@@ -79,6 +92,13 @@ class Cronicle::Driver
|
|
79
92
|
end
|
80
93
|
|
81
94
|
def create_job(user, name, job)
|
95
|
+
execute do
|
96
|
+
if job[:bundle]
|
97
|
+
mkgemfile(user, name, job[:bundle])
|
98
|
+
bundle(user, name)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
82
102
|
create_or_update_job(user, name, job)
|
83
103
|
end
|
84
104
|
|
@@ -86,6 +106,13 @@ class Cronicle::Driver
|
|
86
106
|
job_content = job[:content].chomp
|
87
107
|
script_content = script[:content].chomp
|
88
108
|
|
109
|
+
execute do
|
110
|
+
if job[:bundle]
|
111
|
+
mkgemfile(user, name, job[:bundle])
|
112
|
+
bundle(user, name)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
89
116
|
if [:schedule, :content].any? {|k| job[k].chomp != script[k].chomp }
|
90
117
|
create_or_update_job(user, name, job, script)
|
91
118
|
end
|
@@ -114,7 +141,7 @@ class Cronicle::Driver
|
|
114
141
|
sudo(:execute, :cp, temp_script, libexec_script)
|
115
142
|
sudo(:execute, :touch, user_crontab(user))
|
116
143
|
delete_cron_entry(user, name)
|
117
|
-
add_cron_entry(user, name, job[:schedule], user_temp_dir)
|
144
|
+
add_cron_entry(user, name, job[:schedule], user_temp_dir, job[:bundle])
|
118
145
|
end
|
119
146
|
end
|
120
147
|
end
|
@@ -135,6 +162,7 @@ class Cronicle::Driver
|
|
135
162
|
unless host.options[:dry_run]
|
136
163
|
delete_cron_entry(user, name)
|
137
164
|
sudo(:execute, :rm, '-f', script[:path], :raise_on_non_zero_exit => false)
|
165
|
+
sudo(:execute, :rm, '-rf', gemfile_dir(user, name), :raise_on_non_zero_exit => false)
|
138
166
|
end
|
139
167
|
end
|
140
168
|
end
|
data/lib/cronicle/dsl/context.rb
CHANGED
@@ -42,7 +42,12 @@ class Cronicle::DSL::Context
|
|
42
42
|
end
|
43
43
|
|
44
44
|
target.assert_valid_keys(:servers, :roles)
|
45
|
+
values = Cronicle::DSL::Context::Job.new(target, &block).result.values
|
45
46
|
|
46
|
-
@result.concat(
|
47
|
+
@result.concat(values.empty? ? [{
|
48
|
+
:servers => Array(target[:servers]),
|
49
|
+
:roles => Array(target[:roles]),
|
50
|
+
:job => {}
|
51
|
+
}] : values)
|
47
52
|
end
|
48
53
|
end
|
@@ -30,7 +30,7 @@ class Cronicle::DSL::Context::Job
|
|
30
30
|
raise ArgumentError, "Job `#{name}`: :user is required"
|
31
31
|
end
|
32
32
|
|
33
|
-
opts.assert_valid_keys(:schedule, :user, :content)
|
33
|
+
opts.assert_valid_keys(:schedule, :user, :content, :bundle)
|
34
34
|
|
35
35
|
if opts[:content] and block
|
36
36
|
raise ArgumentError, 'Can not pass :content and block to `job` method'
|
@@ -42,6 +42,11 @@ class Cronicle::DSL::Context::Job
|
|
42
42
|
job_hash[:name] = name
|
43
43
|
job_hash[:user] = opts.fetch(:user).to_s
|
44
44
|
job_hash[:schedule] = opts[:schedule].to_s if opts[:schedule]
|
45
|
+
bundle = opts[:bundle]
|
46
|
+
|
47
|
+
if bundle
|
48
|
+
job_hash[:bundle] = bundle.kind_of?(Hash) ? bundle : Array(bundle).map(&:to_s)
|
49
|
+
end
|
45
50
|
|
46
51
|
if block
|
47
52
|
source = block.to_raw_source(:strip_enclosure => true).each_line.to_a
|
data/lib/cronicle/exporter.rb
CHANGED
@@ -32,12 +32,12 @@ class Cronicle::Exporter
|
|
32
32
|
|
33
33
|
def parse_crontab(crontab, libexec_contents)
|
34
34
|
scripts = {}
|
35
|
-
libexec_dir = @options.fetch(:libexec
|
35
|
+
libexec_dir = @options.fetch(:var_dir) + '/libexec'
|
36
36
|
|
37
37
|
crontab.each_line.map(&:strip).each do |line|
|
38
38
|
next if line =~ /\A#/
|
39
39
|
|
40
|
-
md = line.match(/\A(@\w+|\S+(?:\s+\S+){4})\s+(.\S+)(.*)\z/)
|
40
|
+
md = line.match(/\A(@\w+|\S+(?:\s+\S+){4})\s+(?:cd\s+\S+\s+&&\s+\S*bundle\s+exec\s+)?(.\S+)(.*)\z/)
|
41
41
|
schedule, path, extra = md.captures if md
|
42
42
|
|
43
43
|
if %r|\A#{Regexp.escape(libexec_dir)}/(?:[^/]+)/(.+)| =~ path
|
@@ -2,7 +2,7 @@ class Hash
|
|
2
2
|
def assert_valid_keys(*valid_keys)
|
3
3
|
each_key do |k|
|
4
4
|
next if valid_keys.include?(k)
|
5
|
-
raise ArgumentError, "
|
5
|
+
raise ArgumentError, "unknown key: #{k.inspect}. valid keys are: #{valid_keys.map(&:inspect).join(', ')}"
|
6
6
|
end
|
7
7
|
end
|
8
8
|
end
|
@@ -77,11 +77,17 @@ class SSHKit::Backend::Netssh
|
|
77
77
|
sudo(:execute, :sed, '-i', sed_cmd, user_crontab(user), :raise_on_non_zero_exit => false)
|
78
78
|
end
|
79
79
|
|
80
|
-
def add_cron_entry(user, name, schedule, temp_dir)
|
80
|
+
def add_cron_entry(user, name, schedule, temp_dir, bundle_gems = nil)
|
81
81
|
script = script_path(user, name)
|
82
82
|
temp_entry = [temp_dir, name + '.entry'].join('/')
|
83
83
|
|
84
|
-
cron_entry = "#{schedule}\\t
|
84
|
+
cron_entry = "#{schedule}\\t"
|
85
|
+
|
86
|
+
if bundle_gems
|
87
|
+
cron_entry << "cd #{gemfile_dir(user, name)} && #{bundler_path} exec "
|
88
|
+
end
|
89
|
+
|
90
|
+
cron_entry << "#{script} 2>&1 | logger -t cronicle/#{user}/#{name}"
|
85
91
|
cron_entry = Shellwords.shellescape(cron_entry)
|
86
92
|
sudo(:execute, :echo, '-e', cron_entry, '>', temp_entry)
|
87
93
|
|
@@ -91,7 +97,7 @@ class SSHKit::Backend::Netssh
|
|
91
97
|
end
|
92
98
|
|
93
99
|
def upload_script(temp_dir, name, content)
|
94
|
-
temp_script = [temp_dir, name].join
|
100
|
+
temp_script = [temp_dir, name].join('/')
|
95
101
|
upload!(StringIO.new(content), temp_script)
|
96
102
|
execute(:chmod, 755, temp_script)
|
97
103
|
yield(temp_script)
|
@@ -113,18 +119,87 @@ class SSHKit::Backend::Netssh
|
|
113
119
|
|
114
120
|
yield(*block_args)
|
115
121
|
ensure
|
116
|
-
|
122
|
+
sudo(:execute, :rm, '-rf', temp_dir, :raise_on_non_zero_exit => false) rescue nil
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def mkgemfile(user, name, bundle_gems, temp_dir = nil)
|
127
|
+
sudo(:execute, :mkdir, '-p', gemfile_dir(user, name, temp_dir))
|
128
|
+
sudo(:execute, :bash, '-c',
|
129
|
+
Shellwords.shellescape(
|
130
|
+
[:echo, Shellwords.shellescape("source 'https://rubygems.org'"), '>', gemfile(user, name, temp_dir)].join(' ')
|
131
|
+
)
|
132
|
+
)
|
133
|
+
|
134
|
+
bundle_gems.each do |gem_name, version|
|
135
|
+
line = "gem '#{gem_name}'"
|
136
|
+
line << ", '#{version}'" if version
|
137
|
+
sudo(:execute, :bash, '-c',
|
138
|
+
Shellwords.shellescape(
|
139
|
+
[:echo, Shellwords.shellescape(line), '>>', gemfile(user, name, temp_dir)].join(' ')
|
140
|
+
)
|
141
|
+
)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def bundle(user, name, temp_dir = nil)
|
146
|
+
with_bundle(user, name, temp_dir) do |bundler_opts|
|
147
|
+
unless sudo(:execute, bundler_path, :check, *bundler_opts, :raise_on_non_zero_exit => false)
|
148
|
+
sudo(:execute, bundler_path, :install, *bundler_opts)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def with_bundle(user, name, temp_dir = nil)
|
154
|
+
within gemfile_dir(user, name, temp_dir) do
|
155
|
+
bundler_opts = ['--no-color', '--gemfile', gemfile(user, name, temp_dir), '--path', bundle_dir]
|
156
|
+
yield(bundler_opts)
|
117
157
|
end
|
118
158
|
end
|
119
159
|
|
120
160
|
def libexec_dir
|
121
|
-
host.options.fetch(:libexec
|
161
|
+
host.options.fetch(:var_dir) + '/libexec'
|
162
|
+
end
|
163
|
+
|
164
|
+
def run_dir
|
165
|
+
host.options.fetch(:var_dir) + '/run'
|
166
|
+
end
|
167
|
+
|
168
|
+
def bundle_dir
|
169
|
+
host.options.fetch(:var_dir) + '/bundle'
|
170
|
+
end
|
171
|
+
|
172
|
+
BUNDLER_PATHS = %w(
|
173
|
+
/usr/local/bin/bundle
|
174
|
+
/usr/bin/bundle
|
175
|
+
)
|
176
|
+
|
177
|
+
def bundler_path
|
178
|
+
@bundler_path ||= (BUNDLER_PATHS.find {|path|
|
179
|
+
execute(:test, '-f', path, :raise_on_non_zero_exit => false)
|
180
|
+
} || :bundle)
|
122
181
|
end
|
123
182
|
|
124
183
|
def user_libexec_dir(user)
|
125
184
|
[libexec_dir, user].join('/')
|
126
185
|
end
|
127
186
|
|
187
|
+
def user_run_dir(user)
|
188
|
+
[run_dir, user].join('/')
|
189
|
+
end
|
190
|
+
|
191
|
+
def gemfile_dir(user, name, temp_dir = nil)
|
192
|
+
if temp_dir
|
193
|
+
[temp_dir, user, name].join('/')
|
194
|
+
else
|
195
|
+
[user_run_dir(user), name].join('/')
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def gemfile(user, name, temp_dir = nil)
|
200
|
+
[gemfile_dir(user, name, temp_dir), 'Gemfile'].join('/')
|
201
|
+
end
|
202
|
+
|
128
203
|
def user_crontab(user)
|
129
204
|
cron_dir = find_cron_dir
|
130
205
|
[cron_dir, user].join('/')
|
data/lib/cronicle/version.rb
CHANGED
@@ -242,6 +242,103 @@ ZOO=baz
|
|
242
242
|
end
|
243
243
|
end
|
244
244
|
|
245
|
+
context 'when apply with bundle' do
|
246
|
+
let(:jobfile) do
|
247
|
+
<<-RUBY.unindent
|
248
|
+
on servers: /.*/ do
|
249
|
+
job :foo, user: :root, schedule: '1 2 * * *', bundle: 'ruby-mysql' do
|
250
|
+
require 'mysql'
|
251
|
+
p Mysql
|
252
|
+
end
|
253
|
+
end
|
254
|
+
RUBY
|
255
|
+
end
|
256
|
+
|
257
|
+
let(:amzn_crontab) do
|
258
|
+
{
|
259
|
+
"/var/spool/cron/ec2-user" =>
|
260
|
+
"FOO=bar
|
261
|
+
ZOO=baz
|
262
|
+
1 1 1 1 1 echo ec2-user > /dev/null
|
263
|
+
",
|
264
|
+
"/var/spool/cron/root" =>
|
265
|
+
"FOO=bar
|
266
|
+
ZOO=baz
|
267
|
+
1 1 1 1 1 echo root > /dev/null
|
268
|
+
1 2 * * *\tcd /var/lib/cronicle/run/root/foo && /usr/local/bin/bundle exec /var/lib/cronicle/libexec/root/foo 2>&1 | logger -t cronicle/root/foo
|
269
|
+
"
|
270
|
+
}
|
271
|
+
end
|
272
|
+
|
273
|
+
let(:amzn_gemfile) do
|
274
|
+
{
|
275
|
+
"/var/lib/cronicle/run/root/foo/Gemfile" =>
|
276
|
+
"source 'https://rubygems.org'
|
277
|
+
gem 'ruby-mysql'
|
278
|
+
"
|
279
|
+
}
|
280
|
+
end
|
281
|
+
|
282
|
+
let(:ubuntu_crontab) do
|
283
|
+
{
|
284
|
+
"/var/spool/cron/crontabs/root" =>
|
285
|
+
"FOO=bar
|
286
|
+
ZOO=baz
|
287
|
+
1 1 1 1 1 echo root > /dev/null
|
288
|
+
1 2 * * *\tcd /var/lib/cronicle/run/root/foo && /usr/local/bin/bundle exec /var/lib/cronicle/libexec/root/foo 2>&1 | logger -t cronicle/root/foo
|
289
|
+
",
|
290
|
+
"/var/spool/cron/crontabs/ubuntu" =>
|
291
|
+
"FOO=bar
|
292
|
+
ZOO=baz
|
293
|
+
1 1 1 1 1 echo ubuntu > /dev/null
|
294
|
+
"
|
295
|
+
}
|
296
|
+
end
|
297
|
+
|
298
|
+
let(:ubuntu_gemfile) do
|
299
|
+
{
|
300
|
+
"/var/lib/cronicle/run/root/foo/Gemfile" =>
|
301
|
+
"source 'https://rubygems.org'
|
302
|
+
gem 'ruby-mysql'
|
303
|
+
"
|
304
|
+
}
|
305
|
+
end
|
306
|
+
|
307
|
+
before do
|
308
|
+
cronicle(:apply) { jobfile }
|
309
|
+
end
|
310
|
+
|
311
|
+
it do
|
312
|
+
on :amazon_linux do
|
313
|
+
expect(get_uname).to match /amzn/
|
314
|
+
expect(get_crontabs).to eq amzn_crontab
|
315
|
+
|
316
|
+
expect(get_file('/var/lib/cronicle/libexec/root/foo')).to eq <<-EOS.unindent
|
317
|
+
#!/usr/bin/env ruby
|
318
|
+
require 'mysql'
|
319
|
+
p Mysql
|
320
|
+
EOS
|
321
|
+
|
322
|
+
expect(get_gemfiles).to eq amzn_gemfile
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
it do
|
327
|
+
on :ubuntu do
|
328
|
+
expect(get_uname).to match /Ubuntu/
|
329
|
+
expect(get_crontabs).to eq ubuntu_crontab
|
330
|
+
|
331
|
+
expect(get_file('/var/lib/cronicle/libexec/root/foo')).to eq <<-EOS.unindent
|
332
|
+
#!/usr/bin/env ruby
|
333
|
+
require 'mysql'
|
334
|
+
p Mysql
|
335
|
+
EOS
|
336
|
+
|
337
|
+
expect(get_gemfiles).to eq ubuntu_gemfile
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
245
342
|
context 'when apply (dry-run)' do
|
246
343
|
let(:amzn_crontab) do
|
247
344
|
{
|
@@ -206,6 +206,165 @@ ZOO=baz
|
|
206
206
|
end
|
207
207
|
end
|
208
208
|
|
209
|
+
context 'when cron is deleted with bundle' do
|
210
|
+
let(:jobfile) do
|
211
|
+
<<-RUBY.unindent
|
212
|
+
on servers: /.*/ do
|
213
|
+
job :foo, user: :root, schedule: '1 2 * * *', bundle: 'ruby-mysql' do
|
214
|
+
require 'mysql'
|
215
|
+
p Mysql
|
216
|
+
end
|
217
|
+
end
|
218
|
+
RUBY
|
219
|
+
end
|
220
|
+
|
221
|
+
let(:amzn_crontab_orig) do
|
222
|
+
{
|
223
|
+
"/var/spool/cron/ec2-user" =>
|
224
|
+
"FOO=bar
|
225
|
+
ZOO=baz
|
226
|
+
1 1 1 1 1 echo ec2-user > /dev/null
|
227
|
+
",
|
228
|
+
"/var/spool/cron/root" =>
|
229
|
+
"FOO=bar
|
230
|
+
ZOO=baz
|
231
|
+
1 1 1 1 1 echo root > /dev/null
|
232
|
+
1 2 * * *\tcd /var/lib/cronicle/run/root/foo && /usr/local/bin/bundle exec /var/lib/cronicle/libexec/root/foo 2>&1 | logger -t cronicle/root/foo
|
233
|
+
"
|
234
|
+
}
|
235
|
+
end
|
236
|
+
|
237
|
+
let(:amzn_gemfile_orig) do
|
238
|
+
{
|
239
|
+
"/var/lib/cronicle/run/root/foo/Gemfile" =>
|
240
|
+
"source 'https://rubygems.org'
|
241
|
+
gem 'ruby-mysql'
|
242
|
+
"
|
243
|
+
}
|
244
|
+
end
|
245
|
+
|
246
|
+
let(:ubuntu_crontab_orig) do
|
247
|
+
{
|
248
|
+
"/var/spool/cron/crontabs/root" =>
|
249
|
+
"FOO=bar
|
250
|
+
ZOO=baz
|
251
|
+
1 1 1 1 1 echo root > /dev/null
|
252
|
+
1 2 * * *\tcd /var/lib/cronicle/run/root/foo && /usr/local/bin/bundle exec /var/lib/cronicle/libexec/root/foo 2>&1 | logger -t cronicle/root/foo
|
253
|
+
",
|
254
|
+
"/var/spool/cron/crontabs/ubuntu" =>
|
255
|
+
"FOO=bar
|
256
|
+
ZOO=baz
|
257
|
+
1 1 1 1 1 echo ubuntu > /dev/null
|
258
|
+
"
|
259
|
+
}
|
260
|
+
end
|
261
|
+
|
262
|
+
let(:ubuntu_gemfile_orig) do
|
263
|
+
{
|
264
|
+
"/var/lib/cronicle/run/root/foo/Gemfile" =>
|
265
|
+
"source 'https://rubygems.org'
|
266
|
+
gem 'ruby-mysql'
|
267
|
+
"
|
268
|
+
}
|
269
|
+
end
|
270
|
+
|
271
|
+
let(:amzn_crontab) do
|
272
|
+
{
|
273
|
+
"/var/spool/cron/ec2-user" =>
|
274
|
+
"FOO=bar
|
275
|
+
ZOO=baz
|
276
|
+
1 1 1 1 1 echo ec2-user > /dev/null
|
277
|
+
",
|
278
|
+
"/var/spool/cron/root" =>
|
279
|
+
"FOO=bar
|
280
|
+
ZOO=baz
|
281
|
+
1 1 1 1 1 echo root > /dev/null
|
282
|
+
1 2 * * *\tcd /var/lib/cronicle/run/root/foo && /usr/local/bin/bundle exec /var/lib/cronicle/libexec/root/foo 2>&1 | logger -t cronicle/root/foo
|
283
|
+
"
|
284
|
+
}
|
285
|
+
end
|
286
|
+
|
287
|
+
let(:amzn_gemfile) do
|
288
|
+
{
|
289
|
+
"/var/lib/cronicle/run/root/foo/Gemfile" =>
|
290
|
+
"source 'https://rubygems.org'
|
291
|
+
gem 'ruby-mysql'
|
292
|
+
"
|
293
|
+
}
|
294
|
+
end
|
295
|
+
|
296
|
+
let(:ubuntu_crontab) do
|
297
|
+
{
|
298
|
+
"/var/spool/cron/crontabs/root" =>
|
299
|
+
"FOO=bar
|
300
|
+
ZOO=baz
|
301
|
+
1 1 1 1 1 echo root > /dev/null
|
302
|
+
1 2 * * *\tcd /var/lib/cronicle/run/root/foo && /usr/local/bin/bundle exec /var/lib/cronicle/libexec/root/foo 2>&1 | logger -t cronicle/root/foo
|
303
|
+
",
|
304
|
+
"/var/spool/cron/crontabs/ubuntu" =>
|
305
|
+
"FOO=bar
|
306
|
+
ZOO=baz
|
307
|
+
1 1 1 1 1 echo ubuntu > /dev/null
|
308
|
+
"
|
309
|
+
}
|
310
|
+
end
|
311
|
+
|
312
|
+
let(:ubuntu_gemfile) do
|
313
|
+
{
|
314
|
+
"/var/lib/cronicle/run/root/foo/Gemfile" =>
|
315
|
+
"source 'https://rubygems.org'
|
316
|
+
gem 'ruby-mysql'
|
317
|
+
"
|
318
|
+
}
|
319
|
+
end
|
320
|
+
|
321
|
+
before do
|
322
|
+
cronicle(:apply) { jobfile }
|
323
|
+
end
|
324
|
+
|
325
|
+
it do
|
326
|
+
on :amazon_linux do
|
327
|
+
expect(get_uname).to match /amzn/
|
328
|
+
expect(get_crontabs).to eq amzn_crontab_orig
|
329
|
+
|
330
|
+
expect(get_file('/var/lib/cronicle/libexec/root/foo')).to eq <<-EOS.unindent
|
331
|
+
#!/usr/bin/env ruby
|
332
|
+
require 'mysql'
|
333
|
+
p Mysql
|
334
|
+
EOS
|
335
|
+
|
336
|
+
expect(get_gemfiles).to eq amzn_gemfile_orig
|
337
|
+
end
|
338
|
+
|
339
|
+
on :ubuntu do
|
340
|
+
expect(get_uname).to match /Ubuntu/
|
341
|
+
expect(get_crontabs).to eq ubuntu_crontab_orig
|
342
|
+
|
343
|
+
expect(get_file('/var/lib/cronicle/libexec/root/foo')).to eq <<-EOS.unindent
|
344
|
+
#!/usr/bin/env ruby
|
345
|
+
require 'mysql'
|
346
|
+
p Mysql
|
347
|
+
EOS
|
348
|
+
|
349
|
+
expect(get_gemfiles).to eq ubuntu_gemfile_orig
|
350
|
+
end
|
351
|
+
|
352
|
+
cronicle(:apply) { '' }
|
353
|
+
|
354
|
+
on :amazon_linux do
|
355
|
+
expect(get_uname).to match /amzn/
|
356
|
+
expect(get_crontabs).to eq amzn_crontab
|
357
|
+
expect(get_gemfiles).to eq amzn_gemfile
|
358
|
+
end
|
359
|
+
|
360
|
+
on :ubuntu do
|
361
|
+
expect(get_uname).to match /Ubuntu/
|
362
|
+
expect(get_crontabs).to eq ubuntu_crontab
|
363
|
+
expect(get_gemfiles).to eq ubuntu_gemfile
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
209
368
|
context 'when cron is deleted (dry-run)' do
|
210
369
|
let(:amzn_crontab) do
|
211
370
|
{
|
data/spec/cronicle_exec_spec.rb
CHANGED
@@ -162,4 +162,52 @@ describe 'Cronicle::Client#exec' do
|
|
162
162
|
}.to raise_error('Definition cannot be found: Job `bar`')
|
163
163
|
end
|
164
164
|
end
|
165
|
+
|
166
|
+
context 'with bundle' do
|
167
|
+
let(:jobfile) do
|
168
|
+
<<-RUBY.unindent
|
169
|
+
on servers: /amazon_linux/ do
|
170
|
+
job :foo, user: 'ec2-user', bundle: 'hashie' do
|
171
|
+
require 'hashie'
|
172
|
+
mash = Hashie::Mash.new
|
173
|
+
mash.name = "My Mash on amazon_linux"
|
174
|
+
p mash.name
|
175
|
+
p mash.name?
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
on servers: /ubuntu/ do
|
180
|
+
job :foo, user: :ubuntu, bundle: 'hashie' do
|
181
|
+
require 'hashie'
|
182
|
+
mash = Hashie::Mash.new
|
183
|
+
mash.name = "My Mash on ubuntu"
|
184
|
+
p mash.name
|
185
|
+
p mash.name?
|
186
|
+
end
|
187
|
+
end
|
188
|
+
RUBY
|
189
|
+
end
|
190
|
+
|
191
|
+
before do
|
192
|
+
cronicle(:exec, :foo, logger: logger) { jobfile }
|
193
|
+
end
|
194
|
+
|
195
|
+
it do
|
196
|
+
expect(amzn_out).to eq <<-EOS.unindent
|
197
|
+
foo on amazon_linux/ec2-user> Execute job
|
198
|
+
foo on amazon_linux/ec2-user>\s
|
199
|
+
foo on amazon_linux/ec2-user> "My Mash on amazon_linux"
|
200
|
+
foo on amazon_linux/ec2-user> true
|
201
|
+
EOS
|
202
|
+
end
|
203
|
+
|
204
|
+
it do
|
205
|
+
expect(ubuntu_out).to eq <<-EOS.unindent
|
206
|
+
foo on ubuntu/ubuntu> Execute job
|
207
|
+
foo on ubuntu/ubuntu>\s
|
208
|
+
foo on ubuntu/ubuntu> "My Mash on ubuntu"
|
209
|
+
foo on ubuntu/ubuntu> true
|
210
|
+
EOS
|
211
|
+
end
|
212
|
+
end
|
165
213
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -50,6 +50,15 @@ def get_crontabs
|
|
50
50
|
}.flatten]
|
51
51
|
end
|
52
52
|
|
53
|
+
def get_gemfiles
|
54
|
+
gemfiles = Specinfra.backend.run_command("ls /var/lib/cronicle/run/*/*/Gemfile 2> /dev/null").stdout.strip.split(/\s+/)
|
55
|
+
|
56
|
+
Hash[*gemfiles.map {|gemfile|
|
57
|
+
content = Specinfra.backend.run_command("cat #{gemfile}").stdout
|
58
|
+
[gemfile, content]
|
59
|
+
}.flatten]
|
60
|
+
end
|
61
|
+
|
53
62
|
def get_file(path)
|
54
63
|
Specinfra.backend.run_command("cat #{path}").stdout
|
55
64
|
end
|
@@ -87,9 +96,14 @@ def on(*hosts)
|
|
87
96
|
end
|
88
97
|
|
89
98
|
RSpec.configure do |config|
|
90
|
-
config.before(:
|
99
|
+
config.before(:all) do
|
91
100
|
on :ubuntu do
|
92
101
|
Specinfra.backend.run_command("apt-get -y install ruby")
|
102
|
+
Specinfra.backend.run_command("gem install bundler")
|
103
|
+
end
|
104
|
+
|
105
|
+
on :amazon_linux do
|
106
|
+
Specinfra.backend.run_command("gem install bundler")
|
93
107
|
end
|
94
108
|
end
|
95
109
|
|
@@ -97,6 +111,7 @@ RSpec.configure do |config|
|
|
97
111
|
on TARGET_HOSTS do
|
98
112
|
cron_dir = get_cron_dir
|
99
113
|
Specinfra.backend.run_command("rm -f #{cron_dir}/*")
|
114
|
+
Specinfra.backend.run_command("rm -rf /var/lib/cronicle/run")
|
100
115
|
end
|
101
116
|
end
|
102
117
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cronicle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Genki Sugawara
|
@@ -178,6 +178,20 @@ dependencies:
|
|
178
178
|
- - '>='
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: rspec-instafail
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - '>='
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - '>='
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
181
195
|
description: It is a tool for execute script, and define cron on remote hosts.
|
182
196
|
email:
|
183
197
|
- sgwr_dts@yahoo.co.jp
|