comsat 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +20 -2
- data/Rakefile +8 -2
- data/comsat.gemspec +7 -3
- data/lib/comsat/helpers/auth_helper.rb +28 -0
- data/lib/comsat/log.rb +16 -0
- data/lib/comsat/route.rb +23 -0
- data/lib/comsat/service.rb +15 -0
- data/lib/comsat/services/campfire.rb +33 -0
- data/lib/comsat/services/pagerduty.rb +31 -0
- data/lib/comsat/version.rb +1 -1
- data/lib/comsat.rb +50 -75
- data/spec/client_spec.rb +39 -0
- data/spec/service_spec.rb +10 -0
- data/spec/spec_helper.rb +6 -0
- metadata +56 -11
data/README.md
CHANGED
@@ -14,6 +14,19 @@ for Campfire might look like:
|
|
14
14
|
The schema name maps to the service name, the rest we pass to the service to
|
15
15
|
deal with.
|
16
16
|
|
17
|
+
## Routes
|
18
|
+
|
19
|
+
Routes allow the user to create aliases for contacting one or more services
|
20
|
+
for a specific event. An event is one of 'notice', 'alert' or 'resolve'.
|
21
|
+
Routes should be named according to their function, and initially are not
|
22
|
+
stored longer than a session, but will eventually be created and reside on
|
23
|
+
the server.
|
24
|
+
|
25
|
+
It is our intention to start developing usage patterns consistent with our
|
26
|
+
defined design goals.
|
27
|
+
|
28
|
+
The examples below show how routes are created.
|
29
|
+
|
17
30
|
## Messages
|
18
31
|
|
19
32
|
Messages should be one of three types, 'notice', 'alert', 'resolve'.
|
@@ -56,8 +69,13 @@ Or install it yourself as:
|
|
56
69
|
## Usage
|
57
70
|
|
58
71
|
```
|
59
|
-
client = Comsat::Client.new
|
60
|
-
client.
|
72
|
+
client = Comsat::Client.new
|
73
|
+
client.create_route("notify_on_exception", "notice", ["campfire://<api_key>:X@blossom.campfirenow.com/Test%20Room"])
|
74
|
+
client.notify("notify_on_exception", {
|
75
|
+
:message => "Exception reached in #function",
|
76
|
+
:source => "my_app",
|
77
|
+
:message_id => "exception-#{rand(1_000)}"
|
78
|
+
})
|
61
79
|
```
|
62
80
|
|
63
81
|
## Contributing
|
data/Rakefile
CHANGED
data/comsat.gemspec
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
require File.expand_path('../lib/comsat/version', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
|
-
gem.authors = ["
|
5
|
+
gem.authors = ["Curt Micol", "Michael Gorsuch"]
|
6
6
|
gem.email = ["ops@heroku.com"]
|
7
|
-
gem.description = "
|
8
|
-
gem.summary = "
|
7
|
+
gem.description = "Notifications as a Gem"
|
8
|
+
gem.summary = "Notifications as a Gem"
|
9
9
|
gem.homepage = ""
|
10
10
|
|
11
11
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
@@ -16,5 +16,9 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = Comsat::VERSION
|
17
17
|
|
18
18
|
gem.add_runtime_dependency('rest-client')
|
19
|
+
gem.add_runtime_dependency('scrolls')
|
19
20
|
gem.add_runtime_dependency('tinder')
|
21
|
+
|
22
|
+
gem.add_development_dependency('rake')
|
23
|
+
gem.add_development_dependency('rspec')
|
20
24
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Comsat
|
6
|
+
module AuthHelper
|
7
|
+
|
8
|
+
def self.parse(url)
|
9
|
+
parse_url(url)
|
10
|
+
OpenStruct.new(to_hash)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.parse_url(url)
|
14
|
+
@uri = URI.parse(url)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.to_hash
|
18
|
+
{
|
19
|
+
:name => @uri.scheme,
|
20
|
+
:api_key => @uri.user,
|
21
|
+
:username => @uri.user,
|
22
|
+
:password => @uri.password,
|
23
|
+
:host => @uri.host,
|
24
|
+
:scope => CGI.unescape(@uri.path.gsub(/\A\//, ''))
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/comsat/log.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Comsat
|
2
|
+
module Log
|
3
|
+
def self.start
|
4
|
+
Scrolls::Log.start
|
5
|
+
log(ns: "log", fn: "start")
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.merge(data1, data2)
|
9
|
+
data1.merge(data2)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.log(data, &blk)
|
13
|
+
Scrolls.log(merge({app: "comsat"}, data), &blk)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/comsat/route.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Comsat
|
2
|
+
class Route
|
3
|
+
attr_accessor :name, :services, :event_type
|
4
|
+
|
5
|
+
def initialize(route, et, urls)
|
6
|
+
@name = route
|
7
|
+
@event_type = et if %w(alert notice resolve).include?(et)
|
8
|
+
@services = []
|
9
|
+
urls.each do |url|
|
10
|
+
svc = ServiceFactory.create(url)
|
11
|
+
if svc.respond_to?("send_#{@event_type}")
|
12
|
+
@services << svc
|
13
|
+
else
|
14
|
+
next
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"#<#{self.class} @name='#{@name}', @event='#{@event_type}', @services=#{@services.each {|s| s.to_s }}>"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Comsat
|
2
|
+
module Service
|
3
|
+
class Base
|
4
|
+
attr_reader :credentials
|
5
|
+
|
6
|
+
def initialize(url)
|
7
|
+
@credentials = Comsat::AuthHelper.parse(url)
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
"#<#{self.class} @host='#{@credentials.host}', @scope='#{@credentials.scope}'>"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Comsat
|
2
|
+
class Campfire < Service::Base
|
3
|
+
def send_notice(data)
|
4
|
+
# {:messages, :source, :message_id}
|
5
|
+
messages = []
|
6
|
+
messages << "[#{data[:source]}] #{data[:message]}"
|
7
|
+
send_message(messages)
|
8
|
+
end
|
9
|
+
alias :send_alert :send_notice
|
10
|
+
alias :send_resolve :send_notice
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def send_message(msgs)
|
15
|
+
unless room = find_room
|
16
|
+
raise "Unable to find room"
|
17
|
+
end
|
18
|
+
Array(msgs).each {|line| room.speak line }
|
19
|
+
end
|
20
|
+
|
21
|
+
def campfire
|
22
|
+
@campfire = ::Tinder::Campfire.new(
|
23
|
+
@credentials.host.split('.')[0],
|
24
|
+
:ssl => true,
|
25
|
+
:token => @credentials.api_key
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_room
|
30
|
+
campfire.find_room_by_name(@credentials.scope)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Comsat
|
2
|
+
class PagerDuty < Service::Base
|
3
|
+
PAGERDUTY_ENDPOINT = 'https://events.pagerduty.com/generic/2010-04-15/create_event.json'
|
4
|
+
|
5
|
+
def send_notice(data)
|
6
|
+
contact_pagerduty(:trigger, data)
|
7
|
+
end
|
8
|
+
alias :send_alert :send_notice
|
9
|
+
|
10
|
+
def send_resolve(data)
|
11
|
+
contact_pagerduty(:resolve, data)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def contact_pagerduty(event_type, data)
|
17
|
+
id = data[:message_id] || SecureRandom.uuid
|
18
|
+
message = data[:message]
|
19
|
+
source = data[:source]
|
20
|
+
message = "#{source}: #{message}"
|
21
|
+
|
22
|
+
data = {
|
23
|
+
:service_key => @credentials.api_key,
|
24
|
+
:incident_key => id,
|
25
|
+
:event_type => event_type,
|
26
|
+
:description => message
|
27
|
+
}
|
28
|
+
RestClient.post PAGERDUTY_ENDPOINT, data.to_json, :content_type => :json
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/comsat/version.rb
CHANGED
data/lib/comsat.rb
CHANGED
@@ -1,107 +1,82 @@
|
|
1
1
|
require "cgi"
|
2
|
-
require "comsat/version"
|
3
2
|
require "json"
|
4
3
|
require "rest_client"
|
4
|
+
require "scrolls"
|
5
5
|
require "securerandom"
|
6
|
+
|
7
|
+
# Service includes
|
6
8
|
require "tinder"
|
7
9
|
|
10
|
+
require "comsat/log"
|
11
|
+
require "comsat/route"
|
12
|
+
require "comsat/service"
|
13
|
+
require "comsat/version"
|
14
|
+
|
15
|
+
require "comsat/helpers/auth_helper"
|
16
|
+
|
17
|
+
require "comsat/services/campfire"
|
18
|
+
require "comsat/services/pagerduty"
|
19
|
+
|
8
20
|
module Comsat
|
9
21
|
class Client
|
10
|
-
def initialize(urls)
|
11
|
-
@urls = urls
|
12
|
-
end
|
13
22
|
|
14
|
-
|
15
|
-
@urls.each do |url|
|
16
|
-
ServiceFactory.create(url).send_notice(data)
|
17
|
-
end
|
18
|
-
end
|
23
|
+
attr_accessor :routes
|
19
24
|
|
20
|
-
def
|
21
|
-
|
22
|
-
ServiceFactory.create(url).send_alert(data)
|
23
|
-
end
|
25
|
+
def initialize
|
26
|
+
@@routes = []
|
24
27
|
end
|
25
28
|
|
26
|
-
def
|
27
|
-
|
28
|
-
ServiceFactory.create(url).send_resolve(data)
|
29
|
-
end
|
29
|
+
def routes
|
30
|
+
@@routes
|
30
31
|
end
|
31
|
-
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
case uri.scheme
|
37
|
-
when 'campfire'
|
38
|
-
Campfire.new(uri)
|
39
|
-
when 'pagerduty'
|
40
|
-
PagerDuty.new(uri)
|
33
|
+
def create_route(route, event_type, services)
|
34
|
+
unless routes.detect {|r| r.name == route }
|
35
|
+
routes << Route.new(route, event_type, services)
|
41
36
|
end
|
42
37
|
end
|
43
|
-
end
|
44
|
-
|
45
|
-
class Campfire
|
46
|
-
def initialize(uri)
|
47
|
-
@acct = uri.host.split('.')[0]
|
48
|
-
@api_key = uri.user
|
49
|
-
@room = CGI.unescape(uri.path.gsub(/\A\//, ''))
|
50
|
-
end
|
51
|
-
|
52
|
-
def send_notice(data)
|
53
|
-
# {:messages, :source, :message_id}
|
54
|
-
messages = []
|
55
|
-
messages << "[#{data[:source]}] #{data[:message]}"
|
56
|
-
send_message(messages)
|
57
|
-
end
|
58
|
-
alias :send_alert :send_notice
|
59
|
-
alias :send_resolve :send_notice
|
60
38
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
39
|
+
def notify(route, message={})
|
40
|
+
notify_route = @@routes.detect {|r| r.name == route } if message
|
41
|
+
event = notify_route.event_type
|
42
|
+
notify_route.services.each do |svc|
|
43
|
+
svc.send("send_#{event}".to_sym, message)
|
64
44
|
end
|
65
|
-
Array(msgs).each {|line| room.speak line }
|
66
45
|
end
|
67
46
|
|
68
|
-
def
|
69
|
-
|
70
|
-
@acct,
|
71
|
-
:ssl => true,
|
72
|
-
:token => @api_key
|
73
|
-
)
|
47
|
+
def send_notice(data)
|
48
|
+
send_event(:notice, data)
|
74
49
|
end
|
75
50
|
|
76
|
-
def
|
77
|
-
|
51
|
+
def send_alert(data)
|
52
|
+
send_event(:alert, data)
|
78
53
|
end
|
79
|
-
end
|
80
54
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
def initialize(uri)
|
85
|
-
@api_key = uri.user
|
55
|
+
def send_resolve(data)
|
56
|
+
send_event(:resolve, data)
|
86
57
|
end
|
87
58
|
|
88
|
-
|
89
|
-
id = data[:message_id] || SecureRandom.uuid
|
90
|
-
message = data[:message]
|
91
|
-
source = data[:source]
|
92
|
-
message = "#{source}: #{message}"
|
59
|
+
private
|
93
60
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
61
|
+
def send_event(event_type, data)
|
62
|
+
@urls.each do |url|
|
63
|
+
service = ServiceFactory.create(url)
|
64
|
+
if service.respond_to?("send_#{event_type}")
|
65
|
+
service.send("send_#{event_type}".to_sym, data)
|
66
|
+
else
|
67
|
+
next
|
68
|
+
end
|
69
|
+
end
|
100
70
|
end
|
101
|
-
|
71
|
+
end
|
102
72
|
|
103
|
-
|
104
|
-
|
73
|
+
class ServiceFactory
|
74
|
+
def self.create(url)
|
75
|
+
svc_name = URI.parse(url).scheme
|
76
|
+
if Comsat.const_defined?(svc_name.capitalize)
|
77
|
+
svc = Comsat.const_get(svc_name.capitalize)
|
78
|
+
svc.new(url)
|
79
|
+
end
|
105
80
|
end
|
106
81
|
end
|
107
82
|
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Comsat::Client do
|
4
|
+
subject { described_class.new }
|
5
|
+
let(:undefined_svc) { "svc://api_key:X@host/scope" }
|
6
|
+
let(:defined_svc) { "campfire://api_key:X@blossom.campfirenow.com/scope" }
|
7
|
+
|
8
|
+
describe "#routes" do
|
9
|
+
it "has zero routes configured by default" do
|
10
|
+
subject.routes.should be_empty
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#create_route" do
|
15
|
+
before do
|
16
|
+
subject.create_route("test_route", "notice", [undefined_svc, defined_svc])
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should register a route with base class" do
|
20
|
+
subject.routes.should_not be_empty
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should create a route" do
|
24
|
+
subject.routes.first.name.should == "test_route"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should have one service initiated" do
|
28
|
+
subject.routes.first.services.length.should == 1
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should have a campfire service initiated" do
|
32
|
+
subject.routes.first.services.first.class.should == Comsat::Campfire
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should provide an event type" do
|
36
|
+
subject.routes.first.event_type == "notice"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Comsat::Service::Base do
|
4
|
+
let(:unsupported) { "svc://api_key:X@host/scope" }
|
5
|
+
subject { described_class.new(unsupported) }
|
6
|
+
|
7
|
+
it "should provide credentials in an object" do
|
8
|
+
subject.credentials.class.should == OpenStruct
|
9
|
+
end
|
10
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: comsat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
|
-
-
|
9
|
-
-
|
8
|
+
- Curt Micol
|
9
|
+
- Michael Gorsuch
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-04-
|
13
|
+
date: 2012-04-11 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rest-client
|
17
|
-
requirement: &
|
17
|
+
requirement: &70287816065340 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,21 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70287816065340
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: scrolls
|
28
|
+
requirement: &70287816064720 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70287816064720
|
26
37
|
- !ruby/object:Gem::Dependency
|
27
38
|
name: tinder
|
28
|
-
requirement: &
|
39
|
+
requirement: &70287816064080 !ruby/object:Gem::Requirement
|
29
40
|
none: false
|
30
41
|
requirements:
|
31
42
|
- - ! '>='
|
@@ -33,8 +44,30 @@ dependencies:
|
|
33
44
|
version: '0'
|
34
45
|
type: :runtime
|
35
46
|
prerelease: false
|
36
|
-
version_requirements: *
|
37
|
-
|
47
|
+
version_requirements: *70287816064080
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rake
|
50
|
+
requirement: &70287816063540 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *70287816063540
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rspec
|
61
|
+
requirement: &70287816063020 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *70287816063020
|
70
|
+
description: Notifications as a Gem
|
38
71
|
email:
|
39
72
|
- ops@heroku.com
|
40
73
|
executables: []
|
@@ -48,7 +81,16 @@ files:
|
|
48
81
|
- Rakefile
|
49
82
|
- comsat.gemspec
|
50
83
|
- lib/comsat.rb
|
84
|
+
- lib/comsat/helpers/auth_helper.rb
|
85
|
+
- lib/comsat/log.rb
|
86
|
+
- lib/comsat/route.rb
|
87
|
+
- lib/comsat/service.rb
|
88
|
+
- lib/comsat/services/campfire.rb
|
89
|
+
- lib/comsat/services/pagerduty.rb
|
51
90
|
- lib/comsat/version.rb
|
91
|
+
- spec/client_spec.rb
|
92
|
+
- spec/service_spec.rb
|
93
|
+
- spec/spec_helper.rb
|
52
94
|
homepage: ''
|
53
95
|
licenses: []
|
54
96
|
post_install_message:
|
@@ -72,5 +114,8 @@ rubyforge_project:
|
|
72
114
|
rubygems_version: 1.8.11
|
73
115
|
signing_key:
|
74
116
|
specification_version: 3
|
75
|
-
summary:
|
76
|
-
test_files:
|
117
|
+
summary: Notifications as a Gem
|
118
|
+
test_files:
|
119
|
+
- spec/client_spec.rb
|
120
|
+
- spec/service_spec.rb
|
121
|
+
- spec/spec_helper.rb
|