wakame-dolphin 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +4 -0
  4. data/.travis.yml +25 -0
  5. data/Gemfile +18 -0
  6. data/Makefile +56 -0
  7. data/README.md +77 -0
  8. data/Rakefile +67 -0
  9. data/bin/dolphin_server +98 -0
  10. data/config/db/cassandra_clear.txt +1 -0
  11. data/config/db/cassandra_schema.txt +14 -0
  12. data/config/db/sequel/migrations/0001_add_notification.rb +15 -0
  13. data/config/db/sequel/migrations/0002_add_event.rb +15 -0
  14. data/config/dolphin-mysql.conf.travis +26 -0
  15. data/config/dolphin.conf.example +26 -0
  16. data/lib/dolphin.rb +148 -0
  17. data/lib/dolphin/data_store.rb +55 -0
  18. data/lib/dolphin/data_stores/base_rdb.rb +57 -0
  19. data/lib/dolphin/data_stores/cassandra.rb +98 -0
  20. data/lib/dolphin/data_stores/mysql.rb +31 -0
  21. data/lib/dolphin/helpers/message/zabbix_helper.rb +16 -0
  22. data/lib/dolphin/helpers/request_helper.rb +72 -0
  23. data/lib/dolphin/mailer.rb +83 -0
  24. data/lib/dolphin/manager.rb +35 -0
  25. data/lib/dolphin/message_builder.rb +98 -0
  26. data/lib/dolphin/models/base.rb +8 -0
  27. data/lib/dolphin/models/cassandra/base.rb +11 -0
  28. data/lib/dolphin/models/cassandra/event.rb +42 -0
  29. data/lib/dolphin/models/cassandra/notification.rb +28 -0
  30. data/lib/dolphin/models/rdb/base.rb +12 -0
  31. data/lib/dolphin/models/rdb/event.rb +47 -0
  32. data/lib/dolphin/models/rdb/notification.rb +27 -0
  33. data/lib/dolphin/models/rdb/orm/base.rb +10 -0
  34. data/lib/dolphin/models/rdb/orm/event.rb +8 -0
  35. data/lib/dolphin/models/rdb/orm/notification.rb +8 -0
  36. data/lib/dolphin/query_processor.rb +50 -0
  37. data/lib/dolphin/request_handler.rb +150 -0
  38. data/lib/dolphin/sender.rb +47 -0
  39. data/lib/dolphin/util.rb +18 -0
  40. data/lib/dolphin/version.rb +3 -0
  41. data/lib/dolphin/worker.rb +149 -0
  42. data/script/console +13 -0
  43. data/spec/files/cassandra_models_spec.rb +127 -0
  44. data/spec/files/dolphin_spec.rb +110 -0
  45. data/spec/files/endpoint/event_spec.rb +123 -0
  46. data/spec/files/endpoint/notification_spec.rb +54 -0
  47. data/spec/files/message_builder_spec.rb +15 -0
  48. data/spec/helpers/test_helper.rb +21 -0
  49. data/spec/helpers/web_request_helper.rb +40 -0
  50. data/spec/spec_helper.rb +18 -0
  51. data/templates/email/alert_port.erb +24 -0
  52. data/templates/email/default.erb +3 -0
  53. data/tests/test_dolphin +10 -0
  54. data/tests/test_get_event +31 -0
  55. data/tests/test_get_notification +27 -0
  56. data/tests/test_post_event +37 -0
  57. data/tests/test_post_notification +43 -0
  58. data/wakame-dolphin.gemspec +40 -0
  59. metadata +311 -0
