minicron 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +187 -0
- data/Rakefile +17 -0
- data/bin/minicron +26 -0
- data/lib/minicron.rb +179 -0
- data/lib/minicron/alert.rb +115 -0
- data/lib/minicron/alert/email.rb +50 -0
- data/lib/minicron/alert/pagerduty.rb +39 -0
- data/lib/minicron/alert/sms.rb +47 -0
- data/lib/minicron/cli.rb +367 -0
- data/lib/minicron/constants.rb +7 -0
- data/lib/minicron/cron.rb +192 -0
- data/lib/minicron/hub/app.rb +132 -0
- data/lib/minicron/hub/assets/app/application.js +151 -0
- data/lib/minicron/hub/assets/app/components/schedules.js +280 -0
- data/lib/minicron/hub/assets/app/controllers/executions.js +35 -0
- data/lib/minicron/hub/assets/app/controllers/hosts.js +129 -0
- data/lib/minicron/hub/assets/app/controllers/jobs.js +109 -0
- data/lib/minicron/hub/assets/app/controllers/schedules.js +80 -0
- data/lib/minicron/hub/assets/app/helpers.js +22 -0
- data/lib/minicron/hub/assets/app/models/execution.js +13 -0
- data/lib/minicron/hub/assets/app/models/host.js +15 -0
- data/lib/minicron/hub/assets/app/models/job.js +15 -0
- data/lib/minicron/hub/assets/app/models/job_execution_output.js +11 -0
- data/lib/minicron/hub/assets/app/models/schedule.js +32 -0
- data/lib/minicron/hub/assets/app/router.js +31 -0
- data/lib/minicron/hub/assets/app/routes/executions.js +36 -0
- data/lib/minicron/hub/assets/app/routes/hosts.js +42 -0
- data/lib/minicron/hub/assets/app/routes/index.js +9 -0
- data/lib/minicron/hub/assets/app/routes/jobs.js +52 -0
- data/lib/minicron/hub/assets/app/routes/schedules.js +37 -0
- data/lib/minicron/hub/assets/css/bootswatch.min.css +9 -0
- data/lib/minicron/hub/assets/css/main.scss +323 -0
- data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.eot +0 -0
- data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.svg +229 -0
- data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.woff +0 -0
- data/lib/minicron/hub/assets/fonts/lato-bold-700.woff +0 -0
- data/lib/minicron/hub/assets/fonts/lato-italic-400.woff +0 -0
- data/lib/minicron/hub/assets/fonts/lato-regular-400.woff +0 -0
- data/lib/minicron/hub/assets/js/ansi_up-1.1.1.min.js +6 -0
- data/lib/minicron/hub/assets/js/auth/ember-auth-9.0.7.min.js +2 -0
- data/lib/minicron/hub/assets/js/auth/ember-auth-request-jquery-1.0.3.min.js +1 -0
- data/lib/minicron/hub/assets/js/bootstrap-3.1.1.min.js +6 -0
- data/lib/minicron/hub/assets/js/ember-1.4.1.min.js +18 -0
- data/lib/minicron/hub/assets/js/ember-data-1.0.0-beta.7.f87cba88.min.js +10 -0
- data/lib/minicron/hub/assets/js/faye-browser-1.0.1.min.js +2 -0
- data/lib/minicron/hub/assets/js/handlebars-1.3.0.min.js +29 -0
- data/lib/minicron/hub/assets/js/jquery-2.1.0.min.js +4 -0
- data/lib/minicron/hub/assets/js/moment-2.5.1.min.js +7 -0
- data/lib/minicron/hub/controllers/api/executions.rb +34 -0
- data/lib/minicron/hub/controllers/api/hosts.rb +150 -0
- data/lib/minicron/hub/controllers/api/job_execution_outputs.rb +30 -0
- data/lib/minicron/hub/controllers/api/jobs.rb +118 -0
- data/lib/minicron/hub/controllers/api/schedule.rb +184 -0
- data/lib/minicron/hub/controllers/index.rb +5 -0
- data/lib/minicron/hub/db/schema.rb +98 -0
- data/lib/minicron/hub/db/schema.sql +158 -0
- data/lib/minicron/hub/models/alert.rb +7 -0
- data/lib/minicron/hub/models/execution.rb +8 -0
- data/lib/minicron/hub/models/host.rb +7 -0
- data/lib/minicron/hub/models/job.rb +18 -0
- data/lib/minicron/hub/models/job_execution_output.rb +7 -0
- data/lib/minicron/hub/models/schedule.rb +25 -0
- data/lib/minicron/hub/serializers/execution.rb +75 -0
- data/lib/minicron/hub/serializers/host.rb +57 -0
- data/lib/minicron/hub/serializers/job.rb +104 -0
- data/lib/minicron/hub/serializers/job_execution_output.rb +48 -0
- data/lib/minicron/hub/serializers/schedule.rb +68 -0
- data/lib/minicron/hub/views/handlebars/application.erb +51 -0
- data/lib/minicron/hub/views/handlebars/errors.erb +29 -0
- data/lib/minicron/hub/views/handlebars/executions.erb +79 -0
- data/lib/minicron/hub/views/handlebars/hosts.erb +205 -0
- data/lib/minicron/hub/views/handlebars/jobs.erb +203 -0
- data/lib/minicron/hub/views/handlebars/loading.erb +3 -0
- data/lib/minicron/hub/views/handlebars/schedules.erb +354 -0
- data/lib/minicron/hub/views/index.erb +7 -0
- data/lib/minicron/hub/views/layouts/app.erb +15 -0
- data/lib/minicron/monitor.rb +116 -0
- data/lib/minicron/transport.rb +15 -0
- data/lib/minicron/transport/client.rb +80 -0
- data/lib/minicron/transport/faye/client.rb +103 -0
- data/lib/minicron/transport/faye/extensions/job_handler.rb +184 -0
- data/lib/minicron/transport/faye/server.rb +58 -0
- data/lib/minicron/transport/server.rb +62 -0
- data/lib/minicron/transport/ssh.rb +51 -0
- data/spec/invalid_config.toml +2 -0
- data/spec/minicron/cli_spec.rb +154 -0
- data/spec/minicron/transport/client_spec.rb +8 -0
- data/spec/minicron/transport/faye/client_spec.rb +53 -0
- data/spec/minicron/transport/server_spec.rb +70 -0
- data/spec/minicron/transport_spec.rb +13 -0
- data/spec/minicron_spec.rb +133 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/valid_config.toml +48 -0
- metadata +577 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'mail'
|
2
|
+
|
3
|
+
module Minicron
|
4
|
+
class Email
|
5
|
+
# Configure the mail client
|
6
|
+
def initialize
|
7
|
+
Mail.defaults do
|
8
|
+
delivery_method(
|
9
|
+
:smtp,
|
10
|
+
:address => Minicron.config['alerts']['email']['smtp']['address'],
|
11
|
+
:port => Minicron.config['alerts']['email']['smtp']['port']
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
# Return the message for an alert
|
16
|
+
#
|
17
|
+
# @option options [Minicron::Hub::Job] job a job instance
|
18
|
+
# @option options [String] kind 'fail' or 'miss'
|
19
|
+
# @option options [Integer, nil] schedule_id only applies to 'miss' alerts
|
20
|
+
# @option options [Integer, nil] execution_id only used by 'fail' alerts
|
21
|
+
# @option options [Integer] job_id used to look up the job name for the alert message
|
22
|
+
# @option options [Time] expected_at when the schedule was expected to execute
|
23
|
+
# @option options [String] medium the medium to send the alert via
|
24
|
+
def get_message(options = {})
|
25
|
+
case options[:kind]
|
26
|
+
when 'miss'
|
27
|
+
"Job ##{options[:job_id]} '#{options[:job].name}' failed to execute at its expected time: #{options[:expected_at]}."
|
28
|
+
when 'fail'
|
29
|
+
"Execution ##{options[:execution_id]} of Job ##{options[:job_id]} '#{options[:job].name}' failed."
|
30
|
+
else
|
31
|
+
raise Exception, "The kind '#{options[:kind]} is not supported!"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Send an email alert
|
36
|
+
#
|
37
|
+
# @param from [String]
|
38
|
+
# @param to [String]
|
39
|
+
# @param subject [String]
|
40
|
+
# @param message [String]
|
41
|
+
def send(from, to, subject, message)
|
42
|
+
Mail.deliver do
|
43
|
+
to to
|
44
|
+
from from
|
45
|
+
subject subject
|
46
|
+
body message
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'pagerduty'
|
2
|
+
|
3
|
+
module Minicron
|
4
|
+
class PagerDuty
|
5
|
+
# Used to set up on the pagerduty client
|
6
|
+
def initialize
|
7
|
+
# Get an instance of the Pagerduty client
|
8
|
+
@client = ::Pagerduty.new(Minicron.config['alerts']['pagerduty']['service_key'])
|
9
|
+
end
|
10
|
+
|
11
|
+
# Return the message for an alert
|
12
|
+
#
|
13
|
+
# @option options [Minicron::Hub::Job] job a job instance
|
14
|
+
# @option options [String] kind 'fail' or 'miss'
|
15
|
+
# @option options [Integer, nil] schedule_id only applies to 'miss' alerts
|
16
|
+
# @option options [Integer, nil] execution_id only used by 'fail' alerts
|
17
|
+
# @option options [Integer] job_id used to look up the job name for the alert message
|
18
|
+
# @option options [Time] expected_at when the schedule was expected to execute
|
19
|
+
# @option options [String] medium the medium to send the alert via
|
20
|
+
def get_message(options = {})
|
21
|
+
case options[:kind]
|
22
|
+
when 'miss'
|
23
|
+
"Job ##{options[:job_id]} failed to execute at its expected time - #{options[:expected_at]}"
|
24
|
+
when 'fail'
|
25
|
+
"Execution ##{options[:execution_id]} of Job ##{options[:job_id]} failed"
|
26
|
+
else
|
27
|
+
raise Exception, "The kind '#{options[:kind]} is not supported!"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Send a pager duty alert
|
32
|
+
#
|
33
|
+
# @param title [String]
|
34
|
+
# @param message [String]
|
35
|
+
def send(title, message)
|
36
|
+
@client.trigger(title, { :message => message })
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'twilio-ruby'
|
2
|
+
|
3
|
+
module Minicron
|
4
|
+
class SMS
|
5
|
+
# Used to set up on the twilio client
|
6
|
+
def initialize
|
7
|
+
# Get an instance of the twilio client
|
8
|
+
@client = Twilio::REST::Client.new(
|
9
|
+
Minicron.config['alerts']['sms']['twilio']['account_sid'],
|
10
|
+
Minicron.config['alerts']['sms']['twilio']['auth_token']
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Return the message for an alert
|
15
|
+
#
|
16
|
+
# @option options [Minicron::Hub::Job] job a job instance
|
17
|
+
# @option options [String] kind 'fail' or 'miss'
|
18
|
+
# @option options [Integer, nil] schedule_id only applies to 'miss' alerts
|
19
|
+
# @option options [Integer, nil] execution_id only used by 'fail' alerts
|
20
|
+
# @option options [Integer] job_id used to look up the job name for the alert message
|
21
|
+
# @option options [Time] expected_at when the schedule was expected to execute
|
22
|
+
# @option options [String] medium the medium to send the alert via
|
23
|
+
def get_message(options = {})
|
24
|
+
case options[:kind]
|
25
|
+
when 'miss'
|
26
|
+
"minicron alert - job missed!\nJob ##{options[:job_id]} failed to execute at its expected time: #{options[:expected_at]}"
|
27
|
+
when 'fail'
|
28
|
+
"minicron alert - job failed!\nExecution ##{options[:execution_id]} of Job ##{options[:job_id]} failed"
|
29
|
+
else
|
30
|
+
raise Exception, "The kind '#{options[:kind]} is not supported!"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Send an sms alert
|
35
|
+
#
|
36
|
+
# @param from [String]
|
37
|
+
# @param to [String]
|
38
|
+
# @param message [String]
|
39
|
+
def send(from, to, message)
|
40
|
+
@client.account.messages.create(
|
41
|
+
:from => from,
|
42
|
+
:to => to,
|
43
|
+
:body => message
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/minicron/cli.rb
ADDED
@@ -0,0 +1,367 @@
|
|
1
|
+
require 'pty'
|
2
|
+
require 'English'
|
3
|
+
require 'rainbow/ext/string'
|
4
|
+
require 'commander'
|
5
|
+
require 'minicron/constants'
|
6
|
+
require 'minicron/transport'
|
7
|
+
require 'minicron/transport/client'
|
8
|
+
require 'minicron/transport/server'
|
9
|
+
require 'minicron/monitor'
|
10
|
+
|
11
|
+
include Commander::UI
|
12
|
+
|
13
|
+
module Minicron
|
14
|
+
class CLI
|
15
|
+
# Function to the parse the config of the options passed to commands
|
16
|
+
#
|
17
|
+
# @param opts [Hash] The Commander provided options hash
|
18
|
+
def parse_config(opts)
|
19
|
+
# Parse the --config file options if it was passed
|
20
|
+
Minicron.parse_file_config(opts.config)
|
21
|
+
|
22
|
+
# Parse the cli options
|
23
|
+
Minicron.parse_cli_config(
|
24
|
+
'global' => {
|
25
|
+
'verbose' => opts.verbose,
|
26
|
+
'trace' => opts.trace
|
27
|
+
},
|
28
|
+
'cli' => {
|
29
|
+
'mode' => opts.mode,
|
30
|
+
'dry_run' => opts.dry_run
|
31
|
+
},
|
32
|
+
'server' => {
|
33
|
+
'host' => opts.host,
|
34
|
+
'port' => opts.port,
|
35
|
+
'path' => opts.path
|
36
|
+
}
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Used as a helper for yielding command output, returns it in a structured hash
|
41
|
+
#
|
42
|
+
# @param type [Symbol] The type of command output, currently one of :status, :command and :verbose
|
43
|
+
# @param output [String]
|
44
|
+
# @return [Hash]
|
45
|
+
def structured(type, output)
|
46
|
+
{ :type => type, :output => output }
|
47
|
+
end
|
48
|
+
|
49
|
+
# Sets up an instance of commander and runs it based on the argv param
|
50
|
+
#
|
51
|
+
# @param argv [Array] an array of arguments passed to the cli
|
52
|
+
# @yieldparam output [String] output from the cli
|
53
|
+
# @raise [ArgumentError] if no arguments are passed to the run cli command
|
54
|
+
# i.e when the argv param is ['run']. A second option (the command to execute)
|
55
|
+
# should be present in the array
|
56
|
+
def run(argv)
|
57
|
+
# replace ARGV with the contents of argv to aid testability
|
58
|
+
ARGV.replace(argv)
|
59
|
+
|
60
|
+
# Get an instance of commander
|
61
|
+
@cli = Commander::Runner.new
|
62
|
+
|
63
|
+
# Set some default otions on it
|
64
|
+
setup_cli
|
65
|
+
|
66
|
+
# Add the run command to the cli
|
67
|
+
add_run_cli_command { |output| yield output }
|
68
|
+
|
69
|
+
# Add the server command to the cli
|
70
|
+
add_server_cli_command
|
71
|
+
|
72
|
+
# Add the db command to the cli
|
73
|
+
add_db_cli_command
|
74
|
+
|
75
|
+
# And off we go!
|
76
|
+
@cli.run!
|
77
|
+
end
|
78
|
+
|
79
|
+
# Executes a command in a pseudo terminal and yields the output
|
80
|
+
#
|
81
|
+
# @param command [String] the command to execute e.g 'ls'
|
82
|
+
# @option options [String] mode ('line') the method to yield the
|
83
|
+
# command output. Either 'line' by line or 'char' by char.
|
84
|
+
# @option options [Boolean] verbose whether or not to output extra
|
85
|
+
# information for debugging purposes.
|
86
|
+
# @yieldparam output [String] output from the command execution
|
87
|
+
def run_command(command, options = {})
|
88
|
+
# Default the options
|
89
|
+
options[:mode] ||= 'line'
|
90
|
+
options[:verbose] ||= false
|
91
|
+
|
92
|
+
# Record the start time of the command
|
93
|
+
start = Time.now.utc
|
94
|
+
subtract_total = 0
|
95
|
+
|
96
|
+
# yield the start time
|
97
|
+
subtract = Time.now.utc
|
98
|
+
yield structured :status, "START #{start.strftime("%Y-%m-%d %H:%M:%S")}"
|
99
|
+
subtract_total += Time.now.utc - subtract
|
100
|
+
|
101
|
+
# Spawn a process to run the command
|
102
|
+
begin
|
103
|
+
PTY.spawn(command) do |stdout, stdin, pid|
|
104
|
+
|
105
|
+
# Output some debug info
|
106
|
+
if options[:verbose]
|
107
|
+
subtract = Time.now.utc
|
108
|
+
yield structured :verbose, '[minicron]'.colour(:magenta)
|
109
|
+
yield structured :verbose, ' started running '.colour(:blue) + "`#{command}`".colour(:yellow) + " at #{start}\n\n".colour(:blue)
|
110
|
+
subtract_total += Time.now.utc - subtract
|
111
|
+
end
|
112
|
+
|
113
|
+
begin
|
114
|
+
# Loop until data is no longer being sent to stdout
|
115
|
+
until stdout.eof?
|
116
|
+
# One character at a time or one line at a time?
|
117
|
+
output = options[:mode] == 'char' ? stdout.read(1) : stdout.readline
|
118
|
+
|
119
|
+
subtract = Time.now.utc
|
120
|
+
yield structured :command, output
|
121
|
+
subtract_total += Time.now.utc - subtract
|
122
|
+
end
|
123
|
+
# See https://github.com/ruby/ruby/blob/57fb2199059cb55b632d093c2e64c8a3c60acfbb/ext/pty/pty.c#L519
|
124
|
+
rescue Errno::EIO
|
125
|
+
ensure
|
126
|
+
# Force waiting for the process to finish so we can get the exit status
|
127
|
+
Process.wait pid
|
128
|
+
end
|
129
|
+
end
|
130
|
+
rescue Errno::ENOENT
|
131
|
+
exit_status = 1
|
132
|
+
|
133
|
+
fail Exception, "Running the command `#{command}` failed, are you sure it exists?"
|
134
|
+
ensure
|
135
|
+
# Record the time the command finished
|
136
|
+
finish = Time.now.utc - subtract_total
|
137
|
+
exit_status = $CHILD_STATUS.exitstatus ? $CHILD_STATUS.exitstatus : nil
|
138
|
+
|
139
|
+
# yield the finish time and exit status
|
140
|
+
yield structured :status, "FINISH #{finish.strftime("%Y-%m-%d %H:%M:%S")}"
|
141
|
+
yield structured :status, "EXIT #{exit_status}"
|
142
|
+
|
143
|
+
# Output some debug info
|
144
|
+
if options[:verbose]
|
145
|
+
yield structured :verbose, "\n" + "[minicron]".colour(:magenta)
|
146
|
+
yield structured :verbose, ' finished running '.colour(:blue) + "`#{command}`".colour(:yellow) + " at #{start}\n".colour(:blue)
|
147
|
+
yield structured :verbose, '[minicron]'.colour(:magenta)
|
148
|
+
yield structured :verbose, ' running '.colour(:blue) + "`#{command}`".colour(:yellow) + " took #{finish - start}s\n".colour(:blue)
|
149
|
+
yield structured :verbose, '[minicron]'.colour(:magenta)
|
150
|
+
yield structured :verbose, " `#{command}`".colour(:yellow) + ' finished with an exit status of '.colour(:blue)
|
151
|
+
yield structured :verbose, exit_status == 0 ? "#{exit_status}\n".colour(:green) : "#{exit_status}\n".colour(:red)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Whether or not coloured output of the rainbox gem is enabled, this is
|
157
|
+
# enabled by default
|
158
|
+
#
|
159
|
+
# @return [Boolean] whether rainbow is enabled or not
|
160
|
+
def coloured_output?
|
161
|
+
Rainbow.enabled
|
162
|
+
end
|
163
|
+
|
164
|
+
# Enable coloured terminal output from the rainbow gem, this is enabled
|
165
|
+
# by default
|
166
|
+
#
|
167
|
+
# @return [Boolean] whether rainbow is enabled or not
|
168
|
+
def enable_coloured_output!
|
169
|
+
Rainbow.enabled = true
|
170
|
+
end
|
171
|
+
|
172
|
+
# Disable coloured terminal output from the rainbow gem, this is enabled
|
173
|
+
# by default
|
174
|
+
#
|
175
|
+
# @return [Boolean] whether rainbow is enabled or not
|
176
|
+
def disable_coloured_output!
|
177
|
+
Rainbow.enabled = false
|
178
|
+
end
|
179
|
+
|
180
|
+
private
|
181
|
+
|
182
|
+
# Sets the basic options for a commander cli instance
|
183
|
+
def setup_cli
|
184
|
+
# basic information for the help menu
|
185
|
+
@cli.program :name, 'minicron'
|
186
|
+
@cli.program :help, 'Author', 'James White <dev.jameswhite+minicron@gmail.com>'
|
187
|
+
@cli.program :help, 'License', 'GPL v3'
|
188
|
+
@cli.program :version, Minicron::VERSION
|
189
|
+
@cli.program :description, 'cli for minicron; a system a to manage and monitor cron jobs'
|
190
|
+
|
191
|
+
# Set the default command to run
|
192
|
+
@cli.default_command :help
|
193
|
+
|
194
|
+
# Check if --trace was pased or not
|
195
|
+
if @cli.instance_variable_get(:@args).include? '--trace'
|
196
|
+
Minicron.config['global']['trace'] = true
|
197
|
+
end
|
198
|
+
|
199
|
+
# Add a global option for verbose mode
|
200
|
+
@cli.global_option '--verbose', "Turn on verbose mode. Default: #{Minicron.config['cli']['verbose']}" do
|
201
|
+
Minicron.config['global']['verbose'] = true
|
202
|
+
end
|
203
|
+
|
204
|
+
# Add a global option for passing the path to a config file
|
205
|
+
@cli.global_option '--config FILE', 'Set the config file to use'
|
206
|
+
end
|
207
|
+
|
208
|
+
# Setup a job by sending the SETUP command to the server
|
209
|
+
#
|
210
|
+
# @param command [String] the job command
|
211
|
+
# @param faye a faye client instance
|
212
|
+
# @return [Hash] the job_id and execution_id
|
213
|
+
def setup_job(command, faye)
|
214
|
+
# Get the fully qualified domain name of the currnet host
|
215
|
+
fqdn = `hostname -f`.strip
|
216
|
+
|
217
|
+
# Get the short hostname of the current host
|
218
|
+
hostname = `hostname -s`.strip
|
219
|
+
|
220
|
+
# Get the md5 hash for the job
|
221
|
+
job_hash = Minicron::Transport.get_job_hash(command, fqdn)
|
222
|
+
|
223
|
+
# Fire up eventmachine
|
224
|
+
faye.ensure_em_running
|
225
|
+
|
226
|
+
# Setup the job on the server
|
227
|
+
ids = faye.setup(job_hash, command, fqdn, hostname)
|
228
|
+
|
229
|
+
# Wait until we get the execution id
|
230
|
+
faye.ensure_delivery
|
231
|
+
|
232
|
+
# Return the ids
|
233
|
+
ids
|
234
|
+
end
|
235
|
+
|
236
|
+
# Add the `minicron db` command
|
237
|
+
def add_db_cli_command
|
238
|
+
@cli.command :db do |c|
|
239
|
+
c.syntax = 'minicron db [setup|dump]'
|
240
|
+
c.description = 'Loads or dumps the minicron database schema.'
|
241
|
+
|
242
|
+
c.action do |args, opts|
|
243
|
+
# Check that exactly one argument has been passed
|
244
|
+
if args.length != 1
|
245
|
+
fail ArgumentError, 'A valid command to run is required! See `minicron help db`'
|
246
|
+
end
|
247
|
+
|
248
|
+
# Parse the file and cli config options
|
249
|
+
parse_config(opts)
|
250
|
+
|
251
|
+
# These are inlined as we only need them in this use case
|
252
|
+
require 'rake'
|
253
|
+
require 'minicron/hub/app'
|
254
|
+
require 'sinatra/activerecord/rake'
|
255
|
+
|
256
|
+
# Setup the db
|
257
|
+
Minicron::Hub::App.setup_db
|
258
|
+
|
259
|
+
# Tell activerecord where the db folder is, it assumes it is in db/
|
260
|
+
Sinatra::ActiveRecordTasks.db_dir = 'lib/minicron/hub/db'
|
261
|
+
|
262
|
+
# Adjust the task name
|
263
|
+
task = args.first == 'setup' ? 'load' : args.first
|
264
|
+
|
265
|
+
# Run the task
|
266
|
+
Rake.application['db:schema:' + task].invoke
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# Add the `minicron server` command
|
272
|
+
def add_server_cli_command
|
273
|
+
@cli.command :server do |c|
|
274
|
+
c.syntax = 'minicron server'
|
275
|
+
c.description = 'Starts the minicron server.'
|
276
|
+
c.option '--host STRING', String, "The host for the server to listen on. Default: #{Minicron.config['server']['host']}"
|
277
|
+
c.option '--port STRING', Integer, "How port for the server to listed on. Default: #{Minicron.config['server']['port']}"
|
278
|
+
c.option '--path STRING', String, "The path on the host. Default: #{Minicron.config['server']['path']}"
|
279
|
+
|
280
|
+
c.action do |args, opts|
|
281
|
+
# Parse the file and @cli config options
|
282
|
+
parse_config(opts)
|
283
|
+
|
284
|
+
# Run the execution monitor (this runs in a separate thread)
|
285
|
+
monitor = Minicron::Monitor.new
|
286
|
+
monitor.start!
|
287
|
+
|
288
|
+
# Start the server!
|
289
|
+
server = Minicron::Transport::Server.new
|
290
|
+
server.start!(
|
291
|
+
Minicron.config['server']['host'],
|
292
|
+
Minicron.config['server']['port'],
|
293
|
+
Minicron.config['server']['path']
|
294
|
+
)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
# Add the `minicron run [command]` command
|
300
|
+
# @yieldparam output [String] output from the cli
|
301
|
+
def add_run_cli_command
|
302
|
+
# Add the run command to the cli
|
303
|
+
@cli.command :run do |c|
|
304
|
+
c.syntax = "minicron run 'command -option value'"
|
305
|
+
c.description = 'Runs the command passed as an argument.'
|
306
|
+
c.option '--mode STRING', String, "How to capture the command output, each 'line' or each 'char'? Default: #{Minicron.config['cli']['mode']}"
|
307
|
+
c.option '--dry-run', "Run the command without sending the output to the server. Default: #{Minicron.config['cli']['dry_run']}"
|
308
|
+
|
309
|
+
c.action do |args, opts|
|
310
|
+
# Check that exactly one argument has been passed
|
311
|
+
if args.length != 1
|
312
|
+
fail ArgumentError, 'A valid command to run is required! See `minicron help run`'
|
313
|
+
end
|
314
|
+
|
315
|
+
# Parse the file and cli config options
|
316
|
+
parse_config(opts)
|
317
|
+
|
318
|
+
begin
|
319
|
+
# Set up the job and get the job and execution ids
|
320
|
+
unless Minicron.config['cli']['dry_run']
|
321
|
+
# Get a faye instance so we can send data about the job
|
322
|
+
faye = Minicron::Transport::Client.new(
|
323
|
+
Minicron.config['client']['scheme'],
|
324
|
+
Minicron.config['client']['host'],
|
325
|
+
Minicron.config['client']['port'],
|
326
|
+
Minicron.config['client']['path']
|
327
|
+
)
|
328
|
+
|
329
|
+
# Set up the job and get the jexecution and job ids back from the server
|
330
|
+
ids = setup_job(args.first, faye)
|
331
|
+
end
|
332
|
+
|
333
|
+
# Execute the command and yield the output
|
334
|
+
run_command(args.first, :mode => Minicron.config['cli']['mode'], :verbose => Minicron.config['global']['verbose']) do |output|
|
335
|
+
# We need to handle the yielded output differently based on it's type
|
336
|
+
case output[:type]
|
337
|
+
when :status
|
338
|
+
unless Minicron.config['cli']['dry_run']
|
339
|
+
faye.send(:job_id => ids[:job_id], :execution_id => ids[:execution_id], :type => :status, :message => output[:output])
|
340
|
+
end
|
341
|
+
when :command
|
342
|
+
unless Minicron.config['cli']['dry_run']
|
343
|
+
faye.send(:job_id => ids[:job_id], :execution_id => ids[:execution_id], :type => :output, :message => output[:output])
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
yield output[:output] unless output[:type] == :status
|
348
|
+
end
|
349
|
+
rescue Exception => e
|
350
|
+
# Send the exception message to the server and yield it
|
351
|
+
unless Minicron.config['cli']['dry_run']
|
352
|
+
faye.send(:job_id => ids[:job_id], :execution_id => ids[:execution_id], :type => :output, :message => e.message)
|
353
|
+
end
|
354
|
+
|
355
|
+
fail e
|
356
|
+
ensure
|
357
|
+
# Ensure that all messages are delivered and that we
|
358
|
+
unless Minicron.config['cli']['dry_run']
|
359
|
+
faye.ensure_delivery
|
360
|
+
faye.tidy_up
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|