mutx 0.2.2 → 0.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5e6d51098762a59058ac78f8d555d4b1e1dde841
4
- data.tar.gz: 837b24fa28e238b47c02306fc7d3fe51082d2b96
3
+ metadata.gz: 59c6ec4325709306828982280037d2b948a596d6
4
+ data.tar.gz: 142bbcdf1c0f8153f909235e5b5e750cb0681bf5
5
5
  SHA512:
6
- metadata.gz: 033846539b9d85ba30524db05c7b0962e15518efc3165696e9e87fc523ad1cef1bdfeea2b96403c707928149cc49c882972d4a97aa68253f6a513a093c51b08c
7
- data.tar.gz: 7a29987b8674b5d012c07fad2bffdc049e6c052574e82aacd386b03d1f89a5607a73fbabefd2f64dbabd8739db4bd556460c3264616b196ac59b74a2d56da1f6
6
+ metadata.gz: 4ef36addee27851f1b8fb2fb6c85beba0cfe3326486cb0f256bcdc83ab0a30fe372752344286ca123bf33c015b5cfccd97c8750c53e082d559c9e1741a46a827
7
+ data.tar.gz: e11d4425d9b651ee628cec0b52c823e907b61fdc5bbc5192326e0b4a36f6e36beea99e9a347c1e3e79de49921fdb88847ce4bdd1596f7bc4b3e19b9ffe3fadb5
@@ -0,0 +1,45 @@
1
+ require 'colorize'
2
+ module Mutx
3
+ class CreateAlert < Thor::Group
4
+
5
+ include Thor::Actions
6
+
7
+ desc "Create an Alert in Mutx"
8
+ argument :name, type: :string, desc: 'alert name'
9
+
10
+ def self.source_root
11
+ File.dirname(__FILE__) + "/templates/"
12
+ end
13
+
14
+ def self.alert_folder
15
+ "#{Dir.pwd}/alerts"
16
+ end
17
+
18
+ def self.alert_filename(alert_name)
19
+ File.join(self.alert_folder, "#{alert_name}_alert.rb")
20
+ end
21
+
22
+ def check_alert_folder
23
+ unless Dir.exist? self.class.alert_folder
24
+ say "creating alert folder: #{self.class.alert_folder}".green
25
+ empty_directory(self.class.alert_folder)
26
+ else
27
+ say "alert folder exists ( #{self.class.alert_folder} )".green
28
+ end
29
+ end
30
+
31
+ def check_not_exist_alert
32
+ raise Error, "alert exists ( #{ self.class.alert_filename(name) } )" if File.exists? self.class.alert_filename(name)
33
+ end
34
+
35
+ def create_alarm
36
+ template 'mutx_alert.rb.tt', self.class.alert_filename(name)
37
+ end
38
+
39
+ def finish_message
40
+ say 'Alert created!'.green
41
+ say "please, edit: #{self.class.alert_filename(name)}".green
42
+ end
43
+
44
+ end
45
+ end
@@ -3,6 +3,7 @@
3
3
  require 'mutx'
4
4
  require 'sidekiq'
5
5
  require 'sidekiq/web'
6
+ require 'sidekiq/cron/web'
6
7
 
7
8
  #Sidekiq.configure_client do |config|
8
9
  # config.redis = { :url => 'redis://10.211.15.195:6379/0' }
@@ -0,0 +1,10 @@
1
+ # TODO cron: * * * * *
2
+ # TODO email: a email or emails
3
+ # TODO telegram: a group id
4
+
5
+ require 'mutx'
6
+ include Mutx::Alert::Script
7
+
8
+ # put your code here!
9
+
10
+ # write success! warning! or critical! to finish script
data/lib/mutx.rb CHANGED
@@ -13,6 +13,7 @@ require 'byebug'
13
13
  require 'digest'
14
14
  require 'basica'
15
15
  require 'sidetiq'
16
+ require 'sidekiq-cron'
16
17
 
17
18
  require_rel 'mutx'
18
19
  require_rel 'generators'
@@ -81,6 +82,11 @@ module Mutx
81
82
  Mutx::Commands.reset_tasks
82
83
  end
83
84
 
85
+ desc 'create_alert NAME', "Create a new alert"
86
+ def create_alert(name)
87
+ Mutx::Commands.create_alert(name)
88
+ end
89
+
84
90
  desc "Say bye to mutx", ""
85
91
  def bye
86
92
  if yes? "Are you sure to say bye to Mutx? (yes/no)"
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+ require 'sidekiq'
3
+
4
+ module Mutx
5
+ module Workers
6
+ class AlertsWorker
7
+ include Sidekiq::Worker
8
+
9
+ sidekiq_options retry: false
10
+
11
+ def perform(args)
12
+ stringio = StringIO.new
13
+ @alert = Alert.find(name: args['name'])
14
+ status = nil
15
+ begin
16
+ PTY.spawn("ruby #{args['path']}") do |stdout, stdin, pid|
17
+ begin
18
+ stdout.each do |line|
19
+ stringio.puts line
20
+ end
21
+ rescue Errno::EIO
22
+ ensure
23
+ Process.wait pid
24
+ status = $?.exitstatus
25
+ end
26
+ end
27
+ rescue => e
28
+ logger.debug(e.message)
29
+ logger.debug(e.backtrace)
30
+ raise e
31
+ ensure
32
+ @alert.update_status(status, info: stringio.string)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -30,9 +30,9 @@ module Mutx
30
30
 
31
31
  efective_command = []
32
32
  efective_command << Mutx::Support::Configuration.headless? if result.gui_task?
33
+ efective_command << result.custom_params_values
33
34
  efective_command << result.command
34
35
  efective_command << "-f pretty -f html -o mutx/temp/#{result.mutx_report_file_name}" if result.is_cucumber?
35
- efective_command << result.custom_params_values
36
36
  efective_command << "_id=#{result.id}" # to use inside execution the possibility to add information to the result
37
37
  puts "[#{result.id}]| Command: #{efective_command.join(" ")}"
38
38
  result.mutx_command = efective_command.join(" ")
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+ require 'telegramsender'
3
+
4
+ module Mutx
5
+ module Workers
6
+ class Notificator
7
+ include Sidekiq::Worker
8
+
9
+ def perform(type, destination, args= {})
10
+ simbolized = args.map { |k, v| [k.to_sym, v] }.to_h
11
+ self.send(type.to_sym, destination, **simbolized)
12
+ end
13
+
14
+ def telegram(group_id, message: '')
15
+ TelegramSender.send_message(group_id, message)
16
+ end
17
+
18
+ def email(mail_to, subject: '', body: '', attachment: nil)
19
+ # TODO
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+ module Mutx
3
+ module Commands
4
+ def self.create_alert(name)
5
+ begin
6
+ Mutx::CreateAlert.start([name])
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+
2
+ module Mutx
3
+ class Notification
4
+
5
+ def self.send_email(destination, subject: nil, body: nil, attachment: nil)
6
+ self.send(:email, destination, subject: subject, body: body, attachment: attachment)
7
+ end
8
+
9
+ def self.send_telegram(destination, message: '')
10
+ self.send(:telegram, destination, message: message)
11
+ end
12
+
13
+ def self.send(type, destination, options={})
14
+ Mutx::Workers::Notificator.perform_async(type, destination, options)
15
+ end
16
+
17
+ end
18
+ end
@@ -54,6 +54,11 @@ module Mutx
54
54
  tests_run: '/tests/:test_name/run',
55
55
  tests_status: '/tests/:test_name/status',
56
56
 
57
+ alerts_index: '/alerts',
58
+ alerts_show: '/alerts/:alert_name',
59
+ alerts_on: '/alerts/:alert_name/run',
60
+ alerts_off: '/alerts/:alert_name/stop',
61
+
57
62
  features_index: '/features',