@@ -0,0 +1,150 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'reel/app'
4
+ require 'extlib/blank'
5
+
6
+ module Dolphin
7
+ class RequestHandler
8
+ include Reel::App
9
+ include Dolphin::Util
10
+ include Dolphin::Helpers::RequestHelper
11
+
12
+ GET_EVENT_LIMIT = 30.freeze
13
+
14
+ def initialize(host, port)
15
+
16
+ # TODO: Fix Celluloid.logger loading order.
17
+ logger :info, "Load settings in #{Dolphin.config}"
18
+
19
+ @server = Reel::Server.supervise_as(:reques_handler, host, port) do |connection|
20
+
21
+ while request = connection.request
22
+ begin
23
+ logger :info, {
24
+ :host => request.headers["Host"],
25
+ :user_agent => request.headers["User-Agent"]
26
+ }
27
+ options = {
28
+ :method => request.method,
29
+ :input => request.body
30
+ }
31
+ options.merge!(request.headers)
32
+ status, headers_or_body, body = call Rack::MockRequest.env_for(request.url, options)
33
+ connection.respond status_symbol(status), headers_or_body, body.to_s
34
+ rescue => e
35
+ logger :error, e
36
+ break
37
+ end
38
+ end
39
+ end
40
+ logger :info, "Running on ruby #{RUBY_VERSION} with selected #{Celluloid::task_class}"
41
+ logger :info, "Listening on http://#{host}:#{port}"
42
+ @server
43
+ end
44
+
45
+ post '/events' do |request|
46
+ run(request) do
47
+
48
+ raise 'Nothing parameters.' if @params.blank?
49
+
50
+ event = {}
51
+ event[:notification_id] = @notification_id
52
+ event[:message_type] = @message_type
53
+ event[:messages] = @params
54
+
55
+ events = worker.future.put_event(event)
56
+
57
+ # always success because put_event is async action.
58
+ response_params = {
59
+ :message => 'OK'
60
+ }
61
+ respond_with response_params
62
+ end
63
+ end
64
+
65
+ get '/events' do |request|
66
+ run(request) do
67
+
68
+ limit = @params['limit'].blank? ? GET_EVENT_LIMIT : @params['limit'].to_i
69
+ raise "Requested over the limit. Limited to #{GET_EVENT_LIMIT}" if limit > GET_EVENT_LIMIT
70
+
71
+ params = {}
72
+ params[:count] = limit
73
+ params[:start_time] = parse_time(@params['start_time']) unless @params['start_time'].blank?
74
+ params[:start_id] = @params['start_id'] unless @params['start_id'].blank?
75
+
76
+ events = worker.get_event(params)
77
+ raise events.message if events.fail?
78
+
79
+ response_params = {
80
+ :results => events.message,
81
+ :message => 'OK'
82
+ }
83
+ response_params[:start_time] = @params['start_time'] unless @params['start_time'].blank?
84
+ respond_with response_params
85
+ end
86
+ end
87
+
88
+ get '/notifications' do |request|
89
+ run(request) do
90
+ required 'notification_id'
91
+
92
+ notification = {}
93
+ notification[:id] = @notification_id
94
+
95
+ result = worker.get_notification(notification)
96
+ raise result.message if result.fail?
97
+ raise "Not found notification id" if result.message.nil?
98
+
99
+ response_params = {
100
+ :results => result.message,
101
+ :message => 'OK'
102
+ }
103
+ respond_with response_params
104
+ end
105
+ end
106
+
107
+ post '/notifications' do |request|
108
+ run(request) do
109
+ required 'notification_id'
110
+ raise 'Nothing parameters.' if @params.blank?
111
+
112
+ unsupported_sender_types = @params.keys - Sender::TYPES
113
+ raise "Unsuppoted sender types: #{unsupported_sender_types.join(',')}" unless unsupported_sender_types.blank?
114
+
115
+ notification = {}
116
+ notification[:id] = @notification_id
117
+ notification[:methods] = @params
118
+ result = worker.put_notification(notification)
119
+ raise result.message if result.fail?
120
+
121
+ response_params = {
122
+ :message => 'OK'
123
+ }
124
+ respond_with response_params
125
+ end
126
+ end
127
+
128
+ delete '/notifications' do |request|
129
+ run(request) do
130
+ required 'notification_id'
131
+
132
+ notification = {}
133
+ notification[:id] = @notification_id
134
+
135
+ result = worker.delete_notification(notification)
136
+ raise result.message if result.fail?
137
+
138
+ response_params = {
139
+ :message => 'OK'
140
+ }
141
+ respond_with response_params
142
+ end
143
+ end
144
+
145
+ private
146
+ def worker
147
+ Celluloid::Actor[:workers]
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,47 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'celluloid'
4
+ require 'extlib/blank'
5
+ require 'time'
6
+
7
+ module Dolphin
8
+ module Sender
9
+ TYPES = ['email'].freeze
10
+
11
+ TYPE = [:mail_senders].freeze
12
+
13
+ class Mail
14
+ include Celluloid
15
+ include Dolphin::Util
16
+
17
+ def notify(notification_object)
18
+ time_now = DateTime.now.strftime('%a, %d %b %Y %H:%M:%S %z')
19
+ send_params = {
20
+ :from => notification_object.from,
21
+ :to => notification_object.to,
22
+ :subject => notification_object.subject,
23
+ :body => notification_object.body,
24
+ :date => time_now,
25
+ :event_id => notification_object.event_id
26
+ }
27
+
28
+ unless notification_object.to.blank?
29
+ send_params[:cc] = notification_object.cc
30
+ end
31
+
32
+ unless notification_object.bcc.blank?
33
+ send_params[:bcc] = notification_object.bcc
34
+ end
35
+
36
+ logger :info, send_params
37
+ begin
38
+ Mailer.notify(send_params)
39
+ logger :info, "Success Sent message"
40
+ rescue => e
41
+ logger :error, e.message
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'celluloid'
4
+
5
+ module Dolphin
6
+ module Util
7
+ include Celluloid::Logger
8
+
9
+ def logger(type, message)
10
+ message = {
11
+ :message => message,
12
+ :classname => self.class.name,
13
+ :thread_id => Thread.current.object_id
14
+ }
15
+ Celluloid.logger.__send__(type, message)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Dolphin
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,149 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'extlib/blank'
4
+
5
+ module Dolphin
6
+ class Worker
7
+ include Celluloid
8
+ include Dolphin::Util
9
+
10
+ def put_event(event_object)
11
+ logger :info, "Worker put events #{event_object}"
12
+
13
+ notification_id = event_object[:notification_id]
14
+ message_template_id = event_object[:message_type]
15
+
16
+ future_event = query_processor.future.put_event(event_object)
17
+
18
+ # if notification_id not exists, doesn't send notification.
19
+ unless notification_id
20
+ return SuccessObject.new
21
+ end
22
+
23
+ future_notification = query_processor.future.get_notification(notification_id)
24
+
25
+ # synchronized
26
+ notifications = future_notification.value
27
+ event_id = future_event.value
28
+ if notifications.nil?
29
+ log_message = "Not found notification: #{event_object[:notification_id]}"
30
+ logger :error, log_message
31
+ return FailureObject.new(log_message)
32
+ end
33
+
34
+ if query_processor_failed?(notifications)
35
+ return FailureObject.new('Failed to get notifications')
36
+ end
37
+
38
+ notifications.each do |sender_type, values|
39
+ if values.blank?
40
+ logger :info, "Skip to notify message because notifications was blank."
41
+ next
42
+ end
43
+
44
+ unless Sender::TYPES.include? sender_type
45
+ log_message = "Not found sender #{sender_type}"
46
+ logger :error, log_message
47
+ # Does not do response to Request Handler.
48
+ next
49
+ end
50
+
51
+ build_params = {}
52
+ # TODO: Plugin
53
+ case sender_type
54
+ when 'email'
55
+ build_params["to"] = values['to']
56
+ build_params["cc"] = values['cc']
57
+ build_params["bcc"] = values['bcc']
58
+ build_params["messages"] = event_object[:messages]
59
+ end
60
+
61
+ message = build_message(sender_type, message_template_id, build_params)
62
+ message.event_id = event_id
63
+
64
+ if message.nil?
65
+ log_message = "Failed to build message: #{message}"
66
+ logger :error, log_message
67
+ # Does not do response to Request Handler.
68
+ next
69
+ end
70
+
71
+ logger :info, "Send notification from Worker #{message}"
72
+
73
+ begin
74
+ send_notification(sender_type, message)
75
+ rescue => e
76
+ logger :error, e
77
+ # Does not do response to Request Handler.
78
+ next
79
+ end
80
+ end
81
+
82
+ SuccessObject.new
83
+ end
84
+
85
+ def get_event(params)
86
+ event = query_processor.get_event(params)
87
+ if query_processor_failed?(event)
88
+ return FailureObject.new('Failed to get events')
89
+ end
90
+ SuccessObject.new(event)
91
+ end
92
+
93
+ def get_notification(notification)
94
+ notification_id = notification[:id]
95
+ notification = query_processor.get_notification(notification_id)
96
+ if query_processor_failed?(notification)
97
+ return FailureObject.new('Failed to get notification')
98
+ end
99
+ SuccessObject.new(notification)
100
+ end
101
+
102
+ def put_notification(notification)
103
+ notification = query_processor.put_notification(notification)
104
+ if query_processor_failed?(notification)
105
+ return FailureObject.new('Failed to put notification')
106
+ end
107
+ SuccessObject.new(notification)
108
+ end
109
+
110
+ def delete_notification(notification)
111
+ notification = query_processor.delete_notification(notification)
112
+ if query_processor_failed?(notification)
113
+ return FailureObject.new('Failed to delete notification')
114
+ end
115
+ SuccessObject.new(notification)
116
+ end
117
+
118
+ private
119
+ def query_processor_failed?(response_data)
120
+ response_data === FALSE
121
+ end
122
+
123
+ def query_processor
124
+ Celluloid::Actor[:query_processors]
125
+ end
126
+
127
+ def sender(type)
128
+ Celluloid::Actor[type]
129
+ end
130
+
131
+ def send_notification(type, log_message)
132
+ case type
133
+ when 'email'
134
+ sender(:mail_senders).notify(log_message)
135
+ else
136
+ raise "Unsuppoted sender type: #{type}"
137
+ end
138
+ end
139
+
140
+ def build_message(type, template_id, params)
141
+ case type
142
+ when 'email'
143
+ MessageBuilder::Mail.new.build(template_id, params)
144
+ else
145
+ nil
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ begin
5
+ require "rubygems"
6
+ require "bundler/setup"
7
+ rescue LoadError => e
8
+ end
9
+
10
+ require File.join(File.expand_path('../../', __FILE__), 'lib/dolphin')
11
+
12
+ require 'irb'
13
+ IRB.start
@@ -0,0 +1,127 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'Test Dolphin::Models for Cassandra' do
6
+ before(:all) do
7
+ @connection = Dolphin::DataStore::Cassandra.new(
8
+ :keyspace => 'dolphin_test',
9
+ :hosts => Dolphin.settings['database']['hosts'],
10
+ :port => Dolphin.settings['database']['port']
11
+ )
12
+ @connection.connect
13
+ end
14
+
15
+ describe Dolphin::Models::Cassandra::Event do
16
+ before(:all) do
17
+ if @connection.closed?
18
+ pending "Cassandra doens't exist"
19
+ else
20
+ @event_values = []
21
+ @event_values << {
22
+ 'notification_id' => "system",
23
+ 'message_type' => "alert_port",
24
+ 'messages' => {
25
+ "message"=>"Alert!!!!"
26
+ }
27
+ }
28
+
29
+ @column_name = SimpleUUID::UUID.new(Time.now).to_guid
30
+ @connection.connect.insert(
31
+ Dolphin::Models::Cassandra::Event::COLUMN_FAMILY,
32
+ Dolphin::Models::Cassandra::Event::ROW_KEY,
33
+ {@column_name => MultiJson.dump(@event_values)}
34
+ )
35
+ end
36
+ end
37
+
38
+ describe ".get" do
39
+ let(:message) {
40
+ res = @connection.get_event({:count=>1})
41
+ message = res[0]
42
+ }
43
+
44
+ it "expect to get message id" do
45
+ expect(message['id']).to eql SimpleUUID::UUID.new(message['id']).to_guid
46
+ end
47
+
48
+ it "expect to get message values" do
49
+ expect(message['event']).to eql @event_values
50
+ end
51
+
52
+ it "expect to get message created_at formated by ISO8601" do
53
+ expect(Time.iso8601(message['created_at'])).to be_instance_of Time
54
+ end
55
+ end
56
+
57
+ describe '.put' do
58
+ it "expect to put success" do
59
+ event_id = @connection.put_event(@event_values[0])
60
+ expect(SimpleUUID::UUID.new(event_id)).to be_a SimpleUUID::UUID
61
+ event_data = @connection.get_event({
62
+ :count => 1,
63
+ :start_id => SimpleUUID::UUID.new(event_id)
64
+ })[0]
65
+ expect(event_id).to eql event_data['id']
66
+ end
67
+ end
68
+ end
69
+
70
+ context Dolphin::Models::Cassandra::Notification do
71
+
72
+ before(:all) do
73
+ if @connection.closed?
74
+ pending "Cassandra doens't exist"
75
+ else
76
+ @notification_values = {
77
+ "email"=> {
78
+ "to" => "foo@example.com,bar@example.com",
79
+ "cc" => "foo@example.com,bar@example.com",
80
+ "bcc" =>"foofoo@example.com,barbar@example.com"
81
+ }
82
+ }
83
+ @row_key = 'system'
84
+ @connection.connect.insert('notifications', @row_key, {
85
+ 'methods' => MultiJson.dump(@notification_values)
86
+ })
87
+ end
88
+ end
89
+
90
+ let(:notification_data) do
91
+ @connection.get_notification(@row_key)
92
+ end
93
+
94
+ describe '.get' do
95
+ it "expect to the same values before created" do
96
+ expect(notification_data).to eql @notification_values
97
+ end
98
+ end
99
+
100
+ describe '.put' do
101
+ let(:notification_new_data) do
102
+ @connection.put_notification(@row_key, @notification_values)
103
+ end
104
+
105
+ it "expect to put success" do
106
+ expect(notification_new_data).to be_nil
107
+
108
+ notification_data = @connection.get_notification(@row_key)
109
+ expect(notification_data).to eql @notification_values
110
+ end
111
+ end
112
+
113
+ describe '.delete' do
114
+ it "expect to delete success" do
115
+ @connection.put_notification(@row_key, @notification_values)
116
+ notification_new_data = @connection.get_notification(@row_key)
117
+ expect(notification_new_data).to eql @notification_values
118
+
119
+ deleted_notification = @connection.delete_notification(@row_key)
120
+ expect(deleted_notification).to be_nil
121
+
122
+ notification_data = @connection.get_notification(@row_key)
123
+ expect(notification_data).to be_nil
124
+ end
125
+ end
126
+ end
127
+ end