notifu 1.2

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e84a8d91a613dee08b4ebfa63f7c05082c4230d8
4
+ data.tar.gz: c0bf2890e4e519adc62b6f76b553fb706451146c
5
+ SHA512:
6
+ metadata.gz: 9ea47dec858e01b1dcea6586a29a491a0fc5fd0cb98731f0308bd010fe51eae593b4f3f092d454b2ef0d02336b495eea67197c58034bc73ada6751fe2f77bffd
7
+ data.tar.gz: b212ae242588fea5fc7b9ff199fa0776337b34ab0c5ca3afe24498eb967ae972b7076c4476122debbdf7f653b27111687a01329d8e4953a993d463752450a552
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ path = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
4
+ $basepath = '/' + File.dirname(path).split('/')[1..-2].join('/') + '/lib/notifu/'
5
+ $actorpath = $basepath + "actors/"
6
+ # $sidekiq_bin = $basepath.sub(/app\//, '') + ".rvm/wrappers/notifu/sidekiq"
7
+ $sidekiq_bin = "sidekiq"
8
+
9
+ require 'notifu'
10
+
11
+ Notifu::CONFIG = Notifu::Config.new.get
12
+
13
+ Ohm.redis = Redic.new Notifu::CONFIG[:redis_data]
14
+
15
+ Notifu::CLI::Root.start(ARGV)
@@ -0,0 +1,12 @@
1
+ require 'yaml'
2
+ require 'json'
3
+ require 'thor'
4
+ require 'ohm'
5
+ require "notifu/mixins"
6
+ require "notifu/util"
7
+ require "notifu/config"
8
+ require "notifu/logger"
9
+ require "notifu/model"
10
+ require "notifu/cli/service"
11
+ require "notifu/cli/object"
12
+ require "notifu/cli"
@@ -0,0 +1,41 @@
1
+ module Notifu
2
+ module Actors
3
+ class GammuSmsBridge < Notifu::Actor
4
+
5
+ self.name = "gammu_sms_bridge"
6
+ self.desc = "Old-school NetCat-like SMS bridge to Gammu"
7
+ self.retry = 3
8
+
9
+ def act
10
+ data = OpenStruct.new({
11
+ notifu_id: self.issue.notifu_id,
12
+ host: self.issue.host,
13
+ message: self.issue.message,
14
+ service: self.issue.service,
15
+ status: self.issue.code.to_state,
16
+ first_event: Time.at(self.issue.time_created.to_i),
17
+ duration: (Time.now.to_i - self.issue.time_created.to_i).duration,
18
+ occurrences_count: self.issue.occurrences_count,
19
+ occurrences_trigger: self.issue.occurrences_trigger
20
+ })
21
+ message = ERB.new(self.template).result(data.instance_eval {binding})
22
+
23
+ self.contacts.each do |contact|
24
+ cell = contact.cell
25
+ template = ERB.new File.new("sms.erb").read, nil, "%"
26
+ message = "template.result(self.issue)"
27
+
28
+ # send message to sms-bridge
29
+ socket = TCPSocket.new Notifu::CONFIG[:actors][:gammu_sms_bridge][:host], Notifu::CONFIG[:actors][:gammu_sms_bridge][port]
30
+ socket.send contact.cell.to_s + "--" + message
31
+ socket.close
32
+ socket = nil
33
+ end
34
+ end
35
+
36
+ def template
37
+ "<%= data[:status] %> [<%= data[:host] %>/<%= data[:service] %>]: (<%= data[:message] %>) <%= data[:duration] %> [<%= data[:notifu_id] %>]"
38
+ end
39
+ end
40
+ end
41
+ end
File without changes
@@ -0,0 +1,29 @@
1
+ module Notifu
2
+ module Actors
3
+ class SlackChan < Notifu::Actor
4
+
5
+ require 'excon'
6
+ require 'erb'
7
+
8
+ self.name = "slack_msg"
9
+ self.desc = "Sends message to a Slack contact"
10
+ self.retry = 3
11
+
12
+
13
+ def act
14
+ cfg = Notifu::CONFIG[:actors][:slack]
15
+ contacts = self.contacts.map { |contact| contact.cell }
16
+ req_string = Notifu::CONFIG[:actors][:twilio_call][:api] +
17
+ "?token=" + Notifu::CONFIG[:actors][:twilio_call][:token] +
18
+ "&status=" + self.issue.code.to_state +
19
+ "&hostname=" + self.issue.host +
20
+ "&service=" + self.issue.service +
21
+ "&description=" + ERB::Util.url_encode(self.issue.message.to_s) +
22
+ "&call_group=" + ERB::Util.url_encode(contacts.to_json) +
23
+ "&init=1"
24
+ Excon.get req_string if self.issue.code.to_i == 2
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Notifu
2
+ module Actors
3
+ class SlackMsg < Notifu::Actor
4
+
5
+ require 'excon'
6
+ require 'erb'
7
+
8
+ self.name = "slack_msg"
9
+ self.desc = "Sends message to a Slack contact"
10
+ self.retry = 3
11
+
12
+
13
+ def act
14
+ cfg = Notifu::CONFIG[:actors][:slack]
15
+ contacts = self.contacts.map { |contact| contact.cell }
16
+ req_string = Notifu::CONFIG[:actors][:twilio_call][:api] +
17
+ "?token=" + Notifu::CONFIG[:actors][:twilio_call][:token] +
18
+ "&status=" + self.issue.code.to_state +
19
+ "&hostname=" + self.issue.host +
20
+ "&service=" + self.issue.service +
21
+ "&description=" + ERB::Util.url_encode(self.issue.message.to_s) +
22
+ "&call_group=" + ERB::Util.url_encode(contacts.to_json) +
23
+ "&init=1"
24
+ Excon.get req_string if self.issue.code.to_i == 2
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,73 @@
1
+ module Notifu
2
+ module Actors
3
+ class Smtp < Notifu::Actor
4
+
5
+ require 'ostruct'
6
+ require 'mail'
7
+
8
+ self.name = "smtp"
9
+ self.desc = "SMTP notifier"
10
+ self.retry = 2
11
+
12
+ def act
13
+ data = OpenStruct.new({
14
+ notifu_id: self.issue.notifu_id,
15
+ host: self.issue.host,
16
+ message: self.issue.message,
17
+ service: self.issue.service,
18
+ status: self.issue.code.to_state,
19
+ first_event: Time.at(self.issue.time_created.to_i),
20
+ duration: (Time.now.to_i - self.issue.time_created.to_i).duration,
21
+ occurrences_count: self.issue.occurrences_count,
22
+ occurrences_trigger: self.issue.occurrences_trigger
23
+ })
24
+ contacts = self.contacts.map { |contact| "#{contact.full_name} <#{contact.mail}>"}
25
+ text_message = ERB.new(self.text_template).result(data.instance_eval {binding})
26
+ html_message = ERB.new(self.html_template).result(data.instance_eval {binding})
27
+ mail = Mail.new do
28
+ from Notifu::CONFIG[:actors][:smtp][:from]
29
+ subject "#{data[:status]}/#{data[:host]}/#{data[:service]}"
30
+ to contacts
31
+ text_part do
32
+ body text_message
33
+ end
34
+ html_part do
35
+ content_type 'text/html; charset=UTF-8'
36
+ body html_message
37
+ end
38
+ end
39
+ mail.delivery_method :sendmail
40
+ mail.deliver
41
+ end
42
+
43
+ def text_template
44
+ %{
45
+ <%= data[:message] %>
46
+
47
+ Notifu ID: <%= data[:notifu_id] %>
48
+ Host: <%= data[:host] %>
49
+ Service: <%= data[:service] %>
50
+ Status: <%= data[:status] %>
51
+ First event: <%= Time.at(data[:first_event]).to_s %>
52
+ Duration: <%= data[:duration] %>
53
+ Occurences: <%= data[:occurrences_count] %>/<%= data[:occurrences_trigger] %> (occured/trigger)
54
+ }
55
+ end
56
+
57
+ def html_template
58
+ %{
59
+ <h3><%= data[:message] %></h3><br/>
60
+
61
+ <strong>Notifu ID: </strong><%= data[:notifu_id] %><br/>
62
+ <strong>Host: </strong><%= data[:host] %><br/>
63
+ <strong>Service: </strong><%= data[:service] %><br/>
64
+ <strong>Status: </strong><%= data[:status] %><br/>
65
+ <strong>First event: </strong><%= Time.at(data[:first_event]).to_s %><br/>
66
+ <strong>Duration: </strong><%= data[:duration] %><br/>
67
+ <strong>Occurences: </strong><%= data[:occurrences_count] %>/<%= data[:occurrences_trigger] %> (occured/trigger)<br/>
68
+ }
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,16 @@
1
+ module Notifu
2
+ module Actors
3
+ class Stdout < Notifu::Actor
4
+
5
+ self.name = "stdout"
6
+ self.desc = "STDOUT notifier, useful for debug only"
7
+ self.retry = 0
8
+
9
+ def act
10
+ puts self.issue.to_yaml
11
+ puts self.contacts.to_yaml
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ module Notifu
2
+ module Actors
3
+ class TwilioCall < Notifu::Actor
4
+
5
+ require 'excon'
6
+ require 'erb'
7
+
8
+ self.name = "twilio_call"
9
+ self.desc = "POST requst to trigger phone-call"
10
+ self.retry = 2
11
+
12
+ def act
13
+ contacts = self.contacts.map { |contact| contact.cell }
14
+ req_string = Notifu::CONFIG[:actors][:twilio_call][:api] +
15
+ "?token=" + Notifu::CONFIG[:actors][:twilio_call][:token] +
16
+ "&status=" + self.issue.code.to_state +
17
+ "&hostname=" + self.issue.host +
18
+ "&service=" + self.issue.service +
19
+ "&description=" + ERB::Util.url_encode(self.issue.message.to_s) +
20
+ "&call_group=" + ERB::Util.url_encode(contacts.to_json) +
21
+ "&init=1"
22
+ Excon.get req_string if self.issue.code.to_i == 2
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ module Notifu
2
+ module CLI
3
+ class Root < Thor
4
+ package_name "Notifu"
5
+
6
+ desc "object SUBCOMMAND", "Runtime configuration object management (SLAs, contacts & groups)"
7
+ subcommand "object", Object
8
+
9
+ desc "service SUBCOMMAND", "Notifu service processes"
10
+ subcommand "service", Service
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,37 @@
1
+ module Notifu
2
+ module CLI
3
+ class Object < Thor
4
+ package_name "Notifu object configuration"
5
+ ##
6
+ # DB Sync task
7
+ #
8
+ desc "sync", "Syncs locally defined config objects with DB"
9
+ def sync
10
+ puts "Syncing data with Redis..."
11
+ Notifu::Config.new.ohm_init
12
+ puts "...done"
13
+ end
14
+
15
+ ##
16
+ # Configure SLA objects
17
+ #
18
+ desc "sla ACTION", "Manage SLAs"
19
+ def sla(name)
20
+ end
21
+
22
+ ##
23
+ # Configure contact objects
24
+ #
25
+ desc "contact ACTION", "Manage contacts"
26
+ def contact(name)
27
+ end
28
+
29
+ ##
30
+ # Configure group objects
31
+ #
32
+ desc "group ACTION", "Manage groups"
33
+ def group(name)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,53 @@
1
+ module Notifu
2
+ module CLI
3
+ class Service < Thor
4
+ package_name "Notifu service"
5
+ ##
6
+ # API Service
7
+ #
8
+ desc "api", "Starts Notifu API"
9
+ def api
10
+ # Notifu::API.start
11
+ end
12
+
13
+ ##
14
+ # Processor Service
15
+ #
16
+ desc "processor", "Starts Notifu processor"
17
+ option :concurrency, :type => :numeric, :default => 2, :aliases => :c
18
+ def processor
19
+ Process.setproctitle "notifu-processor"
20
+ puts "Starting #{options[:concurrency].to_s} processor(s)"
21
+ puts( $sidekiq_bin + " -c " + options[:concurrency].to_s + " -r " + $basepath + "workers/processor.rb -q processor" )
22
+ system( $sidekiq_bin + " -c " + options[:concurrency].to_s + " -r " + $basepath + "workers/processor.rb -q processor" )
23
+ end
24
+
25
+ ##
26
+ # Actor Service
27
+ #
28
+ desc "actor", "Starts Notifu actor"
29
+ option :actor, :type => :string, :default => nil, :aliases => :a
30
+ option :concurrency, :type => :numeric, :default => 1, :aliases => :c
31
+ def actor
32
+ if ! options[:actor]
33
+ puts "No actor name specified (-a <actor_name>)! Available actors:"
34
+ Dir[$actorpath + "*.rb"].each do |name|
35
+ puts name.gsub(/.*\/([a-zA-Z0-9_]+)\.rb/, " \\1")
36
+ end
37
+ else
38
+ if File.exists?($actorpath + options[:actor] + ".rb") then
39
+ Process.setproctitle "notifu-actor [#{options[:actor]}]"
40
+ puts "Starting #{options[:concurrency].to_s} '#{options[:actor]}' actor(s)"
41
+ puts( $sidekiq_bin + " exec sidekiq -c " + options[:concurrency].to_s + " -r " + $basepath + "workers/actor.rb -q actor-" + options[:actor])
42
+ system( $sidekiq_bin + " exec sidekiq -c " + options[:concurrency].to_s + " -r " + $basepath + "workers/actor.rb -q actor-" + options[:actor])
43
+ exit 0
44
+ else
45
+ STDERR.puts "Actor '#{options[:actor]}' does not exist"
46
+ exit 1
47
+ end
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,120 @@
1
+ module Notifu
2
+ class Config
3
+
4
+ attr_reader :config
5
+
6
+ @@config_path = "/etc/notifu/"
7
+
8
+ def initialize
9
+ begin
10
+ @config = YAML.load_file(@@config_path + 'notifu.yaml')
11
+ rescue
12
+ raise "Failed to load main config file!"
13
+ end
14
+ end
15
+
16
+ def get
17
+ @get ||= self.config.deep_symbolize_keys
18
+ end
19
+
20
+ def ohm_init
21
+ contacts_init
22
+ slas_init
23
+ groups_init
24
+ end
25
+
26
+ def contacts_init
27
+ Dir[@@config_path + 'contacts/*.yaml'].each do |path|
28
+ cfg = YAML.load_file(path).deep_symbolize_keys
29
+ begin
30
+ Notifu::Model::Contact.with(:name, cfg[:name]).update(cfg)
31
+ puts "Updated contact '#{cfg[:name]}'."
32
+ rescue
33
+ Notifu::Model::Contact.create(cfg).save
34
+ puts "Created contact '#{cfg[:name]}'."
35
+ end
36
+ end
37
+ end
38
+
39
+ def slas_init
40
+ Dir[@@config_path + 'slas/*.yaml'].each do |path|
41
+ cfg = YAML.load_file(path).deep_symbolize_keys
42
+ begin
43
+ Notifu::Model::Sla.with(:name, cfg[:name]).update(cfg)
44
+ puts "Updated SLA '#{cfg[:name]}'."
45
+ rescue
46
+ Notifu::Model::Sla.create(cfg).save
47
+ puts "Created SLA '#{cfg[:name]}'."
48
+ end
49
+ end
50
+ end
51
+
52
+ def groups_init
53
+ Dir[@@config_path + 'groups/*.yaml'].each do |path|
54
+ cfg = YAML.load_file(path).deep_symbolize_keys
55
+ begin
56
+ group = Notifu::Model::Group.create(name: cfg[:name])
57
+ puts "Created group '#{cfg[:name]}'."
58
+ rescue
59
+ group = Notifu::Model::Group.with(:name, cfg[:name])
60
+ puts "Found group '#{cfg[:name]}'."
61
+ end
62
+
63
+ contacts = Array.new
64
+
65
+ cfg[:primary].each do |contact_id|
66
+ begin
67
+ contacts << Notifu::Model::Contact.with(:name, contact_id)
68
+ puts "Contact '#{contact_id}' accepted as primary."
69
+ rescue
70
+ puts "Failed to load primary contact '#{contact_id}'."
71
+ end
72
+ end
73
+
74
+ group.primary.replace(contacts)
75
+ group.save
76
+ puts "Primary contacts for group '#{cfg[:name]}' updated."
77
+
78
+ if cfg[:secondary].is_a? Array
79
+ contacts = Array.new
80
+
81
+ cfg[:secondary].each do |contact_id|
82
+ begin
83
+ contacts << Notifu::Model::Contact.with(:name, contact_id)
84
+ puts "Contact '#{contact_id}' accepted as secondary."
85
+ rescue
86
+ puts "Failed to load secondary contact '#{contact_id}'."
87
+ exit 1
88
+ end
89
+ end
90
+
91
+ group.secondary.replace(contacts)
92
+ group.save
93
+ puts "Secondary contacts for group '#{cfg[:name]}' updated."
94
+
95
+ if cfg[:tertiary].is_a? Array
96
+ contacts = Array.new
97
+
98
+ cfg[:tertiary].each do |contact_id|
99
+ begin
100
+ contacts << Notifu::Model::Contact.with(:name, contact_id)
101
+ puts "Contact '#{contact_id}' accepted as tertiary."
102
+ rescue
103
+ puts "Failed to load tertiary contact '#{contact_id}'."
104
+ exit 1
105
+ end
106
+ end
107
+
108
+ group.tertiary.replace(contacts)
109
+ group.save
110
+ puts "Tertiary contacts for group '#{cfg[:name]}' updated."
111
+ else
112
+ group.tertiary.replace([])
113
+ end
114
+ else
115
+ group.secondary.replace([])
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end