58
63
  features_file: '/features/file',
59
64
 
@@ -0,0 +1,174 @@
1
+ module Mutx
2
+ class Alert
3
+
4
+ module Script
5
+
6
+ def ok!
7
+ puts "Result: OK"
8
+ exit STATUS[:ok]
9
+ end
10
+
11
+ def skip!
12
+ puts "Result: SKIP"
13
+ exit STATUS[:skip]
14
+ end
15
+
16
+ def unknown!
17
+ puts "Result: UNKNOWN"
18
+ exit STATUS[:unknown]
19
+ end
20
+
21
+ def warning!
22
+ puts "Result: WARNING"
23
+ exit STATUS[:warning]
24
+ end
25
+
26
+ def critical!
27
+ puts "Result: CRITICAL"
28
+ exit STATUS[:critical]
29
+ end
30
+
31
+ end
32
+
33
+ ALERT_FOLDER = File.join("#{Dir.pwd}", 'alerts')
34
+
35
+ STATUS = {
36
+ ok: 0,
37
+ unknown: 1,
38
+ skip: 2,
39
+ warning: 3,
40
+ critical: 4
41
+ }
42
+
43
+ def self.all
44
+ alerts = Dir.entries(ALERT_FOLDER).select { |file|
45
+ file.match(/_alert.rb$/)
46
+ }.map {|file| self.new(file) }
47
+ end
48
+
49
+ def self.find(args={})
50
+ if args.is_a? Hash
51
+ filename = "#{args[:name]}_alert.rb"
52
+ if File.exists?(File.join(ALERT_FOLDER, filename))
53
+ return self.new(filename)
54
+ else
55
+ return nil
56
+ end
57
+ else
58
+ return nil
59
+ end
60
+ end
61
+
62
+ attr_reader :filename, :attributes, :job, :notification
63
+
64
+ def initialize(filename)
65
+ @filename = filename
66
+ extract_info
67
+ @enqueue = true
68
+ @job = Sidekiq::Cron::Job.find(name) || ((@enqueue = false) || create_job )
69
+ end
70
+
71
+ def name
72
+ filename.gsub('_alert.rb', '')
73
+ end
74
+
75
+ def email
76
+ attributes['email']
77
+ end
78
+
79
+ def telegram
80
+ attributes['telegram']
81
+ end
82
+
83
+ def slack
84
+ attributes['slack']
85
+ end
86
+
87
+ def cron
88
+ attributes['cron']
89
+ end
90
+
91
+ def last_enqueue
92
+ @job.last_enqueue_time
93
+ end
94
+
95
+ def enqueue?
96
+ @enqueue
97
+ end
98
+
99
+ def on!
100
+ if @job.valid?
101
+ @job.save
102
+ @enqueue = true
103
+ end
104
+ return self.enqueue?
105
+ end
106
+
107
+ def off!
108
+ @job.destroy
109
+ @enqueue = false
110
+ end
111
+
112
+ def status
113
+ STATUS.invert[self.result.to_i] || :unknown
114
+ end
115
+
116
+ def update_status(a_new_status, info: nil)
117
+ last_result = self.result
118
+ return if ((last_result.to_s == a_new_status.to_s) or (a_new_result.to_i == STATUS[:skip]))
119
+ self.result = a_new_status
120
+ notify(info) if last_result
121
+ end
122
+
123
+ def result
124
+ Sidekiq.redis do |redis|
125
+ redis.get("alerts:#{name}")
126
+ end
127
+ end
128
+
129
+ def result=(value)
130
+ Sidekiq.redis do |redis|
131
+ redis.set("alerts:#{name}", value.to_s)
132
+ end
133
+ end
134
+
135
+ private
136
+ def extract_info
137
+ content = File.read(File.join(ALERT_FOLDER, filename))
138
+ lines = content.split("\n").select {|line| line.match(/^\s*\#\s\w[\w_]+\:.+/) && !line.match(/TODO/)}
139
+ attributes = lines.map{ |line| line.gsub(/^\s*\#/,'').split(':',2).map(&:strip) }
140
+ @attributes = Hash[attributes]
141
+ @notification = @attributes.select do |k,v|
142
+ [:email, :slack, :telegram].include?(k.to_sym)
143
+ end
144
+ end
145
+
146
+ def create_job
147
+ Sidekiq::Cron::Job.new(name: name,
148
+ cron: attributes['cron'],
149
+ class: 'Mutx::Workers::AlertsWorker',
150
+ args: {
151
+ name: name,
152
+ file: filename,
153
+ path: File.join(ALERT_FOLDER, filename),
154
+ email: attributes['email']
155
+ })
156
+ end
157
+
158
+ def notify(info)
159
+ notify_telegram(self.telegram, info) if self.telegram
160
+ notify_email(self.email, info) if self.email
161
+ end
162
+
163
+ def notify_telegram(group_id, info)
164
+ return unless group_id
165
+ Notification.send_telegram(group_id, message: "Alert #{name} is #{status.upcase}")
166
+ Notification.send_telegram(group_id, message: info)
167
+ end
168
+
169
+ def notify_email(mail_to, info)
170
+ return unless mail_to
171
+ Notification.send_email(mail_to, subject: "Alert #{name} is #{status.upcase}", body: info)
172
+ end
173
+ end
174
+ end
data/lib/mutx/routes.rb CHANGED
@@ -36,6 +36,7 @@ module Mutx
36
36
  res.redirect path_for(:tasks_index)
37
37
  end
38
38
  on('admin') { run Mutx::Routes::Admin::Routes }
39
+ on('alerts') { run Mutx::Routes::Alerts::Routes }
39
40
  on('tasks') { run Mutx::Routes::Tasks::Routes }
40
41
  on('tests') { run Mutx::Routes::Tests::Routes }
41
42
  on('task-results') { run Mutx::Routes::TaskResults::Routes }
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+
3
+ module Mutx
4
+ module Routes
5
+ module Alerts
6
+ class Routes < App
7
+ define do
8
+ on get do
9
+ on ":alert_name" do |alert_name|
10
+ res.write view('Alert', alert: Alert.find(name: alert_name))
11
+ end
12
+
13
+ on root do
14
+ res.write view('Alerts', alerts: Alert.all)
15
+ end
16
+ end
17
+
18
+ on post do
19
+ on ':alert_name/run' do |alert_name|
20
+ alert = Alert.find(name: alert_name)
21
+ if alert.on!
22
+ flash[:info] = "Alert add success"
23
+ else
24
+ flash[:error] = alert.job.errors.join(', ')
25
+ end
26
+ res.redirect path_for(:alerts_index)
27
+ end
28
+
29
+ on ':alert_name/stop' do |alert_name|
30
+ alert = Alert.find(name: alert_name)
31
+ alert.off!
32
+ flash[:info] = "Alert off success"
33
+ res.redirect path_for(:alerts_index)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
data/lib/mutx/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mutx
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
3
3
  end
@@ -0,0 +1,45 @@
1
+ <td>
2
+ {{ alert.name }}
3
+ </td>
4
+ <td>
5
+ {{ alert.cron }}
6
+ </td>
7
+ <td>
8
+ % alert.notification.each do |type, destination|
9
+ <b>{{ type}}:</b> {{destination}}<br/>
10
+ % end
11
+ </td>
12
+
13
+ % if alert.enqueue?
14
+ <td>
15
+ <span class="label label-success"> Running at {{ alert.job.cron }}</span>
16
+ </td>
17
+
18
+ <td>
19
+ {{ alert.last_enqueue.strftime("at %I:%M%p") if alert.last_enqueue }}
20
+ </td>
21
+
22
+ <td>
23
+ <span class="label label-{{ { success: 'success', warning: 'warning', critical: 'danger', unknown: 'primary' }[alert.status] }}"> {{ alert.status }} </span>
24
+
25
+ </td>
26
+
27
+ <td>
28
+ <form name="{{ alert.name }}" method="POST" action="{{ path_for(:alerts_off, alert_name: alert.name )}}" >
29
+
30
+ <button type="submit">{{ Mutx::View.icon_for("off") }}</button>
31
+ </form>
32
+ </td>
33
+ % else
34
+ <td>
35
+ <span class="label label-danger"> Stopped </span>
36
+ </td>
37
+
38
+ <td/>
39
+ <td/>
40
+ <td>
41
+ <form name="{{ alert.name }}" method="POST" action="{{ path_for(:alerts_on, alert_name: alert.name)}}" >
42
+ <button type="submit">{{ Mutx::View.icon_for("on") }}</button>
43
+ </form>
44
+ </td>
45
+ % end
@@ -0,0 +1,25 @@
1
+ <div class="panel panel-default">
2
+ <div class="panel-heading">
3
+ <h4>{{section.capitalize}}</h4>
4
+ </div>
5
+ <table class="table table-striped table-hover">
6
+ <thead>
7
+ <tr>
8
+ <th>Name</th>
9
+ <th>Cron</th>
10
+ <th>Notificate to</th>
11
+ <th>Status</th>
12
+ <th>Last Exec.</th>
13
+ <th>Last Result</th>
14
+ <th/>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+ % alerts.each do |alert|
19
+ <tr>
20
+ {{ partial('alerts/_alert', alert: alert) }}
21
+ </tr>
22
+ % end
23
+ </tbody>
24
+ </table>
25
+ </div>
@@ -0,0 +1,8 @@
1
+ {{alert.name}}
2
+ <br/>
3
+
4
+ {{alert.filename}}
5
+
6
+ <br/>
7
+
8
+ {{alert.attributes}}
@@ -24,6 +24,9 @@ module Mutx
24
24
  'Tasks' => "tasks/index",
25
25
  'Task' => "tasks/show",
26
26
 
27
+ 'Alerts' => 'alerts/index',
28
+ 'Alert' => 'alerts/show',
29
+
27
30
  'Task Results' => 'task_results/index',
28
31
 
29
32
  "Results"=> "results/index",
data/mutx.gemspec CHANGED
@@ -42,6 +42,7 @@ Gem::Specification.new do |spec|
42
42
  spec.add_dependency 'basica'
43
43
  spec.add_dependency 'sidetiq'
44
44
  spec.add_dependency 'chronic'
45
+ spec.add_dependency 'sidekiq-cron'
45
46
  #spec.add_dependency 'zip'
46
47
 
47
48
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Rodriguez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-07 00:00:00.000000000 Z
11
+ date: 2017-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -304,6 +304,20 @@ dependencies:
304
304
  - - ">="
305
305
  - !ruby/object:Gem::Version
306
306
  version: '0'
307
+ - !ruby/object:Gem::Dependency
308
+ name: sidekiq-cron
309
+ requirement: !ruby/object:Gem::Requirement
310
+ requirements:
311
+ - - ">="
312
+ - !ruby/object:Gem::Version
313
+ version: '0'
314
+ type: :runtime
315
+ prerelease: false
316
+ version_requirements: !ruby/object:Gem::Requirement
317
+ requirements:
318
+ - - ">="
319
+ - !ruby/object:Gem::Version
320
+ version: '0'
307
321
  - !ruby/object:Gem::Dependency
308
322
  name: bundler
309
323
  requirement: !ruby/object:Gem::Requirement
@@ -375,6 +389,7 @@ files:
375
389
  - img/mutx_logo.svg
376
390
  - lib/.DS_Store
377
391
  - lib/generators/.DS_Store
392
+ - lib/generators/create_alert.rb
378
393
  - lib/generators/task_rack.rb
379
394
  - lib/generators/templates/.DS_Store
380
395
  - lib/generators/templates/Gemfile.tt
@@ -384,6 +399,7 @@ files:
384
399
  - lib/generators/templates/cronned_task.rb.tt
385
400
  - lib/generators/templates/mutx.conf.tt
386
401
  - lib/generators/templates/mutx.log.tt
402
+ - lib/generators/templates/mutx_alert.rb.tt
387
403
  - lib/generators/templates/mutx_body_template.html.erb
388
404
  - lib/generators/templates/mutx_body_template.html.erb.zip
389
405
  - lib/generators/templates/mutx_template.html.erb
@@ -407,15 +423,18 @@ files:
407
423
  - lib/mutx/background_jobs/.DS_Store
408
424
  - lib/mutx/background_jobs/sidekiq.rb
409
425
  - lib/mutx/background_jobs/workers/.DS_Store
426
+ - lib/mutx/background_jobs/workers/alerts_worker.rb
410
427
  - lib/mutx/background_jobs/workers/connectivity_check.rb
411
428
  - lib/mutx/background_jobs/workers/email_sender.rb
412
429
  - lib/mutx/background_jobs/workers/executor.rb
413
430
  - lib/mutx/background_jobs/workers/garbage_cleaner.rb
414
431
  - lib/mutx/background_jobs/workers/listener.rb
415
432
  - lib/mutx/background_jobs/workers/mutx_cron.rb
433
+ - lib/mutx/background_jobs/workers/notificator.rb
416
434
  - lib/mutx/background_jobs/workers/update_started.rb
417
435
  - lib/mutx/commands/.DS_Store
418
436
  - lib/mutx/commands/bye.rb
437
+ - lib/mutx/commands/create_alert.rb
419
438
  - lib/mutx/commands/help.rb
420
439
  - lib/mutx/commands/install.rb
421
440
  - lib/mutx/commands/reset.rb
@@ -438,7 +457,9 @@ files:
438
457
  - lib/mutx/lib/middlewares/flash_middleware.rb
439
458
  - lib/mutx/lib/middlewares/logger_middleware.rb
440
459
  - lib/mutx/lib/monkey_patch.rb
460
+ - lib/mutx/lib/notification.rb
441
461
  - lib/mutx/lib/paths.rb
462
+ - lib/mutx/models/alert.rb
442
463
  - lib/mutx/platforms/ruby.rb
443
464
  - lib/mutx/public/css/bootstrap.min.css
444
465
  - lib/mutx/public/css/font-awesome.min.css
@@ -456,6 +477,7 @@ files:
456
477
  - lib/mutx/routes/admin_routes/custom_params_routes.rb
457
478
  - lib/mutx/routes/admin_routes/repositories_routes.rb
458
479
  - lib/mutx/routes/admin_routes/tasks_routes.rb
480
+ - lib/mutx/routes/alerts_routes.rb
459
481
  - lib/mutx/routes/api_routes.rb
460
482
  - lib/mutx/routes/api_routes/custom_params_routes.rb
461
483
  - lib/mutx/routes/api_routes/input_routes.rb
@@ -520,6 +542,9 @@ files:
520
542
  - lib/mutx/view/admin/tasks/index.mote
521
543
  - lib/mutx/view/admin/tasks/new.mote
522
544
  - lib/mutx/view/admin/tasks/show.mote
545
+ - lib/mutx/view/alerts/_alert.mote
546
+ - lib/mutx/view/alerts/index.mote
547
+ - lib/mutx/view/alerts/show.mote
523
548
  - lib/mutx/view/body.mote
524
549
  - lib/mutx/view/custom-params/_custom_params.mote
525
550
  - lib/mutx/view/custom-params/types/json.mote