minicron 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +187 -0
  4. data/Rakefile +17 -0
  5. data/bin/minicron +26 -0
  6. data/lib/minicron.rb +179 -0
  7. data/lib/minicron/alert.rb +115 -0
  8. data/lib/minicron/alert/email.rb +50 -0
  9. data/lib/minicron/alert/pagerduty.rb +39 -0
  10. data/lib/minicron/alert/sms.rb +47 -0
  11. data/lib/minicron/cli.rb +367 -0
  12. data/lib/minicron/constants.rb +7 -0
  13. data/lib/minicron/cron.rb +192 -0
  14. data/lib/minicron/hub/app.rb +132 -0
  15. data/lib/minicron/hub/assets/app/application.js +151 -0
  16. data/lib/minicron/hub/assets/app/components/schedules.js +280 -0
  17. data/lib/minicron/hub/assets/app/controllers/executions.js +35 -0
  18. data/lib/minicron/hub/assets/app/controllers/hosts.js +129 -0
  19. data/lib/minicron/hub/assets/app/controllers/jobs.js +109 -0
  20. data/lib/minicron/hub/assets/app/controllers/schedules.js +80 -0
  21. data/lib/minicron/hub/assets/app/helpers.js +22 -0
  22. data/lib/minicron/hub/assets/app/models/execution.js +13 -0
  23. data/lib/minicron/hub/assets/app/models/host.js +15 -0
  24. data/lib/minicron/hub/assets/app/models/job.js +15 -0
  25. data/lib/minicron/hub/assets/app/models/job_execution_output.js +11 -0
  26. data/lib/minicron/hub/assets/app/models/schedule.js +32 -0
  27. data/lib/minicron/hub/assets/app/router.js +31 -0
  28. data/lib/minicron/hub/assets/app/routes/executions.js +36 -0
  29. data/lib/minicron/hub/assets/app/routes/hosts.js +42 -0
  30. data/lib/minicron/hub/assets/app/routes/index.js +9 -0
  31. data/lib/minicron/hub/assets/app/routes/jobs.js +52 -0
  32. data/lib/minicron/hub/assets/app/routes/schedules.js +37 -0
  33. data/lib/minicron/hub/assets/css/bootswatch.min.css +9 -0
  34. data/lib/minicron/hub/assets/css/main.scss +323 -0
  35. data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  36. data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.svg +229 -0
  37. data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  38. data/lib/minicron/hub/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  39. data/lib/minicron/hub/assets/fonts/lato-bold-700.woff +0 -0
  40. data/lib/minicron/hub/assets/fonts/lato-italic-400.woff +0 -0
  41. data/lib/minicron/hub/assets/fonts/lato-regular-400.woff +0 -0
  42. data/lib/minicron/hub/assets/js/ansi_up-1.1.1.min.js +6 -0
  43. data/lib/minicron/hub/assets/js/auth/ember-auth-9.0.7.min.js +2 -0
  44. data/lib/minicron/hub/assets/js/auth/ember-auth-request-jquery-1.0.3.min.js +1 -0
  45. data/lib/minicron/hub/assets/js/bootstrap-3.1.1.min.js +6 -0
  46. data/lib/minicron/hub/assets/js/ember-1.4.1.min.js +18 -0
  47. data/lib/minicron/hub/assets/js/ember-data-1.0.0-beta.7.f87cba88.min.js +10 -0
  48. data/lib/minicron/hub/assets/js/faye-browser-1.0.1.min.js +2 -0
  49. data/lib/minicron/hub/assets/js/handlebars-1.3.0.min.js +29 -0
  50. data/lib/minicron/hub/assets/js/jquery-2.1.0.min.js +4 -0
  51. data/lib/minicron/hub/assets/js/moment-2.5.1.min.js +7 -0
  52. data/lib/minicron/hub/controllers/api/executions.rb +34 -0
  53. data/lib/minicron/hub/controllers/api/hosts.rb +150 -0
  54. data/lib/minicron/hub/controllers/api/job_execution_outputs.rb +30 -0
  55. data/lib/minicron/hub/controllers/api/jobs.rb +118 -0
  56. data/lib/minicron/hub/controllers/api/schedule.rb +184 -0
  57. data/lib/minicron/hub/controllers/index.rb +5 -0
  58. data/lib/minicron/hub/db/schema.rb +98 -0
  59. data/lib/minicron/hub/db/schema.sql +158 -0
  60. data/lib/minicron/hub/models/alert.rb +7 -0
  61. data/lib/minicron/hub/models/execution.rb +8 -0
  62. data/lib/minicron/hub/models/host.rb +7 -0
  63. data/lib/minicron/hub/models/job.rb +18 -0
  64. data/lib/minicron/hub/models/job_execution_output.rb +7 -0
  65. data/lib/minicron/hub/models/schedule.rb +25 -0
  66. data/lib/minicron/hub/serializers/execution.rb +75 -0
  67. data/lib/minicron/hub/serializers/host.rb +57 -0
  68. data/lib/minicron/hub/serializers/job.rb +104 -0
  69. data/lib/minicron/hub/serializers/job_execution_output.rb +48 -0
  70. data/lib/minicron/hub/serializers/schedule.rb +68 -0
  71. data/lib/minicron/hub/views/handlebars/application.erb +51 -0
  72. data/lib/minicron/hub/views/handlebars/errors.erb +29 -0
  73. data/lib/minicron/hub/views/handlebars/executions.erb +79 -0
  74. data/lib/minicron/hub/views/handlebars/hosts.erb +205 -0
  75. data/lib/minicron/hub/views/handlebars/jobs.erb +203 -0
  76. data/lib/minicron/hub/views/handlebars/loading.erb +3 -0
  77. data/lib/minicron/hub/views/handlebars/schedules.erb +354 -0
  78. data/lib/minicron/hub/views/index.erb +7 -0
  79. data/lib/minicron/hub/views/layouts/app.erb +15 -0
  80. data/lib/minicron/monitor.rb +116 -0
  81. data/lib/minicron/transport.rb +15 -0
  82. data/lib/minicron/transport/client.rb +80 -0
  83. data/lib/minicron/transport/faye/client.rb +103 -0
  84. data/lib/minicron/transport/faye/extensions/job_handler.rb +184 -0
  85. data/lib/minicron/transport/faye/server.rb +58 -0
  86. data/lib/minicron/transport/server.rb +62 -0
  87. data/lib/minicron/transport/ssh.rb +51 -0
  88. data/spec/invalid_config.toml +2 -0
  89. data/spec/minicron/cli_spec.rb +154 -0
  90. data/spec/minicron/transport/client_spec.rb +8 -0
  91. data/spec/minicron/transport/faye/client_spec.rb +53 -0
  92. data/spec/minicron/transport/server_spec.rb +70 -0
  93. data/spec/minicron/transport_spec.rb +13 -0
  94. data/spec/minicron_spec.rb +133 -0
  95. data/spec/spec_helper.rb +33 -0
  96. data/spec/valid_config.toml +48 -0
  97. 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
@@ -